home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / NETWORK / ISP / bind.4.8.3.lzh / BIND483 / RES / res_query.c < prev    next >
C/C++ Source or Header  |  1994-09-23  |  8KB  |  286 lines

  1. /*
  2.  * Copyright (c) 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that: (1) source distributions retain this entire copyright
  7.  * notice and comment, and (2) distributions including binaries display
  8.  * the following acknowledgement:  ``This product includes software
  9.  * developed by the University of California, Berkeley and its contributors''
  10.  * in the documentation or other materials provided with the distribution
  11.  * and in all advertising materials mentioning features or use of this
  12.  * software. Neither the name of the University nor the names of its
  13.  * contributors may be used to endorse or promote products derived
  14.  * from this software without specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  16.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  17.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #if defined(LIBC_SCCS) && !defined(lint)
  21. static char sccsid[] = "@(#)res_query.c    5.7 (Berkeley) 6/1/90";
  22. #endif /* LIBC_SCCS and not lint */
  23.  
  24. #include <sys/param.h>
  25. #ifdef OSK
  26. #include <types.h>
  27. #include <socket.h>
  28. #include <in.h>
  29. #else
  30. #include <sys/socket.h>
  31. #include <netinet/in.h>
  32. #endif
  33. #include <ctype.h>
  34. #include <netdb.h>
  35. #include <stdio.h>
  36. #include <errno.h>
  37. #include <string.h>
  38. #ifdef OSK
  39. #include <inet.h>
  40. #include <nameser.h>
  41. #else
  42. #include <arpa/inet.h>
  43. #include <arpa/nameser.h>
  44. #endif
  45. #include <resolv.h>
  46.  
  47. #if PACKETSZ > 1024
  48. #define MAXPACKET    PACKETSZ
  49. #else
  50. #define MAXPACKET    1024
  51. #endif
  52.  
  53. extern int errno;
  54. int h_errno;
  55.  
  56. /*
  57.  * Formulate a normal query, send, and await answer.
  58.  * Returned answer is placed in supplied buffer "answer".
  59.  * Perform preliminary check of answer, returning success only
  60.  * if no error is indicated and the answer count is nonzero.
  61.  * Return the size of the response on success, -1 on error.
  62.  * Error number is left in h_errno.
  63.  * Caller must parse answer and determine whether it answers the question.
  64.  */
  65. res_query(name, class, type, answer, anslen)
  66.     char *name;        /* domain name */
  67.     int class, type;    /* class and type of query */
  68.     u_char *answer;        /* buffer to put answer */
  69.     int anslen;        /* size of answer buffer */
  70. {
  71.     char buf[MAXPACKET];
  72.     HEADER *hp;
  73.     int n;
  74.  
  75.     if ((_res.options & RES_INIT) == 0 && res_init() == -1)
  76.         return (-1);
  77. #ifdef DEBUG
  78.     if (_res.options & RES_DEBUG)
  79.         printf("res_query(%s, %d, %d)\n", name, class, type);
  80. #endif
  81.     n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL,
  82.         buf, sizeof(buf));
  83.  
  84.     if (n <= 0) {
  85. #ifdef DEBUG
  86.         if (_res.options & RES_DEBUG)
  87.             printf("res_query: mkquery failed\n");
  88. #endif
  89.         h_errno = NO_RECOVERY;
  90.         return (n);
  91.     }
  92.     n = res_send(buf, n, answer, anslen);
  93.     if (n < 0) {
  94. #ifdef DEBUG
  95.         if (_res.options & RES_DEBUG)
  96.             printf("res_query: send error\n");
  97. #endif
  98.         h_errno = TRY_AGAIN;
  99.         return(n);
  100.     }
  101.  
  102.     hp = (HEADER *) answer;
  103.     if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
  104. #ifdef DEBUG
  105.         if (_res.options & RES_DEBUG)
  106.             printf("rcode = %d, ancount=%d\n", hp->rcode,
  107.                 ntohs(hp->ancount));
  108. #endif
  109.         switch (hp->rcode) {
  110.             case NXDOMAIN:
  111.                 h_errno = HOST_NOT_FOUND;
  112.                 break;
  113.             case SERVFAIL:
  114.                 h_errno = TRY_AGAIN;
  115.                 break;
  116.             case NOERROR:
  117.                 h_errno = NO_DATA;
  118.                 break;
  119.             case FORMERR:
  120.             case NOTIMP:
  121.             case REFUSED:
  122.             default:
  123.                 h_errno = NO_RECOVERY;
  124.                 break;
  125.         }
  126.         return (-1);
  127.     }
  128.     return(n);
  129. }
  130.  
  131. /*
  132.  * Formulate a normal query, send, and retrieve answer in supplied buffer.
  133.  * Return the size of the response on success, -1 on error.
  134.  * If enabled, implement search rules until answer or unrecoverable failure
  135.  * is detected.  Error number is left in h_errno.
  136.  * Only useful for queries in the same name hierarchy as the local host
  137.  * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
  138.  */
  139. res_search(name, class, type, answer, anslen)
  140.     char *name;        /* domain name */
  141.     int class, type;    /* class and type of query */
  142.     u_char *answer;        /* buffer to put answer */
  143.     int anslen;        /* size of answer */
  144. {
  145.     register char *cp, **domain;
  146.     int n, ret, got_nodata = 0;
  147.     char *hostalias();
  148.  
  149.     if ((_res.options & RES_INIT) == 0 && res_init() == -1)
  150.         return (-1);
  151.  
  152.     errno = 0;
  153.     h_errno = HOST_NOT_FOUND;        /* default, if we never query */
  154.     for (cp = name, n = 0; *cp; cp++)
  155.         if (*cp == '.')
  156.             n++;
  157.     if (n == 0 && (cp = hostalias(name)))
  158.         return (res_query(cp, class, type, answer, anslen));
  159.  
  160.     /*
  161.      * We do at least one level of search if
  162.      *    - there is no dot and RES_DEFNAME is set, or
  163.      *    - there is at least one dot, there is no trailing dot,
  164.      *      and RES_DNSRCH is set.
  165.      */
  166.     if ((n == 0 && _res.options & RES_DEFNAMES) ||
  167.        (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
  168.          for (domain = _res.dnsrch; *domain; domain++) {
  169.         ret = res_querydomain(name, *domain, class, type,
  170.             answer, anslen);
  171.         if (ret > 0)
  172.             return (ret);
  173.         /*
  174.          * If no server present, give up.
  175.          * If name isn't found in this domain,
  176.          * keep trying higher domains in the search list
  177.          * (if that's enabled).
  178.          * On a NO_DATA error, keep trying, otherwise
  179.          * a wildcard entry of another type could keep us
  180.          * from finding this entry higher in the domain.
  181.          * If we get some other error (negative answer or
  182.          * server failure), then stop searching up,
  183.          * but try the input name below in case it's fully-qualified.
  184.          */
  185.         if (errno == ECONNREFUSED) {
  186.             h_errno = TRY_AGAIN;
  187.             return (-1);
  188.         }
  189.         if (h_errno == NO_DATA)
  190.             got_nodata++;
  191.         if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) ||
  192.             (_res.options & RES_DNSRCH) == 0)
  193.             break;
  194.     }
  195.     /*
  196.      * If the search/default failed, try the name as fully-qualified,
  197.      * but only if it contained at least one dot (even trailing).
  198.      * This is purely a heuristic; we assume that any reasonable query
  199.      * about a top-level domain (for servers, SOA, etc) will not use
  200.      * res_search.
  201.      */
  202.     if (n && (ret = res_querydomain(name, (char *)NULL, class, type,
  203.         answer, anslen)) > 0)
  204.         return (ret);
  205.     if (got_nodata)
  206.         h_errno = NO_DATA;
  207.     return (-1);
  208. }
  209.  
  210. /*
  211.  * Perform a call on res_query on the concatenation of name and domain,
  212.  * removing a trailing dot from name if domain is NULL.
  213.  */
  214. res_querydomain(name, domain, class, type, answer, anslen)
  215.     char *name, *domain;
  216.     int class, type;    /* class and type of query */
  217.     u_char *answer;        /* buffer to put answer */
  218.     int anslen;        /* size of answer */
  219. {
  220.     char nbuf[2*MAXDNAME+2];
  221.     char *longname = nbuf;
  222.     int n;
  223.  
  224. #ifdef DEBUG
  225.     if (_res.options & RES_DEBUG)
  226. #ifdef OSK
  227.        if ( domain == NULL ) 
  228.         printf("res_querydomain(%s, 0, %d, %d)\n",
  229.             name, class, type);
  230.         else
  231. #endif
  232.         printf("res_querydomain(%s, %s, %d, %d)\n",
  233.             name, domain, class, type);
  234. #endif
  235.     if (domain == NULL) {
  236.         /*
  237.          * Check for trailing '.';
  238.          * copy without '.' if present.
  239.          */
  240.         n = strlen(name) - 1;
  241.         if (name[n] == '.' && n < sizeof(nbuf) - 1) {
  242.             bcopy(name, nbuf, n);
  243.             nbuf[n] = '\0';
  244.         } else
  245.             longname = name;
  246.     } else
  247.         (void)sprintf(nbuf, "%.*s.%.*s",
  248.             MAXDNAME, name, MAXDNAME, domain);
  249.  
  250.     return (res_query(longname, class, type, answer, anslen));
  251. }
  252.  
  253. char *
  254. hostalias(name)
  255.     register char *name;
  256. {
  257.     register char *C1, *C2;
  258.     FILE *fp;
  259.     char *file, *getenv(), *strcpy(), *strncpy();
  260.     char buf[BUFSIZ];
  261.     static char abuf[MAXDNAME];
  262.  
  263.     file = getenv("HOSTALIASES");
  264.     if (file == NULL || (fp = fopen(file, "r")) == NULL)
  265.         return (NULL);
  266.     buf[sizeof(buf) - 1] = '\0';
  267.     while (fgets(buf, sizeof(buf), fp)) {
  268.         for (C1 = buf; *C1 && !isspace(*C1); ++C1);
  269.         if (!*C1)
  270.             break;
  271.         *C1 = '\0';
  272.         if (!strcasecmp(buf, name)) {
  273.             while (isspace(*++C1));
  274.             if (!*C1)
  275.                 break;
  276.             for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
  277.             abuf[sizeof(abuf) - 1] = *C2 = '\0';
  278.             (void)strncpy(abuf, C1, sizeof(abuf) - 1);
  279.             fclose(fp);
  280.             return (abuf);
  281.         }
  282.     }
  283.     fclose(fp);
  284.     return (NULL);
  285. }
  286.