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 this notice is preserved and that due credit is given
   7:  * to the University of California at Berkeley. The name of the University
   8:  * may not be used to endorse or promote products derived from this
   9:  * software without specific prior written permission. This software
  10:  * is provided ``as is'' without express or implied warranty.
  11:  */
  12: 
  13: #if defined(LIBC_SCCS) && !defined(lint)
  14: static char sccsid[] = "@(#)res_query.c	5.3 (Berkeley) 4/5/88";
  15: #endif /* LIBC_SCCS and not lint */
  16: 
  17: #include <sys/param.h>
  18: #include <sys/socket.h>
  19: #include <netinet/in.h>
  20: #include <ctype.h>
  21: #include <netdb.h>
  22: #include <stdio.h>
  23: #include <errno.h>
  24: #include <strings.h>
  25: #include <arpa/inet.h>
  26: #include <arpa/nameser.h>
  27: #include <resolv.h>
  28: 
  29: #if PACKETSZ > 1024
  30: #define MAXPACKET   PACKETSZ
  31: #else
  32: #define MAXPACKET   1024
  33: #endif
  34: 
  35: extern int errno;
  36: int h_errno;
  37: 
  38: /*
  39:  * Formulate a normal query, send, and await answer.
  40:  * Returned answer is placed in supplied buffer "answer".
  41:  * Perform preliminary check of answer, returning success only
  42:  * if no error is indicated and the answer count is nonzero.
  43:  * Return the size of the response on success, -1 on error.
  44:  * Error number is left in h_errno.
  45:  * Caller must parse answer and determine whether it answers the question.
  46:  */
  47: res_query(name, class, type, answer, anslen)
  48:     char *name;     /* domain name */
  49:     int class, type;    /* class and type of query */
  50:     u_char *answer;     /* buffer to put answer */
  51:     int anslen;     /* size of answer buffer */
  52: {
  53:     char buf[MAXPACKET];
  54:     HEADER *hp;
  55:     int n;
  56: 
  57:     if ((_res.options & RES_INIT) == 0 && res_init() == -1)
  58:         return (-1);
  59: #ifdef DEBUG
  60:     if (_res.options & RES_DEBUG)
  61:         printf("res_query(%s, %d, %d)\n", name, class, type);
  62: #endif
  63:     n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL,
  64:         buf, sizeof(buf));
  65: 
  66:     if (n <= 0) {
  67: #ifdef DEBUG
  68:         if (_res.options & RES_DEBUG)
  69:             printf("res_query: mkquery failed\n");
  70: #endif
  71:         h_errno = NO_RECOVERY;
  72:         return (n);
  73:     }
  74:     n = res_send(buf, n, answer, anslen);
  75:     if (n < 0) {
  76: #ifdef DEBUG
  77:         if (_res.options & RES_DEBUG)
  78:             printf("res_query: send error\n");
  79: #endif
  80:         h_errno = TRY_AGAIN;
  81:         return(n);
  82:     }
  83: 
  84:     hp = (HEADER *) answer;
  85:     if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
  86: #ifdef DEBUG
  87:         if (_res.options & RES_DEBUG)
  88:             printf("rcode = %d, ancount=%d\n", hp->rcode,
  89:                 ntohs(hp->ancount));
  90: #endif
  91:         switch (hp->rcode) {
  92:             case NXDOMAIN:
  93:                 h_errno = HOST_NOT_FOUND;
  94:                 break;
  95:             case SERVFAIL:
  96:                 h_errno = TRY_AGAIN;
  97:                 break;
  98:             case NOERROR:
  99:                 h_errno = NO_DATA;
 100:                 break;
 101:             case FORMERR:
 102:             case NOTIMP:
 103:             case REFUSED:
 104:             default:
 105:                 h_errno = NO_RECOVERY;
 106:                 break;
 107:         }
 108:         return (-1);
 109:     }
 110:     return(n);
 111: }
 112: 
 113: /*
 114:  * Formulate a normal query, send, and retrieve answer in supplied buffer.
 115:  * Return the size of the response on success, -1 on error.
 116:  * If enabled, implement search rules until answer or unrecoverable failure
 117:  * is detected.  Error number is left in h_errno.
 118:  * Only useful for queries in the same name hierarchy as the local host
 119:  * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
 120:  */
 121: res_search(name, class, type, answer, anslen)
 122:     char *name;     /* domain name */
 123:     int class, type;    /* class and type of query */
 124:     u_char *answer;     /* buffer to put answer */
 125:     int anslen;     /* size of answer */
 126: {
 127:     register char *cp, **domain;
 128:     int n, ret;
 129:     char *hostalias();
 130: 
 131:     if ((_res.options & RES_INIT) == 0 && res_init() == -1)
 132:         return (-1);
 133: 
 134:     errno = 0;
 135:     h_errno = HOST_NOT_FOUND;       /* default, if we never query */
 136:     for (cp = name, n = 0; *cp; cp++)
 137:         if (*cp == '.')
 138:             n++;
 139:     if (n == 0 && (cp = hostalias(name)))
 140:         return (res_query(cp, class, type, answer, anslen));
 141: 
 142:     if ((n == 0 || *--cp != '.') && (_res.options & RES_DEFNAMES))
 143:         for (domain = _res.dnsrch; *domain; domain++) {
 144:         h_errno = 0;
 145:         ret = res_querydomain(name, *domain, class, type,
 146:             answer, anslen);
 147:         if (ret > 0)
 148:             return (ret);
 149:         /*
 150: 		 * If no server present, give up.
 151: 		 * If name isn't found in this domain,
 152: 		 * keep trying higher domains in the search list
 153: 		 * (if that's enabled).
 154: 		 * On a NO_DATA error, keep trying, otherwise
 155: 		 * a wildcard entry of another type could keep us
 156: 		 * from finding this entry higher in the domain.
 157: 		 * If we get some other error (non-authoritative negative
 158: 		 * answer or server failure), then stop searching up,
 159: 		 * but try the input name below in case it's fully-qualified.
 160: 		 */
 161:         if (errno == ECONNREFUSED) {
 162:             h_errno = TRY_AGAIN;
 163:             return (-1);
 164:         }
 165:         if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) ||
 166:             (_res.options & RES_DNSRCH) == 0)
 167:             break;
 168:         }
 169:     /*
 170: 	 * If the search/default failed, try the name as fully-qualified,
 171: 	 * but only if it contained at least one dot (even trailing).
 172: 	 */
 173:     if (n)
 174:         return (res_querydomain(name, (char *)NULL, class, type,
 175:             answer, anslen));
 176:     return (-1);
 177: }
 178: 
 179: /*
 180:  * Perform a call on res_query on the concatenation of name and domain,
 181:  * removing a trailing dot from name if domain is NULL.
 182:  */
 183: res_querydomain(name, domain, class, type, answer, anslen)
 184:     char *name, *domain;
 185:     int class, type;    /* class and type of query */
 186:     u_char *answer;     /* buffer to put answer */
 187:     int anslen;     /* size of answer */
 188: {
 189:     char nbuf[2*MAXDNAME+2];
 190:     char *longname = nbuf;
 191:     int n;
 192: 
 193: #ifdef DEBUG
 194:     if (_res.options & RES_DEBUG)
 195:         printf("res_querydomain(%s, %s, %d, %d)\n",
 196:             name, domain, class, type);
 197: #endif
 198:     if (domain == NULL) {
 199:         /*
 200: 		 * Check for trailing '.';
 201: 		 * copy without '.' if present.
 202: 		 */
 203:         n = strlen(name) - 1;
 204:         if (name[n] == '.' && n < sizeof(nbuf) - 1) {
 205:             bcopy(name, nbuf, n);
 206:             nbuf[n] = '\0';
 207:         } else
 208:             longname = name;
 209:     } else
 210:         (void)sprintf(nbuf, "%.*s.%.*s",
 211:             MAXDNAME, name, MAXDNAME, domain);
 212: 
 213:     return (res_query(longname, class, type, answer, anslen));
 214: }
 215: 
 216: char *
 217: hostalias(name)
 218:     register char *name;
 219: {
 220:     register char *C1, *C2;
 221:     FILE *fp;
 222:     char *file, *getenv(), *strcpy(), *strncpy();
 223:     char buf[BUFSIZ];
 224:     static char abuf[MAXDNAME];
 225: 
 226:     file = getenv("HOSTALIASES");
 227:     if (file == NULL || (fp = fopen(file, "r")) == NULL)
 228:         return (NULL);
 229:     buf[sizeof(buf) - 1] = '\0';
 230:     while (fgets(buf, sizeof(buf), fp)) {
 231:         for (C1 = buf; *C1 && !isspace(*C1); ++C1);
 232:         if (!*C1)
 233:             break;
 234:         *C1 = '\0';
 235:         if (!strcasecmp(buf, name)) {
 236:             while (isspace(*++C1));
 237:             if (!*C1)
 238:                 break;
 239:             for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
 240:             abuf[sizeof(abuf) - 1] = *C2 = '\0';
 241:             (void)strncpy(abuf, C1, sizeof(abuf) - 1);
 242:             fclose(fp);
 243:             return (abuf);
 244:         }
 245:     }
 246:     fclose(fp);
 247:     return (NULL);
 248: }

Defined functions

hostalias defined in line 216; used 4 times
res_query defined in line 47; used 3 times
res_querydomain defined in line 183; used 2 times

Defined variables

sccsid defined in line 14; never used

Defined macros

MAXPACKET defined in line 32; used 1 times
  • in line 53
Last modified: 1988-09-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1380
Valid CSS Valid XHTML 1.0 Strict