Re: dns -server looks at servers besides the one specified by -server

Juergen Schoenwaelder (schoenw@cs.utwente.nl)
Mon, 4 Nov 1996 20:22:55 +0100

Karl Lehenbauer <karl@hammer1.ops.NeoSoft.com> said:

Karl> If I do a "dns -server 206.109.5.76 address
Karl> hammer1.ops.neosoft.com", it works, but it shouldn't, because
Karl> there is no host at 206.109.5.76.

Karl> I browsed through tnmDns.c for a few minutes but did not see
Karl> it. I would guess that after it fails on the specified
Karl> server, it is trying the default ones.

Karl> For net management purposes, it would be nice to be able to
Karl> see the failure of the lookup of the specified address.

I agree. Indeed, there were even more bugs in the implementation of
the -server option. Below is a patch which makes the -server option
accept and return a Tcl list if multiple DNS servers are configured.
It also fixes some prototypes to make tnmDns.c happy with bind 4.9.4
prototypes. Let me know if this patch still fails to make the dns
command work as you expect it to work.
Juergen

*** tnm/generic/tnmDns.c.orig Tue Oct 8 13:50:13 1996
--- tnm/generic/tnmDns.c Mon Nov 4 20:15:47 1996
***************
*** 17,28 ****
#include <resolv.h>

/*
! * Max # of return hostnames/ip-addrs:
*/

#define MAXRESULT 10

/*
* Query and reply structure.
*/

--- 17,36 ----
#include <resolv.h>

/*
! * Max # of returned hostnames or IP addresses:
*/

#define MAXRESULT 10

/*
+ * The default Internet name server port.
+ */
+
+ #ifndef NAMESERVER_PORT
+ #define NAMESERVER_PORT 53
+ #endif
+
+ /*
* Query and reply structure.
*/

***************
*** 54,60 ****
typedef struct DnsControl {
int retries; /* Default number of retries. */
int timeout; /* Default timeout in seconds. */
! struct in_addr server; /* Default DNS server. */
} DnsControl;

/*
--- 62,70 ----
typedef struct DnsControl {
int retries; /* Default number of retries. */
int timeout; /* Default timeout in seconds. */
! int nscount; /* Number of name servers. */
! struct sockaddr_in /* List of default name server */
! nsaddr_list[MAXNS]; /* addresses. */
} DnsControl;

/*
***************
*** 65,72 ****
AssocDeleteProc _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp));

static void
! DnsInit _ANSI_ARGS_((int timeout, int retries,
! struct in_addr *server));
static int
DnsGetHostName _ANSI_ARGS_((Tcl_Interp *interp, char *hname));

--- 75,82 ----
AssocDeleteProc _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp));

static void
! DnsInit _ANSI_ARGS_((DnsControl *control));
!
static int
DnsGetHostName _ANSI_ARGS_((Tcl_Interp *interp, char *hname));

***************
*** 128,136 ****
*
* DnsInit --
*
! * This procedure initializes the resolver and gets the default
! * DNS server from the resolver library. It also initializes the
! * default retries/timeout values.
*
* Results:
* None.
--- 138,144 ----
*
* DnsInit --
*
! * This procedure initializes the resolver parameters.
*
* Results:
* None.
***************
*** 142,169 ****
*/

static void
! DnsInit(timeout, retries, server)
! int timeout;
! int retries;
! struct in_addr *server;
{
! static int initialized = 0;

! if (! initialized) {
! res_init();
! _res.options |= RES_RECURSE | RES_DNSRCH | RES_DEFNAMES | RES_AAONLY;
! initialized = 1;
! if (_res.nscount > 0) {
! *server = _res.nsaddr.sin_addr;
! }
! if (! server->s_addr) {
! server->s_addr = htonl(INADDR_LOOPBACK);
! }
}
-
- _res.retrans = timeout;
- _res.retry = retries + 1;
- _res.nsaddr.sin_addr = *server;
}

/*
--- 150,166 ----
*/

static void
! DnsInit(control)
! DnsControl *control;
{
! int i;

! _res.retrans = control->timeout;
! _res.retry = control->retries + 1;
! _res.nscount = control->nscount;
! for (i = 0; i < control->nscount; i++) {
! _res.nsaddr_list[i] = control->nsaddr_list[i];
}
}

/*
***************
*** 231,237 ****
long ttl;
querybuf *q;
u_char *ptr;
! char *eom;

/*
* Initialize the query_result. Note, query_result->u.str[0]
--- 228,234 ----
long ttl;
querybuf *q;
u_char *ptr;
! u_char *eom;

/*
* Initialize the query_result. Note, query_result->u.str[0]
***************
*** 249,256 ****
*/

