First attempt to do IPv6 on the resolver

Initial
Stephane Bortzmeyer 20 years ago
parent ccc43a77fe
commit 1abc617ba3

@ -1,21 +1,22 @@
/* /*
* DNS plugin. * DNS plugin. $Id$
* $Id$
*/ */
#define IN_PLUGIN #define IN_PLUGIN
#include "../../echoping.h" #include "../../echoping.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/nameser.h> #include <arpa/nameser.h>
#include <resolv.h> #include <resolv.h>
struct addrinfo name_server; struct addrinfo name_server;
poptContext dns_poptcon; poptContext dns_poptcon;
char *request; char *request;
int type; int type;
boolean use_tcp = FALSE; boolean use_tcp = FALSE;
boolean no_recurse = FALSE; boolean no_recurse = FALSE;
/* nsError stolen from Liu & Albitz check_soa (in their book "DNS and BIND") */ /* nsError stolen from Liu & Albitz check_soa (in their book "DNS and BIND") */
@ -32,156 +33,173 @@ boolean no_recurse = FALSE;
* strings. * * strings. *
****************************************************************/ ****************************************************************/
int int
nsError (error, domain) nsError(error, domain)
int error; int error;
char *domain; char *domain;
{ {
switch (error) switch (error) {
{ case HOST_NOT_FOUND:
case HOST_NOT_FOUND: err_ret("Unknown domain: %s\n", domain);
err_ret ("Unknown domain: %s\n", domain); return -1;
return -1; case NO_DATA:
case NO_DATA: err_ret("No records for %s in the Answer section\n", domain);
err_ret ("No records for %s in the Answer section\n", domain); return -1;
return -1; case TRY_AGAIN:
case TRY_AGAIN: err_ret("No response for query\n");
err_ret ("No response for query\n"); return -2;
return -2; default:
default: err_ret("Unexpected error\n");
err_ret ("Unexpected error\n"); return -1;
return -1; }
}
} }
void void
dns_usage (const char *msg) dns_usage(const char *msg)
{ {
if (msg) if (msg) {
{ fprintf(stderr, "Error: %s\n", msg);
fprintf (stderr, "Error: %s\n", msg); }
} poptPrintUsage(dns_poptcon, stderr, 0);
poptPrintUsage (dns_poptcon, stderr, 0); fprintf(stderr, " request\n");
fprintf (stderr, " request\n"); exit(1);
exit (1);
} }
char * char *
init (const int argc, const char **argv) init(const int argc, const char **argv)
{ {
int value; int value;
char *hostname; char *hostname;
char *msg = malloc (256); char *msg = malloc(256);
char *type_name, *upper_type_name = NULL; char *type_name, *upper_type_name = NULL;
/* popt variables */ /* popt variables */
struct poptOption options[] = { struct poptOption options[] = {
{"type", 't', POPT_ARG_STRING, &type_name, 0, {"type", 't', POPT_ARG_STRING, &type_name, 0,
"Type of resources queried (A, MX, SOA, etc)", "Type of resources queried (A, MX, SOA, etc)",
"type"}, "type"},
{"tcp", NULL, POPT_ARG_NONE, &use_tcp, 0, {"tcp", NULL, POPT_ARG_NONE, &use_tcp, 0,
"Use TCP for the request (virtual circuit)", "Use TCP for the request (virtual circuit)",
"tcp"}, "tcp"},
{"no-recurse", NULL, POPT_ARG_NONE, &no_recurse, 0, {"no-recurse", NULL, POPT_ARG_NONE, &no_recurse, 0,
"Do not ask recursion", "Do not ask recursion",
"no-recurse"}, "no-recurse"},
POPT_AUTOHELP POPT_TABLEEND POPT_AUTOHELP POPT_TABLEEND
}; };
dns_poptcon = poptGetContext (NULL, argc, dns_poptcon = poptGetContext(NULL, argc,
argv, options, POPT_CONTEXT_KEEP_FIRST); argv, options, POPT_CONTEXT_KEEP_FIRST);
while ((value = poptGetNextOpt (dns_poptcon)) > 0) while ((value = poptGetNextOpt(dns_poptcon)) > 0) {
{ if (value < -1) {
if (value < -1) sprintf(msg, "%s: %s",
{ poptBadOption(dns_poptcon, POPT_BADOPTION_NOALIAS),
sprintf (msg, "%s: %s", poptStrerror(value));
poptBadOption (dns_poptcon, POPT_BADOPTION_NOALIAS), dns_usage(msg);
poptStrerror (value)); }
dns_usage (msg);
} }
} hostname = (char *)poptGetArg(dns_poptcon); /* Not used */
hostname = (char *) poptGetArg (dns_poptcon); /* Not used */ request = (char *)poptGetArg(dns_poptcon);
request = (char *) poptGetArg (dns_poptcon); if (request == NULL)
if (request == NULL) dns_usage("Mandatory request missing");
dns_usage ("Mandatory request missing"); if ((type_name == NULL) || !strcmp(type_name, ""))
if ((type_name == NULL) || !strcmp (type_name, "")) type = T_A;
type = T_A; else {
else upper_type_name = to_upper(type_name);
{ /*
upper_type_name = to_upper (type_name); * TODO: a better algorithm. Use dns_rdatatype_fromtext in
/* TODO: a better algorithm. Use dns_rdatatype_fromtext in BIND ? */ * BIND ?
if (!strcmp (upper_type_name, "A")) */
type = T_A; if (!strcmp(upper_type_name, "A"))
else if (!strcmp (upper_type_name, "AAAA")) type = T_A;
type = T_AAAA; else if (!strcmp(upper_type_name, "AAAA"))
else if (!strcmp (upper_type_name, "NS")) type = T_AAAA;
type = T_NS; else if (!strcmp(upper_type_name, "NS"))
else if (!strcmp (upper_type_name, "SOA")) type = T_NS;
type = T_SOA; else if (!strcmp(upper_type_name, "SOA"))
else if (!strcmp (upper_type_name, "MX")) type = T_SOA;
type = T_MX; else if (!strcmp(upper_type_name, "MX"))
else if (!strcmp (upper_type_name, "SRV")) type = T_MX;
type = T_SRV; else if (!strcmp(upper_type_name, "SRV"))
else if (!strcmp (upper_type_name, "CNAME")) type = T_SRV;
type = T_CNAME; else if (!strcmp(upper_type_name, "CNAME"))
else if (!strcmp (upper_type_name, "PTR")) type = T_CNAME;
type = T_PTR; else if (!strcmp(upper_type_name, "PTR"))
else if (!strcmp (upper_type_name, "TXT")) type = T_PTR;
type = T_TXT; else if (!strcmp(upper_type_name, "TXT"))
else type = T_TXT;
dns_usage ("Unknown type"); else
} dns_usage("Unknown type");
return "domain"; }
return "domain";
} }
void void
start (struct addrinfo *res) start(struct addrinfo * res)
{ {
struct sockaddr name_server_sockaddr; struct sockaddr name_server_sockaddr;
struct sockaddr_in name_server_sockaddr_in; struct sockaddr_in name_server_sockaddr_in;
name_server = *res; struct sockaddr_in6 name_server_sockaddr_in6;
name_server_sockaddr = *name_server.ai_addr; name_server = *res;
/* Converts a generic sockaddr to an IPv4 sockaddr_in */ name_server_sockaddr = *name_server.ai_addr;
(void) memcpy ((void *) &name_server_sockaddr_in, &name_server_sockaddr, if (name_server_sockaddr.sa_family == AF_INET) {
sizeof (struct sockaddr)); /* Converts a generic sockaddr to an IPv4 sockaddr_in */
if (res_init () < 0) (void)memcpy((void *)&name_server_sockaddr_in, &name_server_sockaddr,
err_sys ("res_init"); sizeof(struct sockaddr));
_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 */ } else if (name_server_sockaddr.sa_family == AF_INET6) {
_res.nscount = 1; #ifdef HAVE_RES_EXT
_res.options &= ~(RES_DNSRCH | RES_DEFNAMES | RES_NOALIASES); /* Converts a generic sockaddr to an IPv6 sockaddr_in6 */
if (use_tcp) (void)memcpy((void *)&name_server_sockaddr_in6, &name_server_sockaddr,
{ sizeof(struct sockaddr));
_res.options |= RES_USEVC; #else
} err_quit("IPv6 name servers not supported on this platform, may be you should use the -4 option");
if (no_recurse) #endif
{ } else {
_res.options &= ~RES_RECURSE; err_quit("Unknown family for address of the server");
} }
if (res_init() < 0)
err_sys("res_init");
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) {
_res.options |= RES_USEVC;
}
if (no_recurse) {
_res.options &= ~RES_RECURSE;
}
} }
int int
execute () execute()
{ {
union union {
{ HEADER hdr; /* defined in resolv.h */
HEADER hdr; /* defined in resolv.h */ u_char buf[PACKETSZ]; /* defined in arpa/nameser.h */
u_char buf[PACKETSZ]; /* defined in arpa/nameser.h */ } response; /* response buffers */
} response; /* response buffers */ int response_length; /* buffer length */
int response_length; /* buffer length */ if ((response_length = res_query(request, /* the domain we care
if ((response_length = res_query (request, /* the domain we care about */ * about */
C_IN, /* Internet class records */ C_IN, /* Internet class records */
type, (u_char *) & response, /*response buffer */ type, (u_char *) & response, /* response buffer */
sizeof (response))) /*buffer size */ sizeof(response))) /* buffer size */
< 0) <0) { /* If negative */
{ /*If negative */ nsError(h_errno, request); /* report the error */
nsError (h_errno, request); /* report the error */ if (h_errno == TRY_AGAIN)
if (h_errno == TRY_AGAIN) return -1; /* More luck next time? */
return -1; /* More luck next time? */ else
else return -2; /* Give in */
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
return 0; * in the authority section (delegation info)
*/
return 0;
} }
void void
terminate () terminate()
{ {
} }

Loading…
Cancel
Save