Commit Diff
Diff:
d51887174651a3d85add12a1dcc55beb8641d93b
353160236e67dc0dcc7f8af9a9c560bf47bc7919
Commit:
353160236e67dc0dcc7f8af9a9c560bf47bc7919
Tree:
7e2ecf8e06d479bc69beb62c1b3d01dd02c1c2b0
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Tue Jul 21 18:19:58 2020 UTC
Message:
with NetBSD's advice I changed the way the forward process replies to queries. It now uses a raw socket (type UDP) where you have to attach a UDP header. This does fragment nicely, and ended my worries. I have written this on OpenBSD, and nearly immediately it worked on Linux, except IPv6. They do a little dance around the protocol stuck into the port first, but that worked after reading the kernel source. I still have to test NetBSD and FreeBSD, but somehow I think they'll work out of the box, we'll see. This has put me behind a day but it's worth it. It's much cleaner this way. Thanks goes to NetBSD. Tested so far on OpenBSD and Linux/RPI.
blob - cf016041a660acc14dc7cc9a4d6bbc30b9163acb
blob + bbd6cceb2d296f79001797fef9caadf39f34c0bd
--- ddd-db.h
+++ ddd-db.h
@@ -27,7 +27,7 @@
*/
/*
- * $Id: ddd-db.h,v 1.49 2020/07/20 13:03:37 pjp Exp $
+ * $Id: ddd-db.h,v 1.50 2020/07/21 18:19:58 pjp Exp $
*/
#ifndef _DB_H
@@ -363,8 +363,8 @@ struct cfg {
int udp[DEFAULT_SOCKET]; /* udp sockets */
int tcp[DEFAULT_SOCKET]; /* tcp socket */
int axfr[DEFAULT_SOCKET]; /* axfr udp socket */
- int dup[DEFAULT_SOCKET]; /* dup sockets */
char *ident[DEFAULT_SOCKET]; /* identification of interface */
+ struct sockaddr_storage ss[DEFAULT_SOCKET]; /* some addr storage */
struct my_imsg {
int imsg_fds[2];
} my_imsg[100];
@@ -378,7 +378,10 @@ struct cfg {
#define MY_IMSG_UDP 7
#define MY_IMSG_FORWARD 8
#define MY_IMSG_MAX 9
- int recurse; /* recurse socket */
+ int raw[2];
+#define RAW_IPSOCKET 0
+#define RAW_IP6SOCKET 1
+ u_short port;
int sockcount; /* set sockets */
int nth;
pid_t pid;
@@ -484,7 +487,7 @@ struct reply_logic {
int buildtype;
#define BUILD_CNAME 1
#define BUILD_OTHER 2
- int (*reply)(struct sreply *, ddDB *);
+ int (*reply)(struct sreply *, int *, ddDB *);
};
blob - 9f48b233f71fd7c77afb0bce960b43a103bb2167
blob + 056513817c31f7012423d3222c72a4259e36f520
--- ddd-dns.h
+++ ddd-dns.h
@@ -27,7 +27,7 @@
*/
/*
- * $Id: ddd-dns.h,v 1.26 2020/07/20 13:03:37 pjp Exp $
+ * $Id: ddd-dns.h,v 1.27 2020/07/21 18:19:58 pjp Exp $
*/
#ifndef _DNS_H
@@ -274,6 +274,7 @@ struct question {
char *converted_name;
u_int16_t edns0len;
u_int8_t ednsversion;
+ int rawsocket;
int aa;
int rd;
int dnssecok;
blob - ab8ecc0b7ce0ee24d01a3a1d57d415cf44885d12
blob + a3b91490e44e3c5643b5ed1c928339309b98e36c
--- delphinusdnsd.c
+++ delphinusdnsd.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: delphinusdnsd.c,v 1.132 2020/07/17 05:40:19 pjp Exp $
+ * $Id: delphinusdnsd.c,v 1.133 2020/07/21 18:19:58 pjp Exp $
*/
@@ -130,35 +130,35 @@ extern void init_notifyddd(void);
extern struct rbtree * lookup_zone(ddDB *, struct question *, int *, int *, char *, int);
extern struct rbtree * Lookup_zone(ddDB *, char *, u_int16_t, u_int16_t, int);
extern int memcasecmp(u_char *, u_char *, int);
-extern int reply_a(struct sreply *, ddDB *);
-extern int reply_aaaa(struct sreply *, ddDB *);
-extern int reply_any(struct sreply *, ddDB *);
-extern int reply_badvers(struct sreply *, ddDB *);
-extern int reply_nodata(struct sreply *, ddDB *);
-extern int reply_cname(struct sreply *, ddDB *);
-extern int reply_fmterror(struct sreply *, ddDB *);
-extern int reply_notauth(struct sreply *, ddDB *);
-extern int reply_notimpl(struct sreply *, ddDB *);
-extern int reply_nxdomain(struct sreply *, ddDB *);
-extern int reply_noerror(struct sreply *, ddDB *);
-extern int reply_notify(struct sreply *, ddDB *);
-extern int reply_soa(struct sreply *, ddDB *);
-extern int reply_mx(struct sreply *, ddDB *);
-extern int reply_naptr(struct sreply *, ddDB *);
-extern int reply_ns(struct sreply *, ddDB *);
-extern int reply_ptr(struct sreply *, ddDB *);
-extern int reply_refused(struct sreply *, ddDB *);
-extern int reply_srv(struct sreply *, ddDB *);
-extern int reply_sshfp(struct sreply *, ddDB *);
-extern int reply_tlsa(struct sreply *, ddDB *);
-extern int reply_txt(struct sreply *, ddDB *);
-extern int reply_version(struct sreply *, ddDB *);
-extern int reply_rrsig(struct sreply *, ddDB *);
-extern int reply_dnskey(struct sreply *, ddDB *);
-extern int reply_ds(struct sreply *, ddDB *);
-extern int reply_nsec(struct sreply *, ddDB *);
-extern int reply_nsec3(struct sreply *, ddDB *);
-extern int reply_nsec3param(struct sreply *, ddDB *);
+extern int reply_a(struct sreply *, int *, ddDB *);
+extern int reply_aaaa(struct sreply *, int *, ddDB *);
+extern int reply_any(struct sreply *, int *, ddDB *);
+extern int reply_badvers(struct sreply *, int *, ddDB *);
+extern int reply_nodata(struct sreply *, int *, ddDB *);
+extern int reply_cname(struct sreply *, int *, ddDB *);
+extern int reply_fmterror(struct sreply *, int *, ddDB *);
+extern int reply_notauth(struct sreply *, int *, ddDB *);
+extern int reply_notimpl(struct sreply *, int *, ddDB *);
+extern int reply_nxdomain(struct sreply *, int *, ddDB *);
+extern int reply_noerror(struct sreply *, int *, ddDB *);
+extern int reply_notify(struct sreply *, int *, ddDB *);
+extern int reply_soa(struct sreply *, int *, ddDB *);
+extern int reply_mx(struct sreply *, int *, ddDB *);
+extern int reply_naptr(struct sreply *, int *, ddDB *);
+extern int reply_ns(struct sreply *, int *, ddDB *);
+extern int reply_ptr(struct sreply *, int *, ddDB *);
+extern int reply_refused(struct sreply *, int *, ddDB *);
+extern int reply_srv(struct sreply *, int *, ddDB *);
+extern int reply_sshfp(struct sreply *, int *, ddDB *);
+extern int reply_tlsa(struct sreply *, int *, ddDB *);
+extern int reply_txt(struct sreply *, int *, ddDB *);
+extern int reply_version(struct sreply *, int *, ddDB *);
+extern int reply_rrsig(struct sreply *, int *, ddDB *);
+extern int reply_dnskey(struct sreply *, int *, ddDB *);
+extern int reply_ds(struct sreply *, int *, ddDB *);
+extern int reply_nsec(struct sreply *, int *, ddDB *);
+extern int reply_nsec3(struct sreply *, int *, ddDB *);
+extern int reply_nsec3param(struct sreply *, int *, ddDB *);
extern char *rrlimit_setup(int);
extern char *dns_label(char *, int *);
extern void ddd_shutdown(void);
@@ -304,7 +304,6 @@ int
main(int argc, char *argv[], char *environ[])
{
static int udp[DEFAULT_SOCKET];
- static int dup[DEFAULT_SOCKET];
static int tcp[DEFAULT_SOCKET];
static int afd[DEFAULT_SOCKET];
static int uafd[DEFAULT_SOCKET];
@@ -623,17 +622,9 @@ main(int argc, char *argv[], char *environ[])
res = res0;
-#ifdef __linux__
-
udp[i] = bind_this_res(res, 0);
- dup[i] = bind_this_res(res, 0);
-#else
- /* first dup, then udp */
- dup[i] = bind_this_res(res, 1);
- udp[i] = bind_this_res(res, 0);
-#endif
+ memcpy((void *)&cfg->ss[i], (void *)res->ai_addr, res->ai_addrlen);
-
if (res->ai_family == AF_INET) {
on = 1;
if (setsockopt(udp[i], IPPROTO_IP, IP_RECVTTL,
@@ -782,14 +773,8 @@ main(int argc, char *argv[], char *environ[])
continue;
}
-#if __linux__
udp[i] = bind_this_pifap(pifap, 0, salen);
- dup[i] = bind_this_pifap(pifap, 0, salen);
-#else
- /* first dup, then udp */
- dup[i] = bind_this_pifap(pifap, 1, salen);
- udp[i] = bind_this_pifap(pifap, 0, salen);
-#endif
+ memcpy((void *)&cfg->ss[i], (void *)pifap->ifa_addr, salen);
if (pifap->ifa_addr->sa_family == AF_INET) {
on = 1;
@@ -870,6 +855,20 @@ main(int argc, char *argv[], char *environ[])
}
} /* if bflag? */
+ if ((cfg->raw[0] = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) < 0) {
+ dolog(LOG_INFO, "raw0 socket: %s\n", strerror(errno));
+ ddd_shutdown();
+ exit(1);
+ }
+ shutdown(cfg->raw[0], SHUT_RD);
+ if ((cfg->raw[1] = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP)) < 0) {
+ dolog(LOG_INFO, "raw1 socket: %s\n", strerror(errno));
+ ddd_shutdown();
+ exit(1);
+ }
+ on = 1;
+ shutdown(cfg->raw[1], SHUT_RD);
+ cfg->port = port;
#if __OpenBSD__
if (unveil(DELPHINUS_RZONE_PATH, "rwc") < 0) {
@@ -936,8 +935,9 @@ main(int argc, char *argv[], char *environ[])
if (axfrport && axfrport != port)
close(uafd[j]);
- close(dup[j]);
}
+ close(cfg->raw[0]);
+ close(cfg->raw[1]);
setproctitle("AXFR engine on port %d", axfrport);
axfrloop(afd, (axfrport == port) ? 0 : i, ident, db, ibuf);
@@ -993,8 +993,9 @@ main(int argc, char *argv[], char *environ[])
for (j = 0; j < i; j++) {
close(tcp[j]);
close(udp[j]);
- close(dup[j]);
}
+ close(cfg->raw[0]);
+ close(cfg->raw[1]);
setproctitle("Replicant engine");
@@ -1113,8 +1114,9 @@ main(int argc, char *argv[], char *environ[])
for (j = 0; j < i; j++) {
close(tcp[j]);
close(udp[j]);
+ if (axfrport && axfrport != port)
+ close(uafd[j]);
- cfg->dup[j] = dup[j];
}
cfg->sockcount = i;
@@ -1136,6 +1138,8 @@ main(int argc, char *argv[], char *environ[])
} /* forward */
+ close(cfg->raw[0]);
+ close(cfg->raw[1]);
/* the rest of the daemon goes on in TCP and UDP loops */
@@ -1194,7 +1198,6 @@ main(int argc, char *argv[], char *environ[])
cfg->ident[i] = strdup(ident[i]);
- close(dup[i]);
}
setproctitle("child %d pid %d", n, cfg->pid);
@@ -1216,8 +1219,6 @@ main(int argc, char *argv[], char *environ[])
cfg->axfr[i] = uafd[i];
cfg->ident[i] = strdup(ident[i]);
-
- close(dup[i]);
}
(void)mainloop(cfg, &cortex_ibuf);
@@ -1519,7 +1520,6 @@ mainloop(struct cfg *cfg, struct imsgbuf *ibuf)
int rcheck = 0;
int blocklist = 1;
int require_tsig = 0;
- int sp;
pid_t idata;
u_int32_t received_ttl;
@@ -1569,6 +1569,7 @@ mainloop(struct cfg *cfg, struct imsgbuf *ibuf)
ssize_t n, datalen;
int ix;
+ int sretlen;
pid = fork();
switch (pid) {
@@ -1681,8 +1682,6 @@ mainloop(struct cfg *cfg, struct imsgbuf *ibuf)
}
#endif
- sp = cfg->recurse;
-
for (;;) {
is_ipv6 = 0;
maxso = 0;
@@ -1849,7 +1848,7 @@ axfrentry:
if (filter && require_tsig == 0) {
build_reply(&sreply, so, buf, len, NULL, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_refused(&sreply, NULL);
+ slen = reply_refused(&sreply, &sretlen, NULL);
dolog(LOG_INFO, "UDP connection refused on descriptor %u interface \"%s\" from %s (ttl=%d, region=%d) replying REFUSED, filter policy\n", so, cfg->ident[i], address, received_ttl, aregion);
goto drop;
@@ -1858,7 +1857,7 @@ axfrentry:
if (passlist && blocklist == 0) {
build_reply(&sreply, so, buf, len, NULL, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_refused(&sreply, NULL);
+ slen = reply_refused(&sreply, &sretlen, NULL);
dolog(LOG_INFO, "UDP connection refused on descriptor %u interface \"%s\" from %s (ttl=%d, region=%d) replying REFUSED, passlist policy\n", so, cfg->ident[i], address, received_ttl, aregion);
goto drop;
@@ -1934,7 +1933,7 @@ 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, 0, replybuf);
- slen = reply_fmterror(&sreply, NULL);
+ slen = reply_fmterror(&sreply, &sretlen, NULL);
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);
imsg_free(&imsg);
goto drop;
@@ -1950,7 +1949,7 @@ axfrentry:
/* we didn't see a tsig header */
if (filter && pq.tsig.have_tsig == 0) {
build_reply(&sreply, so, buf, len, NULL, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_refused(&sreply, NULL);
+ slen = reply_refused(&sreply, &sretlen, NULL);
dolog(LOG_INFO, "UDP connection refused on descriptor %u interface \"%s\" from %s (ttl=%d, region=%d) replying REFUSED, not a tsig\n", so, cfg->ident[i], address, received_ttl, aregion);
imsg_free(&imsg);
goto drop;
@@ -1984,7 +1983,7 @@ axfrentry:
dolog(LOG_INFO, "on descriptor %u interface \"%s\" authenticated dns NOTIFY packet from %s, replying NOTIFY\n", so, cfg->ident[i], address);
snprintf(replystring, DNS_MAXNAME, "NOTIFY");
build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_notify(&sreply, NULL);
+ slen = reply_notify(&sreply, &sretlen, NULL);
/* send notify to replicant process */
idata = (pid_t)question->hdr->namelen;
@@ -1997,7 +1996,7 @@ axfrentry:
dolog(LOG_INFO, "on descriptor %u interface \"%s\" not authenticated dns NOTIFY packet (code = %d) from %s, replying notauth\n", so, cfg->ident[i], question->tsig.tsigerrorcode, address);
snprintf(replystring, DNS_MAXNAME, "NOTAUTH");
build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_notauth(&sreply, NULL);
+ slen = reply_notauth(&sreply, &sretlen, NULL);
goto udpout;
}
@@ -2005,7 +2004,7 @@ axfrentry:
dolog(LOG_INFO, "on descriptor %u interface \"%s\" dns NOTIFY packet from %s, replying NOTIFY\n", so, cfg->ident[i], address);
snprintf(replystring, DNS_MAXNAME, "NOTIFY");
build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_notify(&sreply, NULL);
+ slen = reply_notify(&sreply, &sretlen, NULL);
/* send notify to replicant process */
idata = (pid_t)question->hdr->namelen;
imsg_compose(udp_ibuf, IMSG_NOTIFY_MESSAGE,
@@ -2017,7 +2016,7 @@ axfrentry:
dolog(LOG_INFO, "on descriptor %u interface \"%s\" dns NOTIFY packet from %s, NOT in our list of MASTER servers replying REFUSED\n", so, cfg->ident[i], address);
snprintf(replystring, DNS_MAXNAME, "REFUSED");
build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_refused(&sreply, NULL);
+ slen = reply_refused(&sreply, &sretlen, NULL);
goto udpout;
}
@@ -2027,13 +2026,13 @@ axfrentry:
dolog(LOG_INFO, "on descriptor %u interface \"%s\" not authenticated dns packet (code = %d) from %s, replying notauth\n", so, cfg->ident[i], question->tsig.tsigerrorcode, address);
snprintf(replystring, DNS_MAXNAME, "NOTAUTH");
build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_notauth(&sreply, NULL);
+ slen = reply_notauth(&sreply, &sretlen, NULL);
goto udpout;
}
/* hack around whether we're edns version 0 */
if (question->ednsversion != 0) {
build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_badvers(&sreply, NULL);
+ slen = reply_badvers(&sreply, &sretlen, NULL);
dolog(LOG_INFO, "on TCP descriptor %u interface \"%s\" edns version is %u from %s, replying badvers\n", so, cfg->ident[i], question->ednsversion, address);
@@ -2046,7 +2045,7 @@ axfrentry:
strcasecmp(question->converted_name, "version.bind.") == 0) {
snprintf(replystring, DNS_MAXNAME, "VERSION");
build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_version(&sreply, NULL);
+ slen = reply_version(&sreply, &sretlen, NULL);
goto udpout;
}
@@ -2066,7 +2065,7 @@ axfrentry:
snprintf(replystring, DNS_MAXNAME, "REFUSED");
build_reply(&sreply, so, buf, len, question, from, fromlen, rbt0, NULL, aregion, istcp, 0, replybuf);
- slen = reply_refused(&sreply, NULL);
+ slen = reply_refused(&sreply, &sretlen, NULL);
goto udpout;
break;
case ERR_NXDOMAIN:
@@ -2085,7 +2084,7 @@ axfrentry:
fromlen, rbt0, NULL, aregion, istcp, \
0, replybuf);
- slen = reply_nxdomain(&sreply, cfg->db);
+ slen = reply_nxdomain(&sreply, &sretlen, cfg->db);
}
goto udpout;
break;
@@ -2099,12 +2098,12 @@ axfrentry:
if (rbt1 != NULL) {
snprintf(replystring, DNS_MAXNAME, "NODATA");
build_reply(&sreply, so, buf, len, question, from, fromlen, rbt1, rbt0, aregion, istcp, 0, replybuf);
- slen = reply_nodata(&sreply, cfg->db);
+ slen = reply_nodata(&sreply, &sretlen, cfg->db);
} else {
if (forward)
goto forwardudp;
build_reply(&sreply, so, buf, len, question, from, fromlen, rbt1, rbt0, aregion, istcp, 0, replybuf);
- slen = reply_refused(&sreply, cfg->db);
+ slen = reply_refused(&sreply, &sretlen, cfg->db);
snprintf(replystring, DNS_MAXNAME, "REFUSED");
}
goto udpout;
@@ -2119,7 +2118,7 @@ forwardudp:
} else {
snprintf(replystring, DNS_MAXNAME, "REFUSED");
build_reply(&sreply, so, buf, len, question, from, fromlen, rbt1, rbt0, aregion, istcp, 0, replybuf);
- slen = reply_refused(&sreply, cfg->db);
+ slen = reply_refused(&sreply, &sretlen, cfg->db);
goto udpout;
}
} else
@@ -2222,7 +2221,7 @@ forwardudp:
fromlen, rbt0, NULL, aregion, istcp, 0,
replybuf);
- slen = reply_noerror(&sreply, cfg->db);
+ slen = reply_noerror(&sreply, &sretlen, cfg->db);
goto udpout;
}
@@ -2237,7 +2236,7 @@ forwardudp:
fromlen, rbt0, NULL, aregion, istcp, \
0, replybuf);
- slen = reply_ns(&sreply, cfg->db);
+ slen = reply_ns(&sreply, &sretlen, cfg->db);
} else {
slen = 0;
snprintf(replystring, DNS_MAXNAME, "DROP");
@@ -2290,7 +2289,7 @@ forwardudp:
fromlen, NULL, NULL, aregion, istcp, 0, \
replybuf);
- slen = reply_notimpl(&sreply, NULL);
+ slen = reply_notimpl(&sreply, &sretlen, NULL);
snprintf(replystring, DNS_MAXNAME, "NOTIMPL");
goto udpout;
}
@@ -2314,7 +2313,7 @@ forwardudp:
continue;
}
- slen = (*rl->reply)(&sreply, cfg->db);
+ slen = (*rl->reply)(&sreply, &sretlen, cfg->db);
break;
} /* if rl->rrtype == */
}
@@ -2333,7 +2332,7 @@ forwardudp:
fromlen, rbt0, NULL, aregion, istcp, 0, \
replybuf);
- slen = reply_ns(&sreply, cfg->db);
+ slen = reply_ns(&sreply, &sretlen, cfg->db);
} else {
@@ -2341,7 +2340,7 @@ forwardudp:
fromlen, NULL, NULL, aregion, istcp, 0, \
replybuf);
- slen = reply_notimpl(&sreply, NULL);
+ slen = reply_notimpl(&sreply, &sretlen, NULL);
snprintf(replystring, DNS_MAXNAME, "NOTIMPL");
}
}
@@ -2614,7 +2613,6 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
int blocklist = 1;
int require_tsig = 0;
int axfr_acl = 0;
- int sp;
pid_t idata;
uint conncnt = 0;
int tcpflags;
@@ -2659,6 +2657,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
struct sforward *sforward;
int ix;
+ int sretlen;
sforward = (struct sforward *)calloc(1, sizeof(struct sforward));
@@ -2722,8 +2721,6 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
}
- sp = cfg->recurse;
-
/*
* listen on descriptors
*/
@@ -2832,7 +2829,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
dolog(LOG_INFO, "TCP connection refused on descriptor %u interface \"%s\" from %s, filter policy, drop\n", so, cfg->ident[i], address);
#if 0
build_reply(&sreply, so, pbuf, len, NULL, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_refused(&sreply, NULL);
+ slen = reply_refused(&sreply, &sretlen, NULL);
#endif
close(so);
continue;
@@ -3004,7 +3001,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
dolog(LOG_INFO, "TCP packet on descriptor %u interface \"%s\" header from %s has no question, drop\n", so, cfg->ident[tcpnp->intidx], tcpnp->address);
/* format error */
build_reply(&sreply, so, pbuf, len, NULL, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_fmterror(&sreply, NULL);
+ slen = reply_fmterror(&sreply, &sretlen, NULL);
dolog(LOG_INFO, "TCP question on descriptor %d interface \"%s\" from %s, did not have question of 1 replying format error\n", so, cfg->ident[tcpnp->intidx], tcpnp->address);
imsg_free(&imsg);
goto drop;
@@ -3019,7 +3016,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
case PARSE_RETURN_NOTAUTH:
if (filter && pq.tsig.have_tsig == 0) {
build_reply(&sreply, so, pbuf, len, NULL, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_refused(&sreply, NULL);
+ slen = reply_refused(&sreply, &sretlen, NULL);
dolog(LOG_INFO, "TCP connection refused on descriptor %u interface \"%s\" from %s (ttl=TCP, region=%d) replying REFUSED, not a tsig\n", so, cfg->ident[tcpnp->intidx], tcpnp->address, aregion);
imsg_free(&imsg);
goto drop;
@@ -3050,7 +3047,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
dolog(LOG_INFO, "on TCP descriptor %u interface \"%s\" authenticated dns NOTIFY packet from %s, replying NOTIFY\n", so, cfg->ident[tcpnp->intidx], tcpnp->address);
snprintf(replystring, DNS_MAXNAME, "NOTIFY");
build_reply(&sreply, so, pbuf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_notify(&sreply, NULL);
+ slen = reply_notify(&sreply, &sretlen, NULL);
/* send notify to replicant process */
idata = (pid_t)question->hdr->namelen;
imsg_compose(ibuf, IMSG_NOTIFY_MESSAGE,
@@ -3062,7 +3059,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
dolog(LOG_INFO, "on TCP descriptor %u interface \"%s\" not authenticated dns NOTIFY packet (code = %d) from %s, replying notauth\n", so, cfg->ident[tcpnp->intidx], question->tsig.tsigerrorcode, tcpnp->address);
snprintf(replystring, DNS_MAXNAME, "NOTAUTH");
build_reply(&sreply, so, pbuf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_notauth(&sreply, NULL);
+ slen = reply_notauth(&sreply, &sretlen, NULL);
goto tcpout;
}
@@ -3070,7 +3067,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
dolog(LOG_INFO, "on TCP descriptor %u interface \"%s\" dns NOTIFY packet from %s, replying NOTIFY\n", so, cfg->ident[tcpnp->intidx], tcpnp->address);
snprintf(replystring, DNS_MAXNAME, "NOTIFY");
build_reply(&sreply, so, pbuf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_notify(&sreply, NULL);
+ slen = reply_notify(&sreply, &sretlen, NULL);
/* send notify to replicant process */
idata = (pid_t)question->hdr->namelen;
imsg_compose(ibuf, IMSG_NOTIFY_MESSAGE,
@@ -3082,7 +3079,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
dolog(LOG_INFO, "on TCP descriptor %u interface \"%s\" dns NOTIFY packet from %s, NOT in our list of MASTER servers replying REFUSED\n", so, cfg->ident[tcpnp->intidx], tcpnp->address);
snprintf(replystring, DNS_MAXNAME, "REFUSED");
build_reply(&sreply, so, pbuf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_refused(&sreply, NULL);
+ slen = reply_refused(&sreply, &sretlen, NULL);
goto tcpout;
}
@@ -3092,7 +3089,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
dolog(LOG_INFO, "on TCP descriptor %u interface \"%s\" not authenticated dns packet (code = %d) from %s, replying notauth\n", so, cfg->ident[tcpnp->intidx], question->tsig.tsigerrorcode, tcpnp->address);
snprintf(replystring, DNS_MAXNAME, "NOTAUTH");
build_reply(&sreply, so, pbuf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_notauth(&sreply, NULL);
+ slen = reply_notauth(&sreply, &sretlen, NULL);
goto tcpout;
}
/* hack around whether we're edns version 0 */
@@ -3122,7 +3119,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
strcasecmp(question->converted_name, "version.bind.") == 0) {
snprintf(replystring, DNS_MAXNAME, "VERSION");
build_reply(&sreply, so, pbuf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, replybuf);
- slen = reply_version(&sreply, NULL);
+ slen = reply_version(&sreply, &sretlen, NULL);
goto tcpout;
}
@@ -3141,7 +3138,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
case ERR_REFUSED:
snprintf(replystring, DNS_MAXNAME, "REFUSED");
build_reply(&sreply, so, pbuf, len, question, from, fromlen, rbt0, NULL, aregion, istcp, 0, replybuf);
- slen = reply_refused(&sreply, NULL);
+ slen = reply_refused(&sreply, &sretlen, NULL);
goto tcpout;
break;
case ERR_NODATA:
@@ -3153,14 +3150,14 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
if (rbt0 != NULL) {
snprintf(replystring, DNS_MAXNAME, "NODATA");
build_reply(&sreply, so, pbuf, len, question, from, fromlen, rbt0, NULL, aregion, istcp, 0, replybuf);
- slen = reply_nodata(&sreply, cfg->db);
+ slen = reply_nodata(&sreply, &sretlen, cfg->db);
} else {
if (forward)
goto forwardtcp;
snprintf(replystring, DNS_MAXNAME, "REFUSED");
build_reply(&sreply, so, pbuf, len, question, from, fromlen, rbt0, NULL, aregion, istcp, 0, replybuf);
- slen = reply_refused(&sreply, cfg->db);
+ slen = reply_refused(&sreply, &sretlen, cfg->db);
}
goto tcpout;
@@ -3178,7 +3175,7 @@ tcploop(struct cfg *cfg, struct imsgbuf *ibuf, struct
from, fromlen, rbt0, NULL,
aregion, istcp, 0, replybuf);
- slen = reply_nxdomain(&sreply, cfg->db);
+ slen = reply_nxdomain(&sreply, &sretlen, cfg->db);
}
goto tcpout;
@@ -3191,7 +3188,7 @@ forwardtcp:
} else {
snprintf(replystring, DNS_MAXNAME, "REFUSED");
build_reply(&sreply, so, pbuf, len, question, from, fromlen, rbt1, rbt0, aregion, istcp, 0, replybuf);
- slen = reply_refused(&sreply, cfg->db);
+ slen = reply_refused(&sreply, &sretlen, cfg->db);
goto tcpout;
}
} else
@@ -3314,7 +3311,7 @@ forwardtcp:
rbt0, NULL, aregion, istcp,
0, replybuf);
- slen = reply_noerror(&sreply, cfg->db);
+ slen = reply_noerror(&sreply, &sretlen, cfg->db);
goto tcpout;
}
@@ -3330,7 +3327,7 @@ forwardtcp:
from, fromlen, rbt0, NULL,
aregion, istcp, 0, replybuf);
- slen = reply_ns(&sreply, cfg->db);
+ slen = reply_ns(&sreply, &sretlen, cfg->db);
} else {
slen = 0;
snprintf(replystring, DNS_MAXNAME, "DROP");
@@ -3383,7 +3380,7 @@ forwardtcp:
from, fromlen, NULL, NULL, aregion,
istcp, 0, replybuf);
- slen = reply_notimpl(&sreply, NULL);
+ slen = reply_notimpl(&sreply, &sretlen, NULL);
snprintf(replystring, DNS_MAXNAME, "NOTIMPL");
goto tcpout;
}
@@ -3425,7 +3422,7 @@ forwardtcp:
continue;
}
- slen = (*rl->reply)(&sreply, cfg->db);
+ slen = (*rl->reply)(&sreply, &sretlen, cfg->db);
break;
} /* if rl->rrtype == */
}
@@ -3444,7 +3441,7 @@ forwardtcp:
fromlen, rbt0, NULL, aregion, istcp,
0, replybuf);
- slen = reply_ns(&sreply, cfg->db);
+ slen = reply_ns(&sreply, &sretlen, cfg->db);
} else {
@@ -3452,7 +3449,7 @@ forwardtcp:
fromlen, NULL, NULL, aregion, istcp,
0, replybuf);
- slen = reply_notimpl(&sreply, NULL);
+ slen = reply_notimpl(&sreply, &sretlen, NULL);
snprintf(replystring, DNS_MAXNAME, "NOTIMPL");
}
}
@@ -3762,6 +3759,7 @@ convert_question(struct parsequestion *pq, int authori
q->tsig.tsigorigid = pq->tsig.tsigorigid;
q->notify = pq->notify;
+ q->rawsocket = 0;
return (q);
}
@@ -4044,11 +4042,6 @@ setup_cortex(struct imsgbuf *ibuf)
ddd_shutdown();
exit(1);
}
-
-#if 0
- /* reopenlog */
- openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
-#endif
#if __OpenBSD__
if (unveil("/", "") == -1) {
blob - 3cbbef1888c35817f3aea0950642ab027a9d3d86
blob + 5a4f18f0b32c643f6004f10d847bf5b6b7b3ab9c
--- forward.c
+++ forward.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: forward.c,v 1.37 2020/07/20 08:26:53 pjp Exp $
+ * $Id: forward.c,v 1.38 2020/07/21 18:19:58 pjp Exp $
*/
#include <sys/types.h>
@@ -38,6 +38,9 @@
#include <sys/resource.h>
#include <netinet/in.h>
+#include <netinet/udp.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <arpa/inet.h>
#include <netdb.h>
@@ -139,7 +142,11 @@ struct tsig * check_tsig(char *, int, char *);
void fwdparseloop(struct imsgbuf *, struct imsgbuf *, struct cfg *);
void changeforwarder(struct forwardqueue *);
void stirforwarders(void);
+int rawsend(int, char *, uint16_t, struct sockaddr_in *, int, struct cfg *);
+int rawsend6(int, char *, uint16_t, struct sockaddr_in6 *, int, struct cfg *);
+extern uint16_t udp_cksum(u_int16_t *, uint16_t, struct ip *, struct udphdr *);
+extern uint16_t udp_cksum6(u_int16_t *, uint16_t, struct ip6_hdr *, struct udphdr *);
extern void dolog(int, char *, ...);
extern void pack(char *, char *, int);
extern void pack16(char *, u_int16_t);
@@ -163,27 +170,27 @@ extern struct rbtree * Lookup_zone(ddDB *, char *, int
extern struct rbtree * lookup_zone(ddDB *, struct question *, int *, int *, char *, int);
extern int cacheit(u_char *, u_char *, u_char *, struct imsgbuf *, struct imsgbuf *, struct cfg *);
-extern int reply_a(struct sreply *, ddDB *);
-extern int reply_aaaa(struct sreply *, ddDB *);
-extern int reply_any(struct sreply *, ddDB *);
-extern int reply_cname(struct sreply *, ddDB *);
-extern int reply_notify(struct sreply *, ddDB *);
-extern int reply_soa(struct sreply *, ddDB *);
-extern int reply_mx(struct sreply *, ddDB *);
-extern int reply_naptr(struct sreply *, ddDB *);
-extern int reply_ns(struct sreply *, ddDB *);
-extern int reply_ptr(struct sreply *, ddDB *);
-extern int reply_srv(struct sreply *, ddDB *);
-extern int reply_sshfp(struct sreply *, ddDB *);
-extern int reply_tlsa(struct sreply *, ddDB *);
-extern int reply_txt(struct sreply *, ddDB *);
-extern int reply_rrsig(struct sreply *, ddDB *);
-extern int reply_dnskey(struct sreply *, ddDB *);
-extern int reply_ds(struct sreply *, ddDB *);
-extern int reply_nsec(struct sreply *, ddDB *);
-extern int reply_nsec3(struct sreply *, ddDB *);
-extern int reply_nsec3param(struct sreply *, ddDB *);
-extern int reply_generic(struct sreply *, ddDB *);
+extern int reply_a(struct sreply *, int *, ddDB *);
+extern int reply_aaaa(struct sreply *, int *, ddDB *);
+extern int reply_any(struct sreply *, int *, ddDB *);
+extern int reply_cname(struct sreply *, int *, ddDB *);
+extern int reply_notify(struct sreply *, int *, ddDB *);
+extern int reply_soa(struct sreply *, int *, ddDB *);
+extern int reply_mx(struct sreply *, int *, ddDB *);
+extern int reply_naptr(struct sreply *, int *, ddDB *);
+extern int reply_ns(struct sreply *, int *, ddDB *);
+extern int reply_ptr(struct sreply *, int *, ddDB *);
+extern int reply_srv(struct sreply *, int *, ddDB *);
+extern int reply_sshfp(struct sreply *, int *, ddDB *);
+extern int reply_tlsa(struct sreply *, int *,ddDB *);
+extern int reply_txt(struct sreply *, int *, ddDB *);
+extern int reply_rrsig(struct sreply *, int *, ddDB *);
+extern int reply_dnskey(struct sreply *, int *, ddDB *);
+extern int reply_ds(struct sreply *, int *, ddDB *);
+extern int reply_nsec(struct sreply *, int *, ddDB *);
+extern int reply_nsec3(struct sreply *, int *, ddDB *);
+extern int reply_nsec3param(struct sreply *, int *, ddDB *);
+extern int reply_generic(struct sreply *, int *, ddDB *);
extern struct rbtree * create_rr(ddDB *, char *, int, int, void *, uint32_t, uint16_t);
extern void flag_rr(struct rbtree *rbt);
extern struct rbtree * find_rrset(ddDB *, char *, int);
@@ -355,9 +362,6 @@ forwardloop(ddDB *db, struct cfg *cfg, struct imsgbuf
#endif
cfg->shptrsize = 0;
- for (i = 0; i < cfg->sockcount; i++)
- close(cfg->dup[i]);
-
close(ibuf->fd);
close(cortex->fd);
close(pi[1]);
@@ -687,6 +691,7 @@ forwardthis(ddDB *db, struct cfg *cfg, int so, struct
int fromlen, returnval, lzerrno;
int istcp = (so == -1 ? 0 : 1);
+ int sretlen;
int found = 0;
time_t now;
@@ -850,16 +855,25 @@ forwardthis(ddDB *db, struct cfg *cfg, int so, struct
goto newqueue;
}
+ q->rawsocket = 1;
build_reply(&sreply,
- (istcp ? so : cfg->dup[sforward->oldsel]),
- buf, len, q, (struct sockaddr *)from, fromlen,
+ (istcp ? so : -1), buf, len, q,
+ (struct sockaddr *)from, fromlen,
rbt, NULL, 0xff, istcp, 0, replybuf);
/* from delphinusdnsd.c */
for (rl = &rlogic[0]; rl->rrtype != 0; rl++) {
if (rl->rrtype == ntohs(q->hdr->qtype)) {
- slen = (*rl->reply)(&sreply, cfg->db);
+ slen = (*rl->reply)(&sreply, &sretlen, cfg->db);
+ switch (from->ss_family) {
+ case AF_INET:
+ rawsend(cfg->raw[0], sreply.replybuf, sretlen, &sforward->from4, sforward->oldsel, cfg);
+ break;
+ case AF_INET6:
+ rawsend6(cfg->raw[1], sreply.replybuf, sretlen, &sforward->from6, sforward->oldsel, cfg);
+ break;
+ }
if (slen < 0) {
/*
* we may have a non-dnssec answer cached without RRSIG
@@ -891,7 +905,7 @@ forwardthis(ddDB *db, struct cfg *cfg, int so, struct
dolog(LOG_INFO, "replying generic RR %d\n",
ntohs(q->hdr->qtype));
#endif
- if (reply_generic(&sreply, cfg->db) < 0) {
+ if (reply_generic(&sreply, &sretlen, cfg->db) < 0) {
expire_rr(db, q->hdr->name, q->hdr->namelen,
ntohs(q->hdr->qtype), highexpire);
free_question(q);
@@ -1183,7 +1197,6 @@ returnit(ddDB *db, struct cfg *cfg, struct forwardqueu
int len = 0;
int outlen;
- socklen_t tolen;
fd_set rset;
ssize_t n, datalen;
@@ -1201,7 +1214,7 @@ returnit(ddDB *db, struct cfg *cfg, struct forwardqueu
len = 2;
} else {
p = buf;
- so = cfg->dup[fwq->oldsel];
+ so = -1;
}
if (rlen <= sizeof(struct dns_header)) {
@@ -1488,14 +1501,10 @@ endimsg:
switch (fwq->oldfamily) {
case AF_INET:
- tolen = sizeof(struct sockaddr_in);
- if (sendto(so, buf, len, 0, (struct sockaddr *)&fwq->oldhost4, tolen) < 0)
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ rawsend(cfg->raw[0], buf, len, &fwq->oldhost4, fwq->oldsel, cfg);
break;
case AF_INET6:
- tolen = sizeof(struct sockaddr_in6);
- if (sendto(so, buf, len, 0, (struct sockaddr *)&fwq->oldhost6, tolen) < 0)
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ rawsend6(cfg->raw[1], buf, len, &fwq->oldhost6, fwq->oldsel, cfg);
break;
}
}
@@ -2197,4 +2206,76 @@ stirforwarders(void)
count++;
}
+}
+
+int
+rawsend(int so, char *buf, uint16_t len, struct sockaddr_in *sin, int oldsel, struct cfg *cfg)
+{
+ struct udphdr uh;
+ struct ip ip;
+ struct msghdr msg;
+ struct iovec iov[2];
+
+ memcpy(&ip.ip_src.s_addr, (void*)&(((struct sockaddr_in *)&cfg->ss[oldsel])->sin_addr.s_addr), sizeof(in_addr_t));
+ memcpy(&ip.ip_dst.s_addr, (void*)&sin->sin_addr, sizeof(in_addr_t));
+ ip.ip_p = IPPROTO_UDP;
+
+ memset(&uh, 0, sizeof(uh));
+ uh.uh_sport = htons(cfg->port);
+ uh.uh_dport = sin->sin_port;
+ uh.uh_ulen = htons(len + sizeof(struct udphdr));
+ uh.uh_sum = 0;
+ uh.uh_sum = udp_cksum((uint16_t *)buf, \
+ len + sizeof(struct udphdr), &ip, &uh);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = sin;
+ msg.msg_namelen = sizeof(struct sockaddr_in);
+ iov[0].iov_base = &uh;
+ iov[0].iov_len = sizeof(struct udphdr);
+ iov[1].iov_base = buf;
+ iov[1].iov_len = len;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 2;
+
+ return (sendmsg(so, &msg, 0));
+}
+int
+rawsend6(int so, char *buf, uint16_t len, struct sockaddr_in6 *sin6, int oldsel, struct cfg *cfg)
+{
+ struct udphdr uh;
+ struct ip6_hdr ip6;
+ struct msghdr msg;
+ struct iovec iov[2];
+
+ memcpy(&ip6.ip6_src, (void*)&(((struct sockaddr_in6 *)&cfg->ss[oldsel])->sin6_addr), sizeof(struct in6_addr));
+ memcpy(&ip6.ip6_dst, (void*)&sin6->sin6_addr, sizeof(struct in6_addr));
+ ip6.ip6_nxt = IPPROTO_UDP;
+
+
+ memset(&uh, 0, sizeof(uh));
+ uh.uh_sport = htons(cfg->port);
+ uh.uh_dport = sin6->sin6_port;
+ uh.uh_ulen = htons(len + sizeof(struct udphdr));
+ uh.uh_sum = 0;
+ uh.uh_sum = udp_cksum6((uint16_t *)buf, \
+ len + sizeof(struct udphdr), &ip6, &uh);
+
+#ifdef __linux__
+ sin6->sin6_port = htons(IPPROTO_UDP);
+#endif
+
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_name = sin6;
+ msg.msg_namelen = sizeof(struct sockaddr_in6);
+
+ iov[0].iov_base = &uh;
+ iov[0].iov_len = sizeof(struct udphdr);
+ iov[1].iov_base = buf;
+ iov[1].iov_len = len;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 2;
+
+ return (sendmsg(so, &msg, 0));
}
blob - 439c9c17abce6f182b3f27eb567d0257aceb5179
blob + e7fd27c26f5585b6fb468c7fb4bb4f326281cc01
--- reply.c
+++ reply.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: reply.c,v 1.109 2020/07/20 08:26:53 pjp Exp $
+ * $Id: reply.c,v 1.110 2020/07/21 18:19:58 pjp Exp $
*/
#include <sys/types.h>
@@ -112,36 +112,36 @@ extern int dn_contains(char *, int, char *, int);
u_int16_t create_anyreply(struct sreply *, char *, int, int, int);
-int reply_generic(struct sreply *, ddDB *);
-int reply_a(struct sreply *, ddDB *);
-int reply_nsec3(struct sreply *, ddDB *);
-int reply_nsec3param(struct sreply *, ddDB *);
-int reply_nsec(struct sreply *, ddDB *);
-int reply_dnskey(struct sreply *, ddDB *);
-int reply_ds(struct sreply *, ddDB *);
-int reply_rrsig(struct sreply *, ddDB *);
-int reply_aaaa(struct sreply *, ddDB *);
-int reply_mx(struct sreply *, ddDB *);
-int reply_ns(struct sreply *, ddDB *);
-int reply_notimpl(struct sreply *, ddDB *);
-int reply_nxdomain(struct sreply *, ddDB *);
-int reply_noerror(struct sreply *, ddDB *);
-int reply_badvers(struct sreply *, ddDB *);
-int reply_nodata(struct sreply *, ddDB *);
-int reply_soa(struct sreply *, ddDB *);
-int reply_ptr(struct sreply *, ddDB *);
-int reply_txt(struct sreply *, ddDB *);
-int reply_version(struct sreply *, ddDB *);
-int reply_srv(struct sreply *, ddDB *);
-int reply_naptr(struct sreply *, ddDB *);
-int reply_sshfp(struct sreply *, ddDB *);
-int reply_tlsa(struct sreply *, ddDB *);
-int reply_cname(struct sreply *, ddDB *);
-int reply_any(struct sreply *, ddDB *);
-int reply_refused(struct sreply *, ddDB *);
-int reply_fmterror(struct sreply *, ddDB *);
-int reply_notauth(struct sreply *, ddDB *);
-int reply_notify(struct sreply *, ddDB *);
+int reply_generic(struct sreply *, int *, ddDB *);
+int reply_a(struct sreply *, int *, ddDB *);
+int reply_nsec3(struct sreply *, int *, ddDB *);
+int reply_nsec3param(struct sreply *, int *, ddDB *);
+int reply_nsec(struct sreply *, int *, ddDB *);
+int reply_dnskey(struct sreply *, int *, ddDB *);
+int reply_ds(struct sreply *, int *, ddDB *);
+int reply_rrsig(struct sreply *, int *, ddDB *);
+int reply_aaaa(struct sreply *, int *, ddDB *);
+int reply_mx(struct sreply *, int *, ddDB *);
+int reply_ns(struct sreply *, int *, ddDB *);
+int reply_notimpl(struct sreply *, int *, ddDB *);
+int reply_nxdomain(struct sreply *, int *, ddDB *);
+int reply_noerror(struct sreply *, int *, ddDB *);
+int reply_badvers(struct sreply *, int *, ddDB *);
+int reply_nodata(struct sreply *, int *, ddDB *);
+int reply_soa(struct sreply *, int *, ddDB *);
+int reply_ptr(struct sreply *, int *, ddDB *);
+int reply_txt(struct sreply *, int *, ddDB *);
+int reply_version(struct sreply *, int *, ddDB *);
+int reply_srv(struct sreply *, int *, ddDB *);
+int reply_naptr(struct sreply *, int *, ddDB *);
+int reply_sshfp(struct sreply *, int *, ddDB *);
+int reply_tlsa(struct sreply *, int *, ddDB *);
+int reply_cname(struct sreply *, int *, ddDB *);
+int reply_any(struct sreply *, int *, ddDB *);
+int reply_refused(struct sreply *, int *, ddDB *);
+int reply_fmterror(struct sreply *, int *, ddDB *);
+int reply_notauth(struct sreply *, int *, ddDB *);
+int reply_notify(struct sreply *, int *, ddDB *);
struct rbtree * find_nsec(char *name, int namelen, struct rbtree *, ddDB *db);
int nsec_comp(const void *a, const void *b);
int count_dots(char *name);
@@ -160,7 +160,7 @@ extern uint8_t vslen;
*/
int
-reply_a(struct sreply *sreply, ddDB *db)
+reply_a(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -337,8 +337,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -357,7 +361,7 @@ out:
*/
int
-reply_nsec3param(struct sreply *sreply, ddDB *db)
+reply_nsec3param(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -551,8 +555,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -566,7 +574,7 @@ out:
*/
int
-reply_nsec3(struct sreply *sreply, ddDB *db)
+reply_nsec3(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -622,7 +630,7 @@ reply_nsec3(struct sreply *sreply, ddDB *db)
/* RFC 5155 section 7.2.8 */
/* perhaps we are accompanied by an rrsig */
if (find_rr(rbt, DNS_TYPE_NSEC3) && find_rr(rbt, DNS_TYPE_RRSIG)) {
- return (reply_nxdomain(sreply, db));
+ return (reply_nxdomain(sreply, sretlen, db));
}
odh = (struct dns_header *)&reply[0];
@@ -778,8 +786,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -792,7 +804,7 @@ out:
*/
int
-reply_nsec(struct sreply *sreply, ddDB *db)
+reply_nsec(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -976,8 +988,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -991,7 +1007,7 @@ out:
*/
int
-reply_ds(struct sreply *sreply, ddDB *db)
+reply_ds(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -1176,8 +1192,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -1192,7 +1212,7 @@ out:
*/
int
-reply_dnskey(struct sreply *sreply, ddDB *db)
+reply_dnskey(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -1374,8 +1394,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -1389,7 +1413,7 @@ out:
int
-reply_rrsig(struct sreply *sreply, ddDB *db)
+reply_rrsig(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -1498,8 +1522,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -1514,7 +1542,7 @@ out:
*/
int
-reply_aaaa(struct sreply *sreply, ddDB *db)
+reply_aaaa(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -1674,8 +1702,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -1690,7 +1722,7 @@ out:
*/
int
-reply_mx(struct sreply *sreply, ddDB *db)
+reply_mx(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -2016,8 +2048,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -2030,7 +2066,7 @@ out:
*/
int
-reply_ns(struct sreply *sreply, ddDB *db)
+reply_ns(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -2426,8 +2462,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -2444,7 +2484,7 @@ out:
int
-reply_cname(struct sreply *sreply, ddDB *db)
+reply_cname(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -2770,9 +2810,13 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
- }
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
+ }
}
return (retlen);
@@ -2784,7 +2828,7 @@ out:
*/
int
-reply_ptr(struct sreply *sreply, ddDB *db)
+reply_ptr(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -2961,8 +3005,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -2976,7 +3024,7 @@ out:
int
-reply_soa(struct sreply *sreply, ddDB *db)
+reply_soa(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -3216,8 +3264,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -3231,7 +3283,7 @@ out:
int
-reply_txt(struct sreply *sreply, ddDB *db)
+reply_txt(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -3418,8 +3470,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -3434,7 +3490,7 @@ out:
int
-reply_version(struct sreply *sreply, ddDB *db)
+reply_version(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -3537,8 +3593,12 @@ reply_version(struct sreply *sreply, ddDB *db)
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -3552,7 +3612,7 @@ reply_version(struct sreply *sreply, ddDB *db)
int
-reply_tlsa(struct sreply *sreply, ddDB *db)
+reply_tlsa(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -3728,8 +3788,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -3744,7 +3808,7 @@ out:
int
-reply_sshfp(struct sreply *sreply, ddDB *db)
+reply_sshfp(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -3919,8 +3983,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -3935,7 +4003,7 @@ out:
int
-reply_naptr(struct sreply *sreply, ddDB *db)
+reply_naptr(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -4144,8 +4212,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -4160,7 +4232,7 @@ out:
int
-reply_srv(struct sreply *sreply, ddDB *db)
+reply_srv(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -4340,8 +4412,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -4356,7 +4432,7 @@ out:
int
-reply_notimpl(struct sreply *sreply, ddDB *db)
+reply_notimpl(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -4423,7 +4499,7 @@ reply_notimpl(struct sreply *sreply, ddDB *db)
*/
int
-reply_nxdomain(struct sreply *sreply, ddDB *db)
+reply_nxdomain(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -4516,8 +4592,12 @@ reply_nxdomain(struct sreply *sreply, ddDB *db)
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, len, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, len, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -4817,8 +4897,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -4831,7 +4915,7 @@ out:
*/
int
-reply_refused(struct sreply *sreply, ddDB *db)
+reply_refused(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -4890,8 +4974,12 @@ reply_refused(struct sreply *sreply, ddDB *db)
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -4904,7 +4992,7 @@ reply_refused(struct sreply *sreply, ddDB *db)
*/
int
-reply_notauth(struct sreply *sreply, ddDB *db)
+reply_notauth(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -4970,8 +5058,12 @@ reply_notauth(struct sreply *sreply, ddDB *db)
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -4984,7 +5076,7 @@ reply_notauth(struct sreply *sreply, ddDB *db)
*/
int
-reply_notify(struct sreply *sreply, ddDB *db)
+reply_notify(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -5054,8 +5146,12 @@ reply_notify(struct sreply *sreply, ddDB *db)
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -5067,7 +5163,7 @@ reply_notify(struct sreply *sreply, ddDB *db)
*/
int
-reply_fmterror(struct sreply *sreply, ddDB *db)
+reply_fmterror(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -5134,7 +5230,7 @@ reply_fmterror(struct sreply *sreply, ddDB *db)
*/
int
-reply_noerror(struct sreply *sreply, ddDB *db)
+reply_noerror(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -5217,8 +5313,12 @@ reply_noerror(struct sreply *sreply, ddDB *db)
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, len, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, len, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -5449,8 +5549,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -5458,7 +5562,7 @@ out:
}
int
-reply_any(struct sreply *sreply, ddDB *db)
+reply_any(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -5565,8 +5669,12 @@ skip:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -6704,7 +6812,7 @@ truncate:
*/
int
-reply_badvers(struct sreply *sreply, ddDB *db)
+reply_badvers(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -6774,8 +6882,12 @@ reply_badvers(struct sreply *sreply, ddDB *db)
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
@@ -6790,9 +6902,9 @@ reply_badvers(struct sreply *sreply, ddDB *db)
*/
int
-reply_nodata(struct sreply *sreply, ddDB *db)
+reply_nodata(struct sreply *sreply, int *sretlen, ddDB *db)
{
- return (reply_noerror(sreply, db));
+ return (reply_noerror(sreply, sretlen, db));
}
/*
@@ -6801,7 +6913,7 @@ reply_nodata(struct sreply *sreply, ddDB *db)
*/
int
-reply_generic(struct sreply *sreply, ddDB *db)
+reply_generic(struct sreply *sreply, int *sretlen, ddDB *db)
{
char *reply = sreply->replybuf;
struct dns_header *odh;
@@ -6975,8 +7087,12 @@ out:
}
free(tmpbuf);
} else {
- if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
- dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ if (q->rawsocket) {
+ *sretlen = retlen = outlen;
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
}
}
blob - 77734a4765acb6a3d8738086e496b3211a77b5a7
blob + f5311b6585d81f375d07d2f496cde5521faf94d1
--- util.c
+++ util.c
@@ -27,13 +27,16 @@
*/
/*
- * $Id: util.c,v 1.75 2020/07/19 13:50:06 pjp Exp $
+ * $Id: util.c,v 1.76 2020/07/21 18:19:58 pjp Exp $
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/udp.h>
#include <arpa/inet.h>
#include <netdb.h>
@@ -117,6 +120,8 @@ u_int64_t timethuman(time_t);
char * bitmap2human(char *, int);
int lookup_axfr(FILE *, int, char *, struct soa *, u_int32_t, char *, char *, int *, int *, int *);
int dn_contains(char *name, int len, char *anchorname, int alen);
+uint16_t udp_cksum(u_int16_t *, uint16_t, struct ip *, struct udphdr *);
+uint16_t udp_cksum6(u_int16_t *, uint16_t, struct ip6_hdr *, struct udphdr *);
int bytes_received;
@@ -2352,4 +2357,145 @@ err:
memcpy(buf, save, len);
return (-1);
+}
+
+
+/*
+ * Copyright (c) 1988, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * UDP_CKSUM - compute the ones complement sum of the ones complement of 16 bit
+ * numbers
+ */
+
+
+
+/*
+ * UDP_CKSUM - compute the checksum with a pseudo header of the UDP packet
+ *
+ */
+
+uint16_t
+udp_cksum(u_int16_t *addr, uint16_t len, struct ip *ip, struct udphdr *uh)
+{
+ union {
+ struct ph {
+ in_addr_t src;
+ in_addr_t dst;
+ u_int8_t pad;
+ u_int8_t proto;
+ u_int16_t len;
+ } s __attribute__((packed));
+
+ u_int16_t i[6];
+ } ph;
+
+ int nleft = len - sizeof(struct udphdr); /* we pass the udp header */
+ int sum = 0;
+ u_int16_t *w = &ph.i[0];
+ u_int16_t *u = (u_int16_t *)uh;
+ uint16_t answer;
+
+ memset(&ph, 0, sizeof(ph));
+ memcpy(&ph.s.src, &ip->ip_src.s_addr, sizeof(in_addr_t));
+ memcpy(&ph.s.dst, &ip->ip_dst.s_addr, sizeof(in_addr_t));
+ ph.s.pad = 0;
+ ph.s.proto = ip->ip_p;
+ ph.s.len = uh->uh_ulen;
+ sum = w[0] + w[1] + w[2] + w[3] + w[4] + w[5] + u[0] + u[1] + u[2];
+ w = addr;
+
+ while (nleft > 1) {
+ sum += *w++;
+ nleft -= 2;
+ }
+ if (nleft == 1) {
+ sum += htons(*(u_char *)w << 8);
+ }
+
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+ answer = ~sum;
+ return (answer);
+}
+
+/*
+ * UDP_CKSUM6 - compute the checksum with a pseudo header of the UDP6 packet
+ * RFC 8200 section 8.1
+ */
+
+uint16_t
+udp_cksum6(u_int16_t *addr, uint16_t len, struct ip6_hdr *ip6, struct udphdr *uh)
+{
+ union {
+ struct ph {
+ struct in6_addr src;
+ struct in6_addr dst;
+ u_int32_t len;
+ u_int8_t pad[3];
+ u_int8_t nxt;
+ } s __attribute__((packed));
+
+ u_int16_t i[20];
+ } ph;
+
+ int nleft = len - sizeof(struct udphdr); /* we pass the udp header */
+ int sum;
+ u_int16_t *w = &ph.i[0];
+ u_int16_t *u = (u_int16_t *)uh;
+ uint16_t answer;
+
+ memset(&ph, 0, sizeof(ph));
+ memcpy(&ph.s.src, &ip6->ip6_src, sizeof(struct in6_addr));
+ memcpy(&ph.s.dst, &ip6->ip6_dst, sizeof(struct in6_addr));
+ ph.s.len = htonl(len);
+ ph.s.nxt = ip6->ip6_nxt;
+
+ sum = w[0] + w[1] + w[2] + w[3] + w[4] + w[5] + \
+ w[6] + w[7] + w[8] + w[9] + w[10] + \
+ w[11] + w[12] + w[13] + w[14] + w[15] + \
+ w[16] + w[17] + w[18] + w[19] + u[0] + u[1] + u[2];
+
+ w = addr;
+
+ while (nleft > 1) {
+ sum += *w++;
+ nleft -= 2;
+ }
+ if (nleft == 1) {
+ sum += htons(*(u_char *)w << 8);
+ }
+
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+ answer = ~sum;
+ return (answer);
}
repomaster@centroid.eu