qlen = res_mkquery(QUERY, query_string, C_IN, query_type,
! (char *) 0, 0, 0,
! (char *) &query, sizeof(query));
if (qlen <= 0) {
query_result->n = -1;
strcpy(query_result->u.str[0], "cannot make query");
--- 246,253 ----
*/

qlen = res_mkquery(QUERY, query_string, C_IN, query_type,
! (u_char *) 0, 0, 0,
! (u_char *) &query, sizeof(query));
if (qlen <= 0) {
query_result->n = -1;
strcpy(query_result->u.str[0], "cannot make query");
***************
*** 261,268 ****
* res_send(msg, msglen, answer, anslen)
*/

! alen = res_send((char *) &query, qlen,
! (char *) &answer, sizeof (answer));
if (alen <= 0) {
query_result->n = -1;
strcpy(query_result->u.str[0], "cannot send query");
--- 258,265 ----
* res_send(msg, msglen, answer, anslen)
*/

! alen = res_send((u_char *) &query, qlen,
! (u_char *) &answer, sizeof (answer));
if (alen <= 0) {
query_result->n = -1;
strcpy(query_result->u.str[0], "cannot send query");
***************
*** 279,295 ****

if (q->qb1.rcode != 0) {
if (q->qb1.rcode == 1)
! strcpy (query_result->u.str[0], "format error");
else if (q->qb1.rcode == 2)
! strcpy (query_result->u.str[0], "server failure");
else if (q->qb1.rcode == 3)
! strcpy (query_result->u.str[0], "domainname error");
else if (q->qb1.rcode == 4)
! strcpy (query_result->u.str[0], "not implemented");
else if (q->qb1.rcode == 5)
! strcpy (query_result->u.str[0], "query refused");
else
! strcpy (query_result->u.str[0], "unknown error");
query_result->type = query_type;
query_result->n = -1;
return;
--- 276,292 ----

if (q->qb1.rcode != 0) {
if (q->qb1.rcode == 1)
! strcpy(query_result->u.str[0], "format error");
else if (q->qb1.rcode == 2)
! strcpy(query_result->u.str[0], "server failure");
else if (q->qb1.rcode == 3)
! strcpy(query_result->u.str[0], "non existent domain");
else if (q->qb1.rcode == 4)
! strcpy(query_result->u.str[0], "not implemented");
else if (q->qb1.rcode == 5)
! strcpy(query_result->u.str[0], "query refused");
else
! sprintf(query_result->u.str[0], "unknown error %d", q->qb1.rcode);
query_result->type = query_type;
query_result->n = -1;
return;
***************
*** 307,313 ****
* give some help (seems to be needed for very ole sun-code...
*/

! eom = (char *) &answer + alen;
*eom++ = 0;

ptr = (u_char *) q->qb2;
--- 304,310 ----
* give some help (seems to be needed for very ole sun-code...
*/

! eom = (u_char *) &answer + alen;
*eom++ = 0;

ptr = (u_char *) q->qb2;
***************
*** 338,344 ****
* dn_expand(msg, msglen, comp_dn, exp_dn, length)
*/

! llen = dn_expand((char *) q, eom, ptr, lbuf, sizeof(lbuf));
if (llen < 0) {
/* XXX: what to do ? */
return;
--- 335,341 ----
* dn_expand(msg, msglen, comp_dn, exp_dn, length)
*/

! llen = dn_expand((u_char *) q, eom, ptr, lbuf, sizeof(lbuf));
if (llen < 0) {
/* XXX: what to do ? */
return;
***************
*** 356,362 ****

if (type == T_NS) {

! len = dn_expand((char *) q, eom, ptr, buf, sizeof(buf));
if (len < 0) {
return;
}
--- 353,359 ----

if (type == T_NS) {

! len = dn_expand((u_char *) q, eom, ptr, buf, sizeof(buf));
if (len < 0) {
return;
}
***************
*** 379,391 ****
* [ MNAME, RNAME, SERIAL, REFRESH, RETRY, EXPIRE, MINIMUM ]
*/

! len = dn_expand((char *) q, eom, ptr, auth_buf, sizeof(auth_buf));
if (len < 0) {
return;
}
ptr += len;

! len = dn_expand((char *) q, eom, ptr, buf, sizeof(buf));
if (len < 0) {
return;
}
--- 376,388 ----
* [ MNAME, RNAME, SERIAL, REFRESH, RETRY, EXPIRE, MINIMUM ]
*/

! len = dn_expand((u_char*) q, eom, ptr, auth_buf, sizeof(auth_buf));
if (len < 0) {
return;
}
ptr += len;

! len = dn_expand((u_char *) q, eom, ptr, buf, sizeof(buf));
if (len < 0) {
return;
}
***************
*** 404,412 ****

} else if (type == T_HINFO) {

- int i;
for (i = 0; i < 1; i++) { /* XXX: ??? */
! len = dn_expand((char *) q, eom, ptr, buf, sizeof(buf));
if (len < 0) {
return;
}
--- 401,408 ----

} else if (type == T_HINFO) {

for (i = 0; i < 1; i++) { /* XXX: ??? */
! len = dn_expand((u_char *) q, eom, ptr, buf, sizeof(buf));
if (len < 0) {
return;
}
***************
*** 421,427 ****

} else if (type == T_PTR) {

! len = dn_expand((char *) q, eom, ptr, buf, sizeof(buf));
if (len < 0) {
return;
}
--- 417,423 ----

} else if (type == T_PTR) {

! len = dn_expand((u_char *) q, eom, ptr, buf, sizeof(buf));
if (len < 0) {
return;
}
***************
*** 437,443 ****
unsigned prio;
GETSHORT (prio, ptr);

! len = dn_expand((char *) q, eom, ptr, buf, sizeof(buf));
if (len < 0) {
return;
}
--- 433,439 ----
unsigned prio;
GETSHORT (prio, ptr);

! len = dn_expand((u_char *) q, eom, ptr, buf, sizeof(buf));
if (len < 0) {
return;
}
***************
*** 913,934 ****
char *argv[];
{
char *cmd = argv[0];
!
! int actRetries = -1; /* actually used # of retries */
! int actTimeout = -1; /* actually used timeout in s */
! struct in_addr actServer; /* actually used DNS server */
! char *serverName = NULL; /* name of new DNS server */

DnsControl *control = (DnsControl *)
Tcl_GetAssocData(interp, tnmDnsControl, NULL);

if (! control) {
control = (DnsControl *) ckalloc(sizeof(DnsControl));
control->retries = 2;
control->timeout = 2;
Tcl_SetAssocData(interp, tnmDnsControl, AssocDeleteProc,
(ClientData) control);
! DnsInit(control->timeout, control->retries, &control->server);
}

argc--; argv++;
--- 909,949 ----
char *argv[];
{
char *cmd = argv[0];
! int i, code;
! DnsControl dnsParams; /* Actually used DNS parameters. */

DnsControl *control = (DnsControl *)
Tcl_GetAssocData(interp, tnmDnsControl, NULL);

if (! control) {
control = (DnsControl *) ckalloc(sizeof(DnsControl));
+ res_init();
+ _res.options |= RES_RECURSE | RES_DNSRCH | RES_DEFNAMES | RES_AAONLY;
control->retries = 2;
control->timeout = 2;
+ control->nscount = _res.nscount;
+ for (i = 0; i < _res.nscount; i++) {
+ control->nsaddr_list[i] = _res.nsaddr_list[i];
+ }
+ if (control->nscount == 0
+ || (control->nscount == 1
+ && control->nsaddr_list[0].sin_addr.s_addr
+ == htonl(INADDR_ANY))) {
+ control->nscount = 1;
+ control->nsaddr_list[0].sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ }
Tcl_SetAssocData(interp, tnmDnsControl, AssocDeleteProc,
(ClientData) control);
! DnsInit(control);
! }
!
! dnsParams.retries = -1;
! dnsParams.timeout = -1;
! dnsParams.nscount = -1;
! for (i = 0; i < MAXNS; i++) {
! dnsParams.nsaddr_list[i].sin_family = AF_INET;
! dnsParams.nsaddr_list[i].sin_addr.s_addr = htonl(INADDR_ANY);
! dnsParams.nsaddr_list[i].sin_port = htons(NAMESERVER_PORT);
}

argc--; argv++;
***************
*** 936,942 ****
if (argc == 0) {
wrongArgs:
Tcl_AppendResult(interp, "wrong # args: should be \"", cmd,
! " ?-timeout t? ?-retries r? ?-server host? ",
"option arg\"", (char *) NULL);
return TCL_ERROR;
}
--- 951,957 ----
if (argc == 0) {
wrongArgs:
Tcl_AppendResult(interp, "wrong # args: should be \"", cmd,
! " ?-timeout t? ?-retries r? ?-server hosts? ",
"option arg\"", (char *) NULL);
return TCL_ERROR;
}
***************
*** 952,958 ****
sprintf(interp->result, "%d", control->timeout);
return TCL_OK;
}
! if (TnmGetPositive(interp, argv[0], &actTimeout) != TCL_OK) {
return TCL_ERROR;
}
argc--, argv++;
--- 967,974 ----
sprintf(interp->result, "%d", control->timeout);
return TCL_OK;
}
! code = TnmGetPositive(interp, argv[0], &dnsParams.timeout);
! if (code != TCL_OK) {
return TCL_ERROR;
}
argc--, argv++;
***************
*** 962,983 ****
sprintf(interp->result, "%d", control->retries);
return TCL_OK;
}
! if (TnmGetUnsigned(interp, argv[0], &actRetries) != TCL_OK) {
return TCL_ERROR;
}
argc--, argv++;
} else if (strcmp(argv[0], "-server") == 0) {
! struct sockaddr_in addr;
argc--, argv++;
if (argc <= 0) {
! Tcl_SetResult(interp, inet_ntoa(control->server), TCL_STATIC);
return TCL_OK;
}
! serverName = argv[0];
! if (TnmSetIPAddress(interp, serverName, &addr) != TCL_OK) {
return TCL_ERROR;
}
! actServer = addr.sin_addr;
argc--, argv++;
} else {
Tcl_AppendResult(interp, "unknown option \"", argv[0], "\"",
--- 978,1027 ----
sprintf(interp->result, "%d", control->retries);
return TCL_OK;
}
! code = TnmGetUnsigned(interp, argv[0], &dnsParams.retries);
! if (code != TCL_OK) {
return TCL_ERROR;
}
argc--, argv++;
} else if (strcmp(argv[0], "-server") == 0) {
! int largc;
! char **largv;
argc--, argv++;
if (argc <= 0) {
! for (i = 0; i < control->nscount; i++) {
! Tcl_AppendElement(interp,
! inet_ntoa(control->nsaddr_list[i].sin_addr));
! }
return TCL_OK;
}
! code = Tcl_SplitList(interp, argv[0], &largc, &largv);
! if (code != TCL_OK) {
! return TCL_ERROR;
! }
! if (largc > MAXNS) {
! Tcl_SetResult(interp,
! "number of DNS server addresses exceeds resolver limit",
! TCL_STATIC);
! ckfree((char *) largv);
! return TCL_ERROR;
! }
! if (largc == 0) {
! Tcl_SetResult(interp,
! "at least one DNS server address required",
! TCL_STATIC);
! ckfree((char *) largv);
return TCL_ERROR;
}
! dnsParams.nscount = largc;
! for (i = 0; i < dnsParams.nscount; i++) {
! code = TnmSetIPAddress(interp, largv[i],
! &dnsParams.nsaddr_list[i]);
! if (code != TCL_OK) {
! ckfree((char *) largv);
! return TCL_ERROR;
! }
! }
! ckfree((char *) largv);
argc--, argv++;
} else {
Tcl_AppendResult(interp, "unknown option \"", argv[0], "\"",
***************
*** 987,1000 ****
}

if (argc == 0) {
! if (actRetries >= 0) {
! control->retries = actRetries;
}
! if (actTimeout > 0) {
! control->timeout = actTimeout;
}
! if (serverName) {
! control->server = actServer;
}
return TCL_OK;
}
--- 1031,1047 ----
}

if (argc == 0) {
! if (dnsParams.retries >= 0) {
! control->retries = dnsParams.retries;
}
! if (dnsParams.timeout > 0) {
! control->timeout = dnsParams.timeout;
}
! if (dnsParams.nscount > 0) {
! control->nscount = dnsParams.nscount;
! for (i = 0; i < dnsParams.nscount; i++) {
! control->nsaddr_list[i] = dnsParams.nsaddr_list[i];
! }
}
return TCL_OK;
}
***************
*** 1003,1011 ****
goto wrongArgs;
}

! DnsInit(actTimeout < 0 ? control->timeout : actTimeout,
! actRetries <= 0 ? control->retries : actRetries,
! serverName ? &actServer : &control->server);

/*
* Get the query type and do the DNS lookup.
--- 1050,1068 ----
goto wrongArgs;
}

! if (dnsParams.timeout < 0) {
! dnsParams.timeout = control->timeout;
! }
! if (dnsParams.retries < 0) {
! dnsParams.retries = control->retries;
! }
! if (dnsParams.nscount < 0) {
! dnsParams.nscount = control->nscount;
! for (i = 0; i < control->nscount; i++) {
! dnsParams.nsaddr_list[i] = control->nsaddr_list[i];
! }
! }
! DnsInit(&dnsParams);

/*
* Get the query type and do the DNS lookup.