Annotation of 43BSDReno/lib/libc/net/res_query.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.