* Copyright (c) 1988 Regents of the University of California.
* All rights reserved.
*
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of California at Berkeley. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
+ * %sccs.include.redist.c%
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)res_query.c 5.2 (Berkeley) %G%";
+static char sccsid[] = "@(#)res_query.c 5.11 (Berkeley) %G%";
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
-#include <sys/socket.h>
#include <netinet/in.h>
-#include <ctype.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <errno.h>
-#include <strings.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
+#include <netdb.h>
#include <resolv.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
#if PACKETSZ > 1024
#define MAXPACKET PACKETSZ
#define MAXPACKET 1024
#endif
-extern int errno;
int h_errno;
/*
h_errno = NO_RECOVERY;
return (n);
}
- n = res_send(buf, n, answer, anslen);
+ n = res_send(buf, n, (char *)answer, anslen);
if (n < 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
h_errno = TRY_AGAIN;
break;
case NOERROR:
- h_errno = NO_ADDRESS;
+ h_errno = NO_DATA;
break;
case FORMERR:
case NOTIMP:
int anslen; /* size of answer */
{
register char *cp, **domain;
- int n, ret;
- char *hostalias();
+ int n, ret, got_nodata = 0;
+ char *__hostalias();
if ((_res.options & RES_INIT) == 0 && res_init() == -1)
return (-1);
errno = 0;
+ h_errno = HOST_NOT_FOUND; /* default, if we never query */
for (cp = name, n = 0; *cp; cp++)
if (*cp == '.')
n++;
- if (n == 0 && (cp = hostalias(name)))
+ if (n == 0 && (cp = __hostalias(name)))
return (res_query(cp, class, type, answer, anslen));
- if ((n == 0 || *--cp != '.') && (_res.options & RES_DEFNAMES))
- for (domain = _res.dnsrch; *domain; domain++) {
+ /*
+ * We do at least one level of search if
+ * - there is no dot and RES_DEFNAME is set, or
+ * - there is at least one dot, there is no trailing dot,
+ * and RES_DNSRCH is set.
+ */
+ if ((n == 0 && _res.options & RES_DEFNAMES) ||
+ (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
+ for (domain = _res.dnsrch; *domain; domain++) {
ret = res_querydomain(name, *domain, class, type,
answer, anslen);
if (ret > 0)
* If name isn't found in this domain,
* keep trying higher domains in the search list
* (if that's enabled).
- * On a NO_ADDRESS error, keep trying, otherwise
+ * On a NO_DATA error, keep trying, otherwise
* a wildcard entry of another type could keep us
* from finding this entry higher in the domain.
- * If we get some other error (non-authoritative negative
- * answer or server failure), then stop searching up,
+ * If we get some other error (negative answer or
+ * server failure), then stop searching up,
* but try the input name below in case it's fully-qualified.
*/
if (errno == ECONNREFUSED) {
h_errno = TRY_AGAIN;
return (-1);
}
- if ((h_errno != HOST_NOT_FOUND && h_errno != NO_ADDRESS) ||
+ if (h_errno == NO_DATA)
+ got_nodata++;
+ if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) ||
(_res.options & RES_DNSRCH) == 0)
break;
- h_errno = 0;
}
/*
* If the search/default failed, try the name as fully-qualified,
* but only if it contained at least one dot (even trailing).
+ * This is purely a heuristic; we assume that any reasonable query
+ * about a top-level domain (for servers, SOA, etc) will not use
+ * res_search.
*/
- if (n)
- return (res_querydomain(name, (char *)NULL, class, type,
- answer, anslen));
- h_errno = HOST_NOT_FOUND;
+ if (n && (ret = res_querydomain(name, (char *)NULL, class, type,
+ answer, anslen)) > 0)
+ return (ret);
+ if (got_nodata)
+ h_errno = NO_DATA;
return (-1);
}
char *longname = nbuf;
int n;
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf("res_querydomain(%s, %s, %d, %d)\n",
+ name, domain, class, type);
+#endif
if (domain == NULL) {
/*
* Check for trailing '.';
}
char *
-hostalias(name)
- register char *name;
+__hostalias(name)
+ register const char *name;
{
register char *C1, *C2;
FILE *fp;