Commit Diff
Diff:
97d17c71276689b26f75a9a61e915c6f15041599
df34d218f6fdd4bb64d6a1fa7c551726bbccfcb3
Commit:
df34d218f6fdd4bb64d6a1fa7c551726bbccfcb3
Tree:
82d12cf708db243bcc7f6eed5cf56455f718cbd7
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Mon Apr 21 19:26:15 2014 UTC
Message:
* SSHFP support (RR# 44) RFC 4255 This supports SHA1 and SHA256 fingerprints * instead of replying from an area on the stack, move it to the heap This fixes truncation between udp and tcp queries. Tested on OpenBSD
blob - 58dababdeb89314adb351c89a9e64403aecd032d
blob + b6d98f01ef13cec9acfc5713f6e2b509f67433c8
--- db.h
+++ db.h
@@ -71,11 +71,18 @@ struct srv {
int targetlen; /* SRV target name length */
} __attribute__((packed));
+struct sshfp {
+ u_int8_t algorithm; /* SSHFP algorithm */
+ u_int8_t fptype; /* SSHFP fingerprint type */
+ char fingerprint[DNS_MAXNAME]; /* fingerprint */
+ int fplen; /* fingerprint length */
+} __attribute__((packed));
+
struct domain {
char zone[DNS_MAXNAME]; /* name of zone in dns name format */
int zonelen; /* length of zone, above */
char zonename[DNS_MAXNAME + 1]; /* name of zone in human readable */
- u_int16_t flags; /* flags of zone */
+ u_int32_t flags; /* flags of zone */
#define DOMAIN_HAVE_A 0x1
#define DOMAIN_HAVE_SOA 0x2
#define DOMAIN_HAVE_CNAME 0x4
@@ -88,6 +95,7 @@ struct domain {
#define DOMAIN_NEGATIVE_CACHE 0x200
#define DOMAIN_HAVE_SRV 0x400
#define DOMAIN_HAVE_SPF 0x800
+#define DOMAIN_HAVE_SSHFP 0x1000
struct soa soa; /* start of authority */
u_int32_t ttl; /* time to live */
time_t created; /* time created, for dynamic zones */
@@ -107,16 +115,18 @@ struct domain {
int ns_type; /* set if it's a delegation */
#define NS_TYPE_DELEGATE 0x1
#define NS_TYPE_HINT 0x2
- char cname[DNS_MAXNAME]; /* CNAME RR */
- int cnamelen; /* len of CNAME */
- char ptr[DNS_MAXNAME]; /* PTR RR */
- int ptrlen; /* len of PTR */
- char txt[DNS_MAXNAME]; /* TXT string */
- int txtlen; /* len of TXT */
- char spf[DNS_MAXNAME]; /* SPF string */
- int spflen; /* len of SPF */
- struct srv srv[RECORD_COUNT]; /* SRV resource record */
- int srv_count; /* count of SRV resource record */
+ char cname[DNS_MAXNAME]; /* CNAME RR */
+ int cnamelen; /* len of CNAME */
+ char ptr[DNS_MAXNAME]; /* PTR RR */
+ int ptrlen; /* len of PTR */
+ char txt[DNS_MAXNAME]; /* TXT string */
+ int txtlen; /* len of TXT */
+ char spf[DNS_MAXNAME]; /* SPF string */
+ int spflen; /* len of SPF */
+ struct srv srv[RECORD_COUNT]; /* SRV resource record */
+ int srv_count; /* count of SRV RR */
+ struct sshfp sshfp[RECORD_COUNT]; /* SSHFP resource record */
+ int sshfp_count; /* SSHFP RR count */
} __attribute__((packed));
struct sreply {
@@ -132,6 +142,7 @@ struct sreply {
int istcp; /* when set it's tcp */
int wildcard; /* wildcarding boolean */
struct recurses *sr; /* recurses struct for raw sockets */
+ char *replybuf; /* reply buffer */
};
struct srecurseheader {
blob - f42af467b79f9f681a20380d074a0feefe8f3ee4
blob + 2f2c5265e2bfa9a52371ba1e0e0d05eeec8e8538
--- dns.h
+++ dns.h
@@ -136,6 +136,7 @@ struct dns_question_hdr {
#define DNS_TYPE_TXT 16
#define DNS_TYPE_SRV 33 /* RFC 2782, page 8 */
+#define DNS_TYPE_SSHFP 44 /* RFC 4255 */
#define DNS_TYPE_SPF 99 /* RFC 4408 */
@@ -167,6 +168,11 @@ struct dns_question_hdr {
#define DNS_MAXLABEL 63
#define DNS_MAXNAME 255
#define DNS_MAXUDP 512
+
+/* SSHFP fingerprint sizes */
+
+#define DNS_SSHFP_SIZE_SHA1 40
+#define DNS_SSHFP_SIZE_SHA256 64
struct question {
blob - 4291e6d8d66b522ff562789d5cc61fe6d02e4e9f
blob + 2f7b998d67e97db45553d07536eb732dcb3aa9d6
--- example8.conf
+++ example8.conf
@@ -32,6 +32,13 @@ zone "centroid.eu" {
centroid.eu,a,3600,200.46.208.61
centroid.eu,a,3600,62.75.160.180
;
+ centroid.eu,SSHFP,3600,1,1,"9b3624f96a6766e73dc88505f945a564dee82e59"
+ centroid.eu,SSHFP,3600,1,2,"03310030886404f8f61d2e4dc445412788284ab04d0858bfa375eb80fc0d34f6"
+ centroid.eu,SSHFP,3600,2,1,"3de1bbae4de5ebd3571a169a50d6a5a4145dd7a9"
+ centroid.eu,SSHFP,3600,2,2,"bbd96ff7e7f629377d655d7fa9662502837b66cf9a2d24590df77acef66fe405"
+ centroid.eu,SSHFP,3600,3,1,"0ca455de4800c0f6c681e805e7bd86e511efb1fc"
+ centroid.eu,SSHFP,3600,3,2,"b330fd2288cf9e13c9ef68b1b0c0b20a10c16cc55f03cd3869cf1a49f06bed43"
+ ;
centroid.eu,mx,3600,10,proteus.solarscale.de.
centroid.eu,aaaa,3600,2001:a60:f074::8
;
blob - 0dea2f3fd90eaf3897f0083e1a701aa6669f30cf
blob + 9c997f9558db784fdeebdea4265f2eb0bc067a15
--- main.c
+++ main.c
@@ -54,6 +54,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_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);
extern void init_wildcard(void);
@@ -71,7 +72,7 @@ char * dns_label(char *, int *);
int compress_label(u_char *, u_int16_t, int);
int memcasecmp(u_char *, u_char *, int);
char * get_dns_type(int dnstype);
-void build_reply(struct sreply *reply, int so, char *buf, int len, struct question *q, struct sockaddr *sa, socklen_t slen, struct domain *sd1, struct domain *sd2, u_int8_t region, int istcp, int wildcard, struct recurses *sr);
+void build_reply(struct sreply *reply, int so, char *buf, int len, struct question *q, struct sockaddr *sa, socklen_t slen, struct domain *sd1, struct domain *sd2, u_int8_t region, int istcp, int wildcard, struct recurses *sr, char *);
void recurseheader(struct srecurseheader *, int, struct sockaddr_storage *, struct sockaddr_storage *, int);
void setup_master(DB *, DB_ENV *, int, char **);
void master_shutdown(int);
@@ -104,6 +105,7 @@ struct typetable {
{ "ANY", DNS_TYPE_ANY },
{ "SRV", DNS_TYPE_SRV },
{ "SPF", DNS_TYPE_SPF },
+ { "SSHFP", DNS_TYPE_SSHFP },
{ NULL, 0}
};
@@ -154,7 +156,7 @@ struct tcps {
} *tn1, *tn2, *tnp;
-static const char rcsid[] = "$Id: main.c,v 1.84 2014/04/21 12:10:43 pjp Exp $";
+static const char rcsid[] = "$Id: main.c,v 1.85 2014/04/21 19:26:15 pjp Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -1400,6 +1402,21 @@ compress_label(u_char *buf, u_int16_t offset, int labe
p += *p;
p++;
break;
+ case DNS_TYPE_SSHFP:
+ p++;
+ switch (*p) {
+ case 1:
+ p += DNS_SSHFP_SIZE_SHA1 + 1;
+ break;
+ case 2:
+ p += DNS_SSHFP_SIZE_SHA256 + 1;
+ break;
+ default:
+ /* XXX */
+ goto end;
+ }
+
+ break;
case DNS_TYPE_SRV:
p += (2 * sizeof(u_int16_t)); /* priority, weight */
/* the port will be assumed in the fall through for
@@ -1720,6 +1737,15 @@ lookup_zone(DB *db, struct question *question, struct
returnval = DNS_TYPE_SOA;
break;
+ case DNS_TYPE_SSHFP:
+ if ((sd->flags & DOMAIN_HAVE_SSHFP) != DOMAIN_HAVE_SSHFP) {
+
+ *lzerrno = ERR_NOERROR;
+ return -1;
+ }
+ returnval = DNS_TYPE_SSHFP;
+ break;
+
case DNS_TYPE_SRV:
if ((sd->flags & DOMAIN_HAVE_SRV) != DOMAIN_HAVE_SRV) {
@@ -1883,6 +1909,15 @@ lookup_zone(DB *db, struct question *question, struct
returnval = DNS_TYPE_NS;
break;
+ case DNS_TYPE_SSHFP:
+ if ((sd->flags & DOMAIN_HAVE_SSHFP) != DOMAIN_HAVE_SSHFP) {
+
+ *lzerrno = ERR_NOERROR;
+ return -1;
+ }
+ returnval = DNS_TYPE_SSHFP;
+ break;
+
case DNS_TYPE_SRV:
if ((sd->flags & DOMAIN_HAVE_SRV) != DOMAIN_HAVE_SRV) {
@@ -2098,6 +2133,7 @@ mainloop(struct cfg *cfg)
char *pbuf;
char buf[4096];
+ char *replybuf = NULL;
char address[INET6_ADDRSTRLEN];
char replystring[DNS_MAXNAME + 1];
char fakereplystring[DNS_MAXNAME + 1];
@@ -2138,6 +2174,14 @@ mainloop(struct cfg *cfg)
SLIST_INIT(&tcpshead);
collects_init();
+ replybuf = calloc(1, 65536);
+ if (replybuf == NULL) {
+ dolog(LOG_ERR, "calloc: %s\n", strerror(errno));
+ slave_shutdown();
+ exit(1);
+ }
+
+
sp = cfg->recurse;
lfd = cfg->log;
@@ -2370,7 +2414,7 @@ mainloop(struct cfg *cfg)
/* format error */
build_reply( &sreply, tnp->so, pbuf, len, NULL,
from, fromlen, NULL, NULL, tnp->region,
- istcp, tnp->wildcard, NULL);
+ istcp, tnp->wildcard, NULL, replybuf);
reply_fmterror(&sreply);
dolog(LOG_INFO, "TCP question on descriptor %d interface \"%s\" from %s, did not have question of 1 replying format error\n", tnp->so, tnp->ident, tnp->address);
@@ -2415,7 +2459,7 @@ mainloop(struct cfg *cfg)
build_reply( &sreply, tnp->so, pbuf, len,
question, from, fromlen,
&sd0, NULL, tnp->region, istcp,
- tnp->wildcard, NULL);
+ tnp->wildcard, NULL, replybuf);
reply_noerror(&sreply);
goto tcpout;
@@ -2441,7 +2485,8 @@ tcpnxdomain:
build_reply( &sreply, tnp->so, pbuf, len, question,
from, fromlen, &sd0, NULL,
- tnp->region, istcp, tnp->wildcard, NULL);
+ tnp->region, istcp, tnp->wildcard, NULL,
+ replybuf);
reply_nxdomain(&sreply);
goto tcpout;
@@ -2475,7 +2520,7 @@ tcpnxdomain:
default:
build_reply( &sreply, tnp->so, pbuf, len, question,
from, fromlen, NULL, NULL, tnp->region,
- istcp, tnp->wildcard, NULL);
+ istcp, tnp->wildcard, NULL, replybuf);
reply_notimpl(&sreply);
snprintf(replystring, DNS_MAXNAME, "NOTIMPL");
@@ -2487,19 +2532,21 @@ tcpnxdomain:
if (type0 == DNS_TYPE_CNAME) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
fromlen, &sd0, ((type1 > 0) ? &sd1 : NULL), \
- tnp->region, istcp, tnp->wildcard, NULL);
+ tnp->region, istcp, tnp->wildcard, NULL, replybuf);
reply_cname(&sreply);
} else if (type0 == DNS_TYPE_NS) {
build_reply(&sreply, tnp->so, pbuf, len, question,
from, fromlen, &sd0, NULL,
- tnp->region, istcp, tnp->wildcard, NULL);
+ tnp->region, istcp, tnp->wildcard, NULL,
+ replybuf);
reply_ns(&sreply, cfg->db);
break;
} else if (type0 == DNS_TYPE_A) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard,
+ NULL, replybuf);
reply_a(&sreply, cfg->db);
break; /* must break here */
}
@@ -2508,7 +2555,9 @@ tcpnxdomain:
case DNS_TYPE_ANY:
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard,
+ NULL, replybuf);
+
reply_any(&sreply);
break; /* must break here */
@@ -2517,16 +2566,20 @@ tcpnxdomain:
if (type0 == DNS_TYPE_CNAME) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
fromlen, &sd0, ((type1 > 0) ? &sd1 : NULL), \
- tnp->region, istcp, tnp->wildcard, NULL);
+ tnp->region, istcp, tnp->wildcard, NULL, replybuf);
reply_cname(&sreply);
} else if (type0 == DNS_TYPE_NS) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
break;
} else if (type0 == DNS_TYPE_AAAA) {
build_reply(&sreply, tnp->so, pbuf, len, question, from,
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_aaaa(&sreply, cfg->db);
break; /* must break here */
}
@@ -2537,16 +2590,23 @@ tcpnxdomain:
if (type0 == DNS_TYPE_CNAME) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
fromlen, &sd0, ((type1 > 0) ? &sd1 : NULL), \
- tnp->region, istcp, tnp->wildcard, NULL);
+ tnp->region, istcp, tnp->wildcard, NULL, replybuf);
+
reply_cname(&sreply);
+
} else if (type0 == DNS_TYPE_NS) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
+
break;
} else if (type0 == DNS_TYPE_MX) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_mx(&sreply, cfg->db);
break; /* must break here */
}
@@ -2555,11 +2615,15 @@ tcpnxdomain:
case DNS_TYPE_SOA:
if (type0 == DNS_TYPE_SOA) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_soa(&sreply);
} else if (type0 == DNS_TYPE_NS) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
break;
}
@@ -2567,15 +2631,30 @@ tcpnxdomain:
case DNS_TYPE_NS:
if (type0 == DNS_TYPE_NS) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
}
break;
+ case DNS_TYPE_SSHFP:
+ if (type0 == DNS_TYPE_SSHFP) {
+ build_reply(&sreply, tnp->so, pbuf, len, question, from, \
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
+ reply_sshfp(&sreply);
+ }
+ break;
+
+
case DNS_TYPE_SRV:
if (type0 == DNS_TYPE_SRV) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_srv(&sreply, cfg->db);
}
break;
@@ -2585,11 +2664,15 @@ tcpnxdomain:
case DNS_TYPE_CNAME:
if (type0 == DNS_TYPE_CNAME) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_cname(&sreply);
} else if (type0 == DNS_TYPE_NS) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
break;
}
@@ -2599,16 +2682,26 @@ tcpnxdomain:
if (type0 == DNS_TYPE_CNAME) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
fromlen, &sd0, ((type1 > 0) ? &sd1 : NULL) \
- , tnp->region, istcp, tnp->wildcard, NULL);
+ , tnp->region, istcp, tnp->wildcard, NULL,
+ replybuf);
+
reply_cname(&sreply);
+
} else if (type0 == DNS_TYPE_NS) {
+
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
+
break;
} else if (type0 == DNS_TYPE_PTR) {
+
build_reply(&sreply, tnp->so, pbuf, len, question, from,
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_ptr(&sreply);
break; /* must break here */
}
@@ -2616,16 +2709,22 @@ tcpnxdomain:
case DNS_TYPE_TXT:
if (type0 == DNS_TYPE_TXT) {
+
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_txt(&sreply);
}
break;
case DNS_TYPE_SPF:
if (type0 == DNS_TYPE_SPF) {
+
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_spf(&sreply);
}
break;
@@ -2643,12 +2742,16 @@ tcpnxdomain:
if (type0 == DNS_TYPE_NS) {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, tnp->wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp,
+ tnp->wildcard, NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
+
} else {
build_reply(&sreply, tnp->so, pbuf, len, question, from, \
- fromlen, NULL, NULL, tnp->region, istcp, tnp->wildcard, NULL);
+ fromlen, NULL, NULL, tnp->region, istcp,
+ tnp->wildcard, NULL, replybuf);
reply_notimpl(&sreply);
snprintf(replystring, DNS_MAXNAME, "NOTIMPL");
@@ -2805,7 +2908,8 @@ axfrentry:
dolog(LOG_INFO, "on descriptor %u interface \"%s\" header from %s has no question, drop\n", so, cfg->ident[i], address);
/* format error */
- build_reply(&sreply, so, buf, len, NULL, from, fromlen, NULL, NULL, aregion, istcp, wildcard, NULL);
+ build_reply(&sreply, so, buf, len, NULL, from, fromlen, NULL, NULL, aregion, istcp, wildcard, NULL, replybuf);
+
reply_fmterror(&sreply);
dolog(LOG_INFO, "question on descriptor %d interface \"%s\" from %s, did not have question of 1 replying format error\n", so, cfg->ident[i], address);
goto drop;
@@ -2858,7 +2962,8 @@ axfrentry:
(void)get_soa(cfg->db, question, &sd0, wildcard);
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard,
+ NULL, replybuf);
reply_noerror(&sreply);
goto udpout;
@@ -2892,7 +2997,9 @@ udpnxdomain:
(void)get_soa(cfg->db, question, &sd0, wildcard);
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, \
+ wildcard, NULL, replybuf);
+
reply_nxdomain(&sreply);
goto udpout;
} /* else rflag */
@@ -2925,7 +3032,9 @@ udpnxdomain:
break;
default:
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, NULL, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, NULL, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_notimpl(&sreply);
snprintf(replystring, DNS_MAXNAME, "NOTIMPL");
goto udpout;
@@ -2934,18 +3043,26 @@ udpnxdomain:
switch (ntohs(question->hdr->qtype)) {
case DNS_TYPE_A:
if (type0 == DNS_TYPE_CNAME) {
+
build_reply(&sreply, so, buf, len, question, from, \
fromlen, &sd0, ((type1 > 0) ? &sd1 : NULL), \
- aregion, istcp, wildcard, NULL);
+ aregion, istcp, wildcard, NULL, replybuf);
+
reply_cname(&sreply);
} else if (type0 == DNS_TYPE_NS) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
break;
} else if (type0 == DNS_TYPE_A) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard,
+ NULL, replybuf);
+
reply_a(&sreply, cfg->db);
break; /* must break here */
}
@@ -2953,26 +3070,37 @@ udpnxdomain:
break;
case DNS_TYPE_ANY:
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL,
+ replybuf);
+
reply_any(&sreply);
break; /* must break here */
case DNS_TYPE_AAAA:
if (type0 == DNS_TYPE_CNAME) {
+
build_reply(&sreply, so, buf, len, question, from, \
fromlen, &sd0, ((type1 > 0) ? &sd1 : NULL), \
- aregion, istcp, wildcard, NULL);
+ aregion, istcp, wildcard, NULL, replybuf);
+
reply_cname(&sreply);
} else if (type0 == DNS_TYPE_NS) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
break;
} else if (type0 == DNS_TYPE_AAAA) {
+
build_reply(&sreply, so, buf, len, question, from,
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard,
+ NULL, replybuf);
+
reply_aaaa(&sreply, cfg->db);
break; /* must break here */
}
@@ -2981,18 +3109,24 @@ udpnxdomain:
case DNS_TYPE_MX:
if (type0 == DNS_TYPE_CNAME) {
+
build_reply(&sreply, so, buf, len, question, from, \
fromlen, &sd0, ((type1 > 0) ? &sd1 : NULL), \
- aregion, istcp, wildcard, NULL);
+ aregion, istcp, wildcard, NULL, replybuf);
+
reply_cname(&sreply);
- } else if (type0 == DNS_TYPE_NS) {
+ } else if (type0 == DNS_TYPE_NS) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
break;
} else if (type0 == DNS_TYPE_MX) {
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
reply_mx(&sreply, cfg->db);
break; /* must break here */
}
@@ -3000,40 +3134,69 @@ udpnxdomain:
break;
case DNS_TYPE_SOA:
if (type0 == DNS_TYPE_SOA) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_soa(&sreply);
} else if (type0 == DNS_TYPE_NS) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
break;
}
break;
case DNS_TYPE_NS:
if (type0 == DNS_TYPE_NS) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
}
break;
+ case DNS_TYPE_SSHFP:
+ if (type0 == DNS_TYPE_SSHFP) {
+ build_reply(&sreply, so, buf, len, question, from, \
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
+ reply_sshfp(&sreply);
+ }
+ break;
+
+
case DNS_TYPE_SRV:
if (type0 == DNS_TYPE_SRV) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_srv(&sreply, cfg->db);
}
break;
case DNS_TYPE_CNAME:
if (type0 == DNS_TYPE_CNAME) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_cname(&sreply);
} else if (type0 == DNS_TYPE_NS) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
break;
}
@@ -3041,33 +3204,47 @@ udpnxdomain:
case DNS_TYPE_PTR:
if (type0 == DNS_TYPE_CNAME) {
+
build_reply(&sreply, so, buf, len, question, from, \
fromlen, &sd0, ((type1 > 0) ? &sd1 : NULL) \
- , aregion, istcp, wildcard, NULL);
+ , aregion, istcp, wildcard, NULL, replybuf);
+
reply_cname(&sreply);
} else if (type0 == DNS_TYPE_NS) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
break;
} else if (type0 == DNS_TYPE_PTR) {
+
build_reply(&sreply, so, buf, len, question, from,
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_ptr(&sreply);
break; /* must break here */
}
break;
case DNS_TYPE_TXT:
if (type0 == DNS_TYPE_TXT) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_txt(&sreply);
}
break;
case DNS_TYPE_SPF:
if (type0 == DNS_TYPE_SPF) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_spf(&sreply);
}
break;
@@ -3081,14 +3258,19 @@ udpnxdomain:
*/
if (type0 == DNS_TYPE_NS) {
+
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, &sd0, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_ns(&sreply, cfg->db);
} else {
build_reply(&sreply, so, buf, len, question, from, \
- fromlen, NULL, NULL, aregion, istcp, wildcard, NULL);
+ fromlen, NULL, NULL, aregion, istcp, wildcard, \
+ NULL, replybuf);
+
reply_notimpl(&sreply);
snprintf(replystring, DNS_MAXNAME, "NOTIMPL");
}
@@ -3139,7 +3321,7 @@ udpnxdomain:
*/
void
-build_reply(struct sreply *reply, int so, char *buf, int len, struct question *q, struct sockaddr *sa, socklen_t slen, struct domain *sd1, struct domain *sd2, u_int8_t region, int istcp, int wildcard, struct recurses *sr)
+build_reply(struct sreply *reply, int so, char *buf, int len, struct question *q, struct sockaddr *sa, socklen_t slen, struct domain *sd1, struct domain *sd2, u_int8_t region, int istcp, int wildcard, struct recurses *sr, char *replybuf)
{
reply->so = so;
reply->buf = buf;
@@ -3153,6 +3335,7 @@ build_reply(struct sreply *reply, int so, char *buf, i
reply->istcp = istcp;
reply->wildcard = wildcard;
reply->sr = sr;
+ reply->replybuf = replybuf;
return;
}
blob - 5848fca5cd26084d40f851a2d51a1287d9423420
blob + 573a03a8e7eb42874273f078ff0d966013fb41ce
--- parse.y
+++ parse.y
@@ -58,7 +58,7 @@ typedef struct {
int lineno;
} YYSTYPE;
-static const char rcsid[] = "$Id: parse.y,v 1.13 2014/04/21 12:10:43 pjp Exp $";
+static const char rcsid[] = "$Id: parse.y,v 1.14 2014/04/21 19:26:15 pjp Exp $";
static int version = 0;
static int state = 0;
static uint8_t region = 0;
@@ -111,6 +111,7 @@ int fill_aaaa(char *name, char *type, int myttl, char
int fill_a(char *name, char *type, int myttl, char *a);
int fill_balance(char *name, char *type, int myttl, char *a);
int fill_mx(char *name, char *type, int myttl, int priority, char *mxhost);
+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_spf(char *name, char *type, int myttl, char *msg);
@@ -341,6 +342,24 @@ zonestatement:
free ($9);
}
|
+ STRING COMMA STRING COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA QUOTEDSTRING CRLF
+ {
+ if (strcasecmp($3, "sshfp") == 0) {
+ if (fill_sshfp($1, $3, $5, $7, $9, $11) < 0) {
+ return -1;
+ }
+
+ } else {
+ if (debug)
+ printf("another sshfp record I don't know about?");
+ return (-1);
+ }
+
+ free ($1);
+ free ($3);
+ free ($11);
+ }
+ |
STRING COMMA STRING COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA STRING CRLF
{
if (strcasecmp($3, "srv") == 0) {
@@ -958,6 +977,7 @@ struct rrtab {
{ "balance", DNS_TYPE_BALANCE },
{ "srv", DNS_TYPE_SRV },
{ "spf", DNS_TYPE_SPF },
+ { "sshfp", DNS_TYPE_SSHFP },
{ NULL, 0 },
};
@@ -1612,6 +1632,76 @@ fill_txt(char *name, char *type, int myttl, char *msg)
sdomain.txtlen = len;
sdomain.flags |= DOMAIN_HAVE_TXT;
+
+ set_record(&sdomain, converted_name, converted_namelen);
+
+ if (converted_name)
+ free (converted_name);
+
+ return (0);
+
+}
+
+/* based on fill_srv */
+int
+fill_sshfp(char *name, char *type, int myttl, int alg, int fptype, char *fingerprint)
+{
+ struct domain sdomain;
+ int converted_namelen;
+ char *converted_name;
+ int len, i;
+
+ for (i = 0; i < strlen(name); i++) {
+ name[i] = tolower(name[i]);
+ }
+
+ converted_name = check_rr(name, type, DNS_TYPE_SSHFP, &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;
+
+ if (sdomain.sshfp_count >= RECORD_COUNT) {
+ dolog(LOG_INFO, "%s: too many SSHFP records for zone \"%s\", skipping line %d\n", file->name, name, file->lineno);
+ return (-1);
+ }
+
+ sdomain.ttl = myttl;
+
+ sdomain.sshfp[sdomain.sshfp_count].algorithm = alg;
+ sdomain.sshfp[sdomain.sshfp_count].fptype = fptype;
+
+ switch (fptype) {
+ case 1:
+ len = sdomain.sshfp[sdomain.sshfp_count].fplen = DNS_SSHFP_SIZE_SHA1;
+ break;
+ case 2:
+ len = sdomain.sshfp[sdomain.sshfp_count].fplen = DNS_SSHFP_SIZE_SHA256;
+ break;
+ default:
+ dolog(LOG_ERR, "sshfp: unknown fingerprint type!\n");
+ return -1;
+ }
+
+ memcpy((char *)&sdomain.sshfp[sdomain.sshfp_count].fingerprint, fingerprint, len);
+
+
+ sdomain.sshfp_count++;
+
+ sdomain.flags |= DOMAIN_HAVE_SSHFP;
set_record(&sdomain, converted_name, converted_namelen);
blob - 04318a7d97307b5824df84f4c52e16454c1b2969
blob + dbd18a81f481d5deaca9cb0e9523bec755998872
--- reply.c
+++ reply.c
@@ -40,6 +40,8 @@ void reply_soa(struct sreply *);
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_sshfp(struct sreply *);
void reply_cname(struct sreply *);
void reply_any(struct sreply *);
void reply_fmterror(struct sreply *);
@@ -84,7 +86,7 @@ struct collects {
extern int debug, verbose;
-static const char rcsid[] = "$Id: reply.c,v 1.52 2014/04/21 12:28:25 pjp Exp $";
+static const char rcsid[] = "$Id: reply.c,v 1.53 2014/04/21 19:26:15 pjp Exp $";
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
@@ -94,7 +96,7 @@ static const char rcsid[] = "$Id: reply.c,v 1.52 2014/
void
reply_a(struct sreply *sreply, DB *db)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
u_int16_t outlen;
int a_count;
@@ -122,16 +124,21 @@ reply_a(struct sreply *sreply, DB *db)
u_int8_t region = sreply->region;
int istcp = sreply->istcp;
+ int replysize = 512;
+ if (istcp) {
+ replysize = 65535;
+ }
+
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ 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);
@@ -256,7 +263,7 @@ out:
void
reply_aaaa(struct sreply *sreply, DB *db)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
u_int16_t outlen;
int aaaa_count;
@@ -281,17 +288,22 @@ reply_aaaa(struct sreply *sreply, DB *db)
int salen = sreply->salen;
struct domain *sd = sreply->sd1;
int istcp = sreply->istcp;
+ int replysize = 512;
+
+ if (istcp) {
+ replysize = 65535;
+ }
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ 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);
@@ -390,7 +402,7 @@ out:
void
reply_mx(struct sreply *sreply, DB *db)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
struct domain *sd0;
int mx_count;
@@ -421,17 +433,22 @@ reply_mx(struct sreply *sreply, DB *db)
struct domain *sd = sreply->sd1;
int istcp = sreply->istcp;
int wildcard = sreply->wildcard;
+ int replysize = 512;
+
+ if (istcp) {
+ replysize = 65535;
+ }
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ 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);
@@ -526,11 +543,11 @@ reply_mx(struct sreply *sreply, DB *db)
switch (cnp->type) {
case DNS_TYPE_A:
- tmplen = additional_a(cnp->name, cnp->namelen, cnp->sd, reply, sizeof(reply), outlen, &addcount);
+ 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, sizeof(reply), outlen, &addcount);
+ tmplen = additional_aaaa(cnp->name, cnp->namelen, cnp->sd, reply, replysize, outlen, &addcount);
additional += addcount;
break;
}
@@ -587,7 +604,7 @@ out:
void
reply_ns(struct sreply *sreply, DB *db)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
struct domain *sd0;
int tmplen;
@@ -619,20 +636,21 @@ reply_ns(struct sreply *sreply, DB *db)
struct domain *sd = sreply->sd1;
int istcp = sreply->istcp;
int wildcard = sreply->wildcard;
-
-#if 0
- memset(&reply, 0, sizeof(reply));
-#endif
+ int replysize = 512;
+ if (istcp) {
+ replysize = 65535;
+ }
+
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
memset((char *)&odh->query, 0, sizeof(u_int16_t));
@@ -759,11 +777,11 @@ reply_ns(struct sreply *sreply, DB *db)
switch (cnp->type) {
case DNS_TYPE_A:
- tmplen = additional_a(cnp->name, cnp->namelen, cnp->sd, reply, sizeof(reply), outlen, &addcount);
+ 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, sizeof(reply), outlen, &addcount);
+ tmplen = additional_aaaa(cnp->name, cnp->namelen, cnp->sd, reply, replysize, outlen, &addcount);
additional += addcount;
break;
}
@@ -827,7 +845,7 @@ out:
void
reply_cname(struct sreply *sreply)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
u_int16_t outlen;
char *p;
@@ -857,17 +875,21 @@ reply_cname(struct sreply *sreply)
struct domain *sd = sreply->sd1;
struct domain *sd1 = sreply->sd2;
int istcp = sreply->istcp;
-
+ int replysize = 512;
+ if (istcp) {
+ replysize = 65535;
+ }
+
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
/* copy question to reply */
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
/* blank query */
memset((char *)&odh->query, 0, sizeof(u_int16_t));
@@ -909,14 +931,14 @@ reply_cname(struct sreply *sreply)
plabel = label;
/* copy label to reply */
- for (i = outlen; i < sizeof(reply); i++) {
+ for (i = outlen; i < replysize; i++) {
if (i - outlen == labellen)
break;
reply[i] = *plabel++;
}
- if (i >= sizeof(reply))
+ if (i >= replysize)
return ;
outlen = i;
@@ -931,7 +953,7 @@ reply_cname(struct sreply *sreply)
if (ntohs(q->hdr->qtype) == DNS_TYPE_A && sd1 != NULL) {
- tmplen = additional_a(sd->cname, sd->cnamelen, sd1, reply, sizeof(reply), outlen, &addcount);
+ tmplen = additional_a(sd->cname, sd->cnamelen, sd1, reply, replysize, outlen, &addcount);
if (tmplen > 0)
outlen = tmplen;
@@ -940,7 +962,7 @@ reply_cname(struct sreply *sreply)
odh->answer += addcount;
HTONS(odh->answer);
} else if (ntohs(q->hdr->qtype) == DNS_TYPE_AAAA && sd1 != NULL) {
- tmplen = additional_aaaa(sd->cname, sd->cnamelen, sd1, reply, sizeof(reply), outlen, &addcount);
+ tmplen = additional_aaaa(sd->cname, sd->cnamelen, sd1, reply, replysize, outlen, &addcount);
if (tmplen > 0)
outlen = tmplen;
@@ -949,7 +971,7 @@ reply_cname(struct sreply *sreply)
odh->answer += addcount;
HTONS(odh->answer);
} else if (ntohs(q->hdr->qtype) == DNS_TYPE_MX && sd1 != NULL) {
- tmplen = additional_mx(sd->cname, sd->cnamelen, sd1, reply, sizeof(reply), outlen, &addcount);
+ tmplen = additional_mx(sd->cname, sd->cnamelen, sd1, reply, replysize, outlen, &addcount);
if (tmplen > 0)
outlen = tmplen;
@@ -958,7 +980,7 @@ reply_cname(struct sreply *sreply)
odh->answer += addcount;
HTONS(odh->answer);
} else if (ntohs(q->hdr->qtype) == DNS_TYPE_PTR && sd1 != NULL) {
- tmplen = additional_ptr(sd->cname, sd->cnamelen, sd1, reply, sizeof(reply), outlen, &addcount);
+ tmplen = additional_ptr(sd->cname, sd->cnamelen, sd1, reply, replysize, outlen, &addcount);
if (tmplen > 0)
outlen = tmplen;
@@ -1005,7 +1027,7 @@ reply_cname(struct sreply *sreply)
void
reply_ptr(struct sreply *sreply)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
u_int16_t outlen;
char *p;
@@ -1032,17 +1054,22 @@ reply_ptr(struct sreply *sreply)
int salen = sreply->salen;
struct domain *sd = sreply->sd1;
int istcp = sreply->istcp;
+ int replysize = 512;
+
+ if (istcp) {
+ replysize = 65535;
+ }
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
/* copy question to reply */
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
/* blank query */
memset((char *)&odh->query, 0, sizeof(u_int16_t));
@@ -1083,14 +1110,14 @@ reply_ptr(struct sreply *sreply)
plabel = label;
/* copy label to reply */
- for (i = outlen; i < sizeof(reply); i++) {
+ for (i = outlen; i < replysize; i++) {
if (i - outlen == labellen)
break;
reply[i] = *plabel++;
}
- if (i >= sizeof(reply)) {
+ if (i >= replysize) {
return ;
}
@@ -1142,7 +1169,7 @@ reply_ptr(struct sreply *sreply)
void
reply_soa(struct sreply *sreply)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
u_int16_t outlen;
char *p;
@@ -1181,18 +1208,23 @@ reply_soa(struct sreply *sreply)
int salen = sreply->salen;
struct domain *sd = sreply->sd1;
int istcp = sreply->istcp;
+ int replysize = 512;
+
+ if (istcp) {
+ replysize = 65535;
+ }
/* st */
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
/* copy question to reply */
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
/* blank query */
memset((char *)&odh->query, 0, sizeof(u_int16_t));
@@ -1234,14 +1266,14 @@ reply_soa(struct sreply *sreply)
plabel = label;
/* copy label to reply */
- for (i = outlen; i < sizeof(reply); i++) {
+ for (i = outlen; i < replysize; i++) {
if (i - outlen == labellen)
break;
reply[i] = *plabel++;
}
- if (i >= sizeof(reply)) {
+ if (i >= replysize) {
return ;
}
@@ -1256,14 +1288,14 @@ reply_soa(struct sreply *sreply)
labellen = sd->soa.rp_len;
plabel = label;
- for (i = outlen; i < sizeof(reply); i++) {
+ for (i = outlen; i < replysize; i++) {
if (i - outlen == labellen)
break;
reply[i] = *plabel++;
}
- if (i >= sizeof(reply)) {
+ if (i >= replysize) {
return ;
}
@@ -1277,7 +1309,7 @@ reply_soa(struct sreply *sreply)
/* XXX */
- if ((outlen + sizeof(sd->soa.serial)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.serial)) > replysize) {
/* XXX server error reply? */
return;
}
@@ -1286,28 +1318,28 @@ reply_soa(struct sreply *sreply)
outlen += sizeof(sd->soa.serial); /* XXX */
/* XXX */
- if ((outlen + sizeof(sd->soa.refresh)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.refresh)) > replysize) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
*soa_val = htonl(sd->soa.refresh);
outlen += sizeof(sd->soa.refresh); /* XXX */
- if ((outlen + sizeof(sd->soa.retry)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.retry)) > replysize) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
*soa_val = htonl(sd->soa.retry);
outlen += sizeof(sd->soa.retry); /* XXX */
- if ((outlen + sizeof(sd->soa.expire)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.expire)) > replysize) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
*soa_val = htonl(sd->soa.expire);
outlen += sizeof(sd->soa.expire);
- if ((outlen + sizeof(sd->soa.minttl)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.minttl)) > replysize) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
@@ -1355,7 +1387,7 @@ reply_soa(struct sreply *sreply)
void
reply_spf(struct sreply *sreply)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
u_int16_t outlen;
char *p;
@@ -1379,18 +1411,23 @@ reply_spf(struct sreply *sreply)
int salen = sreply->salen;
struct domain *sd = sreply->sd1;
int istcp = sreply->istcp;
+ int replysize = 512;
+
+ if (istcp) {
+ replysize = 65535;
+ }
/* st */
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
/* copy question to reply */
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
/* blank query */
memset((char *)&odh->query, 0, sizeof(u_int16_t));
@@ -1470,7 +1507,7 @@ reply_spf(struct sreply *sreply)
void
reply_txt(struct sreply *sreply)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
u_int16_t outlen;
char *p;
@@ -1494,18 +1531,23 @@ reply_txt(struct sreply *sreply)
int salen = sreply->salen;
struct domain *sd = sreply->sd1;
int istcp = sreply->istcp;
+ int replysize = 512;
+
+ if (istcp) {
+ replysize = 65535;
+ }
/* st */
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
/* copy question to reply */
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
/* blank query */
memset((char *)&odh->query, 0, sizeof(u_int16_t));
@@ -1576,7 +1618,153 @@ reply_txt(struct sreply *sreply)
return;
}
+/*
+ * REPLY_SSHFP() - replies a DNS question (*q) on socket (so)
+ * (based on reply_srv)
+ */
+
+void
+reply_sshfp(struct sreply *sreply)
+{
+ char *reply = sreply->replybuf;
+ struct dns_header *odh;
+ int sshfp_count;
+ u_int16_t *plen;
+ u_int16_t outlen;
+
+ struct answer {
+ char name[2];
+ u_int16_t type;
+ u_int16_t class;
+ u_int32_t ttl;
+ u_int16_t rdlength; /* 12 */
+ u_int8_t sshfp_alg;
+ u_int8_t sshfp_type;
+ char target;
+ } __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 typelen = 0;
+ int replysize = 512;
+
+ if (istcp) {
+ replysize = 65535;
+ }
+
+
+ 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->sshfp_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);
+
+ sshfp_count = 0;
+ do {
+ 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);
+
+ switch (sd->sshfp[sshfp_count].fptype) {
+ case 1:
+ typelen = DNS_SSHFP_SIZE_SHA1;
+ break;
+ case 2:
+ typelen = DNS_SSHFP_SIZE_SHA256;
+ break;
+ default:
+ dolog(LOG_ERR, "oops bad sshfp type? not returning a packet!\n");
+ return;
+ }
+
+ answer->rdlength = htons((2 * sizeof(u_int8_t)) + typelen);
+ answer->sshfp_alg = sd->sshfp[sshfp_count].algorithm;
+ answer->sshfp_type = sd->sshfp[sshfp_count].fptype;
+
+ 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) {
+ NTOHS(odh->query);
+ SET_DNS_TRUNCATION(odh);
+ HTONS(odh->query);
+ goto out;
+ }
+
+ /* set new offset for answer */
+ outlen += (12 + 2 + sd->sshfp[sshfp_count].fplen);
+ answer = (struct answer *)&reply[outlen];
+ } while (++sshfp_count < RECORD_COUNT && --sd->sshfp_count);
+
+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)
@@ -1586,7 +1774,7 @@ reply_txt(struct sreply *sreply)
void
reply_srv(struct sreply *sreply, DB *db)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
struct domain *sd0;
int srv_count;
@@ -1619,17 +1807,22 @@ reply_srv(struct sreply *sreply, DB *db)
struct domain *sd = sreply->sd1;
int istcp = sreply->istcp;
int wildcard = sreply->wildcard;
+ int replysize = 512;
+
+ if (istcp) {
+ replysize = 65535;
+ }
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ 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);
@@ -1727,11 +1920,11 @@ reply_srv(struct sreply *sreply, DB *db)
switch (cnp->type) {
case DNS_TYPE_A:
- tmplen = additional_a(cnp->name, cnp->namelen, cnp->sd, reply, sizeof(reply), outlen, &addcount);
+ 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, sizeof(reply), outlen, &addcount);
+ tmplen = additional_aaaa(cnp->name, cnp->namelen, cnp->sd, reply, replysize, outlen, &addcount);
additional += addcount;
break;
}
@@ -1790,7 +1983,7 @@ out:
void
reply_notimpl(struct sreply *sreply)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
u_int16_t outlen;
@@ -1800,7 +1993,12 @@ reply_notimpl(struct sreply *sreply)
struct sockaddr *sa = sreply->sa;
int salen = sreply->salen;
int istcp = sreply->istcp;
+ int replysize = 512;
+ if (istcp) {
+ replysize = 65535;
+ }
+
#if 0
struct domain *sd = sreply->sd1;
struct question *q = sreply->q;
@@ -1810,11 +2008,11 @@ reply_notimpl(struct sreply *sreply)
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
- memcpy(&reply, buf, len);
+ memcpy(reply, buf, len);
memset((char *)&odh->query, 0, sizeof(u_int16_t));
@@ -1858,7 +2056,7 @@ reply_notimpl(struct sreply *sreply)
void
reply_nxdomain(struct sreply *sreply)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
u_int16_t outlen;
char *p;
@@ -1897,11 +2095,16 @@ reply_nxdomain(struct sreply *sreply)
int salen = sreply->salen;
struct domain *sd = sreply->sd1;
int istcp = sreply->istcp;
+ int replysize = 512;
+
+ if (istcp) {
+ replysize = 65535;
+ }
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
@@ -1912,7 +2115,7 @@ reply_nxdomain(struct sreply *sreply)
if ((sd->flags & DOMAIN_HAVE_SOA) != DOMAIN_HAVE_SOA) {
- memcpy(&reply, buf, len);
+ memcpy(reply, buf, len);
memset((char *)&odh->query, 0, sizeof(u_int16_t));
SET_DNS_REPLY(odh);
@@ -1957,7 +2160,7 @@ reply_nxdomain(struct sreply *sreply)
}
/* copy question to reply */
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
/* blank query */
memset((char *)&odh->query, 0, sizeof(u_int16_t));
@@ -2006,14 +2209,14 @@ reply_nxdomain(struct sreply *sreply)
plabel = label;
/* copy label to reply */
- for (i = outlen; i < sizeof(reply); i++) {
+ for (i = outlen; i < replysize; i++) {
if (i - outlen == labellen)
break;
reply[i] = *plabel++;
}
- if (i >= sizeof(reply)) {
+ if (i >= replysize) {
return ;
}
@@ -2028,14 +2231,14 @@ reply_nxdomain(struct sreply *sreply)
labellen = sd->soa.rp_len;
plabel = label;
- for (i = outlen; i < sizeof(reply); i++) {
+ for (i = outlen; i < replysize; i++) {
if (i - outlen == labellen)
break;
reply[i] = *plabel++;
}
- if (i >= sizeof(reply)) {
+ if (i >= replysize) {
return ;
}
@@ -2049,7 +2252,7 @@ reply_nxdomain(struct sreply *sreply)
/* XXX */
- if ((outlen + sizeof(sd->soa.serial)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.serial)) > replysize) {
/* XXX server error reply? */
return;
}
@@ -2057,28 +2260,28 @@ reply_nxdomain(struct sreply *sreply)
*soa_val = htonl(sd->soa.serial);
outlen += sizeof(sd->soa.serial);
- if ((outlen + sizeof(sd->soa.refresh)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.refresh)) > replysize) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
*soa_val = htonl(sd->soa.refresh);
outlen += sizeof(sd->soa.refresh);
- if ((outlen + sizeof(sd->soa.retry)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.retry)) > replysize) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
*soa_val = htonl(sd->soa.retry);
outlen += sizeof(sd->soa.retry);
- if ((outlen + sizeof(sd->soa.expire)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.expire)) > replysize) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
*soa_val = htonl(sd->soa.expire);
outlen += sizeof(sd->soa.expire);
- if ((outlen + sizeof(sd->soa.minttl)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.minttl)) > replysize) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
@@ -2126,7 +2329,7 @@ reply_nxdomain(struct sreply *sreply)
void
reply_fmterror(struct sreply *sreply)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
u_int16_t outlen;
@@ -2136,14 +2339,19 @@ reply_fmterror(struct sreply *sreply)
struct sockaddr *sa = sreply->sa;
int salen = sreply->salen;
int istcp = sreply->istcp;
+ int replysize = 512;
- memset(&reply, 0, sizeof(reply));
+ if (istcp) {
+ replysize = 65535;
+ }
+ memset(reply, 0, replysize);
+
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
@@ -2190,7 +2398,7 @@ reply_fmterror(struct sreply *sreply)
void
reply_noerror(struct sreply *sreply)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
u_int16_t outlen;
char *p;
@@ -2229,11 +2437,16 @@ reply_noerror(struct sreply *sreply)
int salen = sreply->salen;
struct domain *sd = sreply->sd1;
int istcp = sreply->istcp;
+ int replysize = 512;
+
+ if (istcp) {
+ replysize = 65535;
+ }
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
@@ -2244,7 +2457,7 @@ reply_noerror(struct sreply *sreply)
if ((sd->flags & DOMAIN_HAVE_SOA) != DOMAIN_HAVE_SOA) {
- memcpy(&reply, buf, len);
+ memcpy(reply, buf, len);
memset((char *)&odh->query, 0, sizeof(u_int16_t));
SET_DNS_REPLY(odh);
@@ -2281,7 +2494,7 @@ reply_noerror(struct sreply *sreply)
}
/* copy question to reply */
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
/* blank query */
memset((char *)&odh->query, 0, sizeof(u_int16_t));
@@ -2323,14 +2536,14 @@ reply_noerror(struct sreply *sreply)
plabel = label;
/* copy label to reply */
- for (i = outlen; i < sizeof(reply); i++) {
+ for (i = outlen; i < replysize; i++) {
if (i - outlen == labellen)
break;
reply[i] = *plabel++;
}
- if (i >= sizeof(reply)) {
+ if (i >= replysize) {
return ;
}
@@ -2345,14 +2558,14 @@ reply_noerror(struct sreply *sreply)
labellen = sd->soa.rp_len;
plabel = label;
- for (i = outlen; i < sizeof(reply); i++) {
+ for (i = outlen; i < replysize; i++) {
if (i - outlen == labellen)
break;
reply[i] = *plabel++;
}
- if (i >= sizeof(reply)) {
+ if (i >= replysize) {
return ;
}
@@ -2366,7 +2579,7 @@ reply_noerror(struct sreply *sreply)
/* XXX */
- if ((outlen + sizeof(sd->soa.serial)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.serial)) > replysize) {
/* XXX server error reply? */
return;
}
@@ -2374,28 +2587,28 @@ reply_noerror(struct sreply *sreply)
*soa_val = htonl(sd->soa.serial);
outlen += sizeof(sd->soa.serial);
- if ((outlen + sizeof(sd->soa.refresh)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.refresh)) > replysize) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
*soa_val = htonl(sd->soa.refresh);
outlen += sizeof(sd->soa.refresh);
- if ((outlen + sizeof(sd->soa.retry)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.retry)) > replysize) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
*soa_val = htonl(sd->soa.retry);
outlen += sizeof(sd->soa.retry);
- if ((outlen + sizeof(sd->soa.expire)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.expire)) > replysize) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
*soa_val = htonl(sd->soa.expire);
outlen += sizeof(sd->soa.expire);
- if ((outlen + sizeof(sd->soa.minttl)) > sizeof(reply)) {
+ if ((outlen + sizeof(sd->soa.minttl)) > replysize) {
return;
}
soa_val = (u_int32_t *)&reply[outlen];
@@ -2788,7 +3001,7 @@ in_cksum(const u_short *addr, register int len, int cs
void
reply_any(struct sreply *sreply)
{
- char reply[512];
+ char *reply = sreply->replybuf;
struct dns_header *odh;
u_int16_t outlen;
@@ -2799,18 +3012,23 @@ reply_any(struct sreply *sreply)
struct sockaddr *sa = sreply->sa;
int salen = sreply->salen;
int istcp = sreply->istcp;
+ int replysize = 512;
+
+ if (istcp) {
+ replysize = 65535;
+ }
/* st */
odh = (struct dns_header *)&reply[0];
outlen = sizeof(struct dns_header);
- if (len > sizeof(reply)) {
+ if (len > replysize) {
return;
}
/* copy question to reply */
- memcpy(&reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+ memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
/* blank query */
memset((char *)&odh->query, 0, sizeof(u_int16_t));
@@ -2829,7 +3047,7 @@ reply_any(struct sreply *sreply)
odh->nsrr = 0;
odh->additional = 0;
- outlen = create_anyreply(sreply, (char *)&reply, sizeof(reply), outlen, 1);
+ outlen = create_anyreply(sreply, (char *)reply, replysize, outlen, 1);
if (outlen == 0) {
return;
}
@@ -2872,7 +3090,7 @@ reply_any(struct sreply *sreply)
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;
+ int a_count, aaaa_count, ns_count, mx_count, srv_count, sshfp_count;
int tmplen, pos, mod;
int ttlhack;
struct answer {
@@ -2892,6 +3110,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_int8_t *sshfp_alg, *sshfp_fptype;
char *name, *p;
int i;
@@ -3247,6 +3466,63 @@ create_anyreply(struct sreply *sreply, char *reply, in
answer->rdlength = htons(sd->txtlen + 1);
}
+ if (sd->flags & DOMAIN_HAVE_SSHFP) {
+ sshfp_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_SSHFP);
+ answer->class = htons(DNS_CLASS_IN);
+ answer->ttl = htonl(sd->ttl);
+ answer->rdlength = htons((2 * sizeof(u_int8_t)) + sd->sshfp[sshfp_count].fplen);
+
+ offset += 10; /* up to rdata length */
+
+ sshfp_alg = (u_int8_t *)&reply[offset];
+ *sshfp_alg = htons(sd->sshfp[sshfp_count].algorithm);
+
+ offset++;
+
+ sshfp_fptype = (u_int8_t *)&reply[offset];
+ *sshfp_fptype = htons(sd->sshfp[sshfp_count].fptype);
+
+ offset++;
+
+ if (offset + sd->sshfp[sshfp_count].fplen > rlen)
+ goto truncate;
+
+ memcpy((char *)&reply[offset], (char *)sd->sshfp[sshfp_count].fingerprint, sd->sshfp[sshfp_count].fplen);
+
+ offset += sd->sshfp[sshfp_count].fplen;
+
+ /* can we afford to write another header? if no truncate */
+ if (sd->sshfp_count > 1 && (offset + 12 + 2 + sd->sshfp[sshfp_count].fplen) > rlen) {
+ goto truncate;
+ }
+
+ answer->rdlength = htons(&reply[offset] - answer->rdata);
+ } while (++sshfp_count < RECORD_COUNT && --sd->sshfp_count);
+
+ NTOHS(odh->answer);
+ odh->answer += sshfp_count;
+ HTONS(odh->answer);
+
+ }
if (sd->flags & DOMAIN_HAVE_SRV) {
srv_count = 0;
do {
@@ -3270,7 +3546,7 @@ create_anyreply(struct sreply *sreply, char *reply, in
answer->type = htons(DNS_TYPE_SRV);
answer->class = htons(DNS_CLASS_IN);
answer->ttl = htonl(sd->ttl);
- answer->rdlength = htons(3 * sizeof(u_int16_t) + sd->srv[srv_count].targetlen);
+ answer->rdlength = htons((3 * sizeof(u_int16_t)) + sd->srv[srv_count].targetlen);
offset += 10; /* up to rdata length */
@@ -3464,7 +3740,6 @@ create_anyreply(struct sreply *sreply, char *reply, in
return (offset);
truncate:
-
NTOHS(odh->query);
SET_DNS_TRUNCATION(odh);
HTONS(odh->query);
repomaster@centroid.eu