|
|
|
@ -1,11 +1,12 @@
|
|
|
|
|
/*
|
|
|
|
|
* DNS plugin.
|
|
|
|
|
* $Id$
|
|
|
|
|
* DNS plugin. $Id$
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define IN_PLUGIN
|
|
|
|
|
#include "../../echoping.h"
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#endif
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <arpa/nameser.h>
|
|
|
|
|
#include <resolv.h>
|
|
|
|
@ -36,8 +37,7 @@ nsError (error, domain)
|
|
|
|
|
int error;
|
|
|
|
|
char *domain;
|
|
|
|
|
{
|
|
|
|
|
switch (error)
|
|
|
|
|
{
|
|
|
|
|
switch (error) {
|
|
|
|
|
case HOST_NOT_FOUND:
|
|
|
|
|
err_ret("Unknown domain: %s\n", domain);
|
|
|
|
|
return -1;
|
|
|
|
@ -56,8 +56,7 @@ nsError (error, domain)
|
|
|
|
|
void
|
|
|
|
|
dns_usage(const char *msg)
|
|
|
|
|
{
|
|
|
|
|
if (msg)
|
|
|
|
|
{
|
|
|
|
|
if (msg) {
|
|
|
|
|
fprintf(stderr, "Error: %s\n", msg);
|
|
|
|
|
}
|
|
|
|
|
poptPrintUsage(dns_poptcon, stderr, 0);
|
|
|
|
@ -87,10 +86,8 @@ init (const int argc, const char **argv)
|
|
|
|
|
};
|
|
|
|
|
dns_poptcon = poptGetContext(NULL, argc,
|
|
|
|
|
argv, options, POPT_CONTEXT_KEEP_FIRST);
|
|
|
|
|
while ((value = poptGetNextOpt (dns_poptcon)) > 0)
|
|
|
|
|
{
|
|
|
|
|
if (value < -1)
|
|
|
|
|
{
|
|
|
|
|
while ((value = poptGetNextOpt(dns_poptcon)) > 0) {
|
|
|
|
|
if (value < -1) {
|
|
|
|
|
sprintf(msg, "%s: %s",
|
|
|
|
|
poptBadOption(dns_poptcon, POPT_BADOPTION_NOALIAS),
|
|
|
|
|
poptStrerror(value));
|
|
|
|
@ -103,10 +100,12 @@ init (const int argc, const char **argv)
|
|
|
|
|
dns_usage("Mandatory request missing");
|
|
|
|
|
if ((type_name == NULL) || !strcmp(type_name, ""))
|
|
|
|
|
type = T_A;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
else {
|
|
|
|
|
upper_type_name = to_upper(type_name);
|
|
|
|
|
/* TODO: a better algorithm. Use dns_rdatatype_fromtext in BIND ? */
|
|
|
|
|
/*
|
|
|
|
|
* TODO: a better algorithm. Use dns_rdatatype_fromtext in
|
|
|
|
|
* BIND ?
|
|
|
|
|
*/
|
|
|
|
|
if (!strcmp(upper_type_name, "A"))
|
|
|
|
|
type = T_A;
|
|
|
|
|
else if (!strcmp(upper_type_name, "AAAA"))
|
|
|
|
@ -136,22 +135,39 @@ start (struct addrinfo *res)
|
|
|
|
|
{
|
|
|
|
|
struct sockaddr name_server_sockaddr;
|
|
|
|
|
struct sockaddr_in name_server_sockaddr_in;
|
|
|
|
|
struct sockaddr_in6 name_server_sockaddr_in6;
|
|
|
|
|
name_server = *res;
|
|
|
|
|
name_server_sockaddr = *name_server.ai_addr;
|
|
|
|
|
if (name_server_sockaddr.sa_family == AF_INET) {
|
|
|
|
|
/* Converts a generic sockaddr to an IPv4 sockaddr_in */
|
|
|
|
|
(void)memcpy((void *)&name_server_sockaddr_in, &name_server_sockaddr,
|
|
|
|
|
sizeof(struct sockaddr));
|
|
|
|
|
} else if (name_server_sockaddr.sa_family == AF_INET6) {
|
|
|
|
|
#ifdef HAVE_RES_EXT
|
|
|
|
|
/* Converts a generic sockaddr to an IPv6 sockaddr_in6 */
|
|
|
|
|
(void)memcpy((void *)&name_server_sockaddr_in6, &name_server_sockaddr,
|
|
|
|
|
sizeof(struct sockaddr));
|
|
|
|
|
#else
|
|
|
|
|
err_quit("IPv6 name servers not supported on this platform, may be you should use the -4 option");
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
|
|
|
|
err_quit("Unknown family for address of the server");
|
|
|
|
|
}
|
|
|
|
|
if (res_init() < 0)
|
|
|
|
|
err_sys("res_init");
|
|
|
|
|
_res.nsaddr_list[0] = name_server_sockaddr_in; /* TODO: and IPv6? We now if we have _res_ext (xBSD) so we should use HAVE_RES_EXT here */
|
|
|
|
|
if (name_server_sockaddr.sa_family == AF_INET) {
|
|
|
|
|
_res.nsaddr_list[0] = name_server_sockaddr_in;
|
|
|
|
|
} else if (name_server_sockaddr.sa_family == AF_INET6) {
|
|
|
|
|
#ifdef HAVE_RES_EXT
|
|
|
|
|
(void)memcpy(_res_ext.nsaddr_list, &name_server_sockaddr_in6, sizeof(struct sockaddr_in6));
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
_res.nscount = 1;
|
|
|
|
|
_res.options &= ~(RES_DNSRCH | RES_DEFNAMES | RES_NOALIASES);
|
|
|
|
|
if (use_tcp)
|
|
|
|
|
{
|
|
|
|
|
if (use_tcp) {
|
|
|
|
|
_res.options |= RES_USEVC;
|
|
|
|
|
}
|
|
|
|
|
if (no_recurse)
|
|
|
|
|
{
|
|
|
|
|
if (no_recurse) {
|
|
|
|
|
_res.options &= ~RES_RECURSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -159,25 +175,27 @@ start (struct addrinfo *res)
|
|
|
|
|
int
|
|
|
|
|
execute()
|
|
|
|
|
{
|
|
|
|
|
union
|
|
|
|
|
{
|
|
|
|
|
union {
|
|
|
|
|
HEADER hdr; /* defined in resolv.h */
|
|
|
|
|
u_char buf[PACKETSZ]; /* defined in arpa/nameser.h */
|
|
|
|
|
} response; /* response buffers */
|
|
|
|
|
int response_length; /* buffer length */
|
|
|
|
|
if ((response_length = res_query (request, /* the domain we care about */
|
|
|
|
|
if ((response_length = res_query(request, /* the domain we care
|
|
|
|
|
* about */
|
|
|
|
|
C_IN, /* Internet class records */
|
|
|
|
|
type, (u_char *) & response, /* response buffer */
|
|
|
|
|
sizeof(response))) /* buffer size */
|
|
|
|
|
< 0)
|
|
|
|
|
{ /*If negative */
|
|
|
|
|
<0) { /* If negative */
|
|
|
|
|
nsError(h_errno, request); /* report the error */
|
|
|
|
|
if (h_errno == TRY_AGAIN)
|
|
|
|
|
return -1; /* More luck next time? */
|
|
|
|
|
else
|
|
|
|
|
return -2; /* Give in */
|
|
|
|
|
}
|
|
|
|
|
/* TODO: better analysis of the replies. For instance, replies can be in the authority section (delegation info) */
|
|
|
|
|
/*
|
|
|
|
|
* TODO: better analysis of the replies. For instance, replies can be
|
|
|
|
|
* in the authority section (delegation info)
|
|
|
|
|
*/
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|