/* darkstat 3
- * copyright (c) 2001-2008 Emil Mikulic.
+ * copyright (c) 2001-2011 Emil Mikulic.
*
* dns.c: synchronous DNS in a child process.
*
* GNU General Public License version 2. (see COPYING.GPL)
*/
-#include "darkstat.h"
+#include "cdefs.h"
#include "conv.h"
#include "decode.h"
#include "dns.h"
#include "queue.h"
#include "str.h"
#include "tree.h"
+#include "bsd.h" /* for setproctitle, strlcpy */
#include <sys/param.h>
#include <sys/socket.h>
struct dns_reply {
struct addr addr;
int error; /* for gai_strerror(), or 0 if no error */
- char name[MAXHOSTNAMELEN];
+ char name[256]; /* http://tools.ietf.org/html/rfc1034#section-3.1 */
};
void
/* Return successful reply. */
memcpy(ipaddr, &reply.addr, sizeof(*ipaddr));
-#if DARKSTAT_USES_HOSTENT
- if (reply.error != 0)
- xasprintf(name, "(%s)", hstrerror(reply.error));
- else
- *name = xstrdup(reply.name);
-#else /* !DARKSTAT_USES_HOSTENT */
if (reply.error != 0) {
/* Identify common special cases. */
const char *type = "none";
type = "site-local";
else if (IN6_IS_ADDR_MULTICAST(&reply.addr.ip.v6))
type = "multicast";
- } else { /* AF_INET */
- if (IN_MULTICAST(reply.addr.ip.v4))
+ } else {
+ assert(reply.addr.family == IPv4);
+ if (IN_MULTICAST(htonl(reply.addr.ip.v4)))
type = "multicast";
}
xasprintf(name, "(%s)", type);
}
else /* Correctly resolved name. */
*name = xstrdup(reply.name);
-#endif /* !DARKSTAT_USES_HOSTENT */
dns_unqueue(&reply.addr);
return (1);
{
struct addr ip;
-#ifdef HAVE_SETPROCTITLE
setproctitle("DNS child");
-#endif
fd_set_nonblock(sock[CHILD]);
verbosef("DNS child entering main DNS loop");
for (;;) {
/* Process queue. */
if (dequeue(&ip)) {
struct dns_reply reply;
-#if DARKSTAT_USES_HOSTENT
- struct hostent *he;
-
- memcpy(&reply.addr, &ip, sizeof(reply.addr));
- he = gethostbyaddr((char *)&ip.addr.ip, sizeof(ip.addr.ip), ip.af); /* TODO MEA */
-
- /* On some platforms (for example Linux with GLIBC 2.3.3), h_errno
- * will be non-zero here even though the lookup succeeded.
- */
- if (he == NULL) {
- reply.name[0] = '\0';
- reply.error = h_errno;
- } else {
- assert(sizeof(reply.name) > sizeof(char *)); /* not just a ptr */
- strlcpy(reply.name, he->h_name, sizeof(reply.name));
- reply.error = 0;
- }
- fd_set_block(sock[CHILD]);
- xwrite(sock[CHILD], &reply, sizeof(reply));
- verbosef("DNS: %s is %s", addr_to_str(&reply.addr),
- (h_errno == 0)?reply.name:hstrerror(h_errno));
-#else /* !DARKSTAT_USES_HOSTENT */
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
+ struct hostent *he;
char host[NI_MAXHOST];
int ret, flags;
sin.sin_addr.s_addr = ip.ip.v4;
ret = getnameinfo((struct sockaddr *) &sin, sizeof(sin),
host, sizeof(host), NULL, 0, flags);
+ if (ret == EAI_FAMILY) {
+ verbosef("getnameinfo error %s, trying gethostbyname",
+ gai_strerror(ret));
+ he = gethostbyaddr(&sin.sin_addr.s_addr,
+ sizeof(sin.sin_addr.s_addr), sin.sin_family);
+ if (he == NULL) {
+ ret = EAI_FAIL;
+ verbosef("gethostbyname error %s", hstrerror(h_errno));
+ } else {
+ ret = 0;
+ strlcpy(host, he->h_name, sizeof(host));
+ }
+ }
break;
case IPv6:
sin6.sin6_family = AF_INET6;
xwrite(sock[CHILD], &reply, sizeof(reply));
verbosef("DNS: %s is \"%s\".", addr_to_str(&reply.addr),
(ret == 0) ? reply.name : gai_strerror(ret));
-#endif /* !DARKSTAT_USES_HOSTENT */
}
}
}