Annotation of 43BSDTahoe/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 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.4 (Berkeley) 4/21/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, got_nodata = 0;
                    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:                ret = res_querydomain(name, *domain, class, type,
                    145:                    answer, anslen);
                    146:                if (ret > 0)
                    147:                        return (ret);
                    148:                /*
                    149:                 * If no server present, give up.
                    150:                 * If name isn't found in this domain,
                    151:                 * keep trying higher domains in the search list
                    152:                 * (if that's enabled).
                    153:                 * On a NO_DATA error, keep trying, otherwise
                    154:                 * a wildcard entry of another type could keep us
                    155:                 * from finding this entry higher in the domain.
                    156:                 * If we get some other error (non-authoritative negative
                    157:                 * answer or server failure), then stop searching up,
                    158:                 * but try the input name below in case it's fully-qualified.
                    159:                 */
                    160:                if (errno == ECONNREFUSED) {
                    161:                        h_errno = TRY_AGAIN;
                    162:                        return (-1);
                    163:                }
                    164:                if (h_errno == NO_DATA)
                    165:                        got_nodata++;
                    166:                if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) ||
                    167:                    (_res.options & RES_DNSRCH) == 0)
                    168:                        break;
                    169:        }
                    170:        /*
                    171:         * If the search/default failed, try the name as fully-qualified,
                    172:         * but only if it contained at least one dot (even trailing).
                    173:         */
                    174:        if (n)
                    175:                return (res_querydomain(name, (char *)NULL, class, type,
                    176:                    answer, anslen));
                    177:        if (got_nodata)
                    178:                h_errno = NO_DATA;
                    179:        return (-1);
                    180: }
                    181: 
                    182: /*
                    183:  * Perform a call on res_query on the concatenation of name and domain,
                    184:  * removing a trailing dot from name if domain is NULL.
                    185:  */
                    186: res_querydomain(name, domain, class, type, answer, anslen)
                    187:        char *name, *domain;
                    188:        int class, type;        /* class and type of query */
                    189:        u_char *answer;         /* buffer to put answer */
                    190:        int anslen;             /* size of answer */
                    191: {
                    192:        char nbuf[2*MAXDNAME+2];
                    193:        char *longname = nbuf;
                    194:        int n;
                    195: 
                    196: #ifdef DEBUG
                    197:        if (_res.options & RES_DEBUG)
                    198:                printf("res_querydomain(%s, %s, %d, %d)\n",
                    199:                    name, domain, class, type);
                    200: #endif
                    201:        if (domain == NULL) {
                    202:                /*
                    203:                 * Check for trailing '.';
                    204:                 * copy without '.' if present.
                    205:                 */
                    206:                n = strlen(name) - 1;
                    207:                if (name[n] == '.' && n < sizeof(nbuf) - 1) {
                    208:                        bcopy(name, nbuf, n);
                    209:                        nbuf[n] = '\0';
                    210:                } else
                    211:                        longname = name;
                    212:        } else
                    213:                (void)sprintf(nbuf, "%.*s.%.*s",
                    214:                    MAXDNAME, name, MAXDNAME, domain);
                    215: 
                    216:        return (res_query(longname, class, type, answer, anslen));
                    217: }
                    218: 
                    219: char *
                    220: hostalias(name)
                    221:        register char *name;
                    222: {
                    223:        register char *C1, *C2;
                    224:        FILE *fp;
                    225:        char *file, *getenv(), *strcpy(), *strncpy();
                    226:        char buf[BUFSIZ];
                    227:        static char abuf[MAXDNAME];
                    228: 
                    229:        file = getenv("HOSTALIASES");
                    230:        if (file == NULL || (fp = fopen(file, "r")) == NULL)
                    231:                return (NULL);
                    232:        buf[sizeof(buf) - 1] = '\0';
                    233:        while (fgets(buf, sizeof(buf), fp)) {
                    234:                for (C1 = buf; *C1 && !isspace(*C1); ++C1);
                    235:                if (!*C1)
                    236:                        break;
                    237:                *C1 = '\0';
                    238:                if (!strcasecmp(buf, name)) {
                    239:                        while (isspace(*++C1));
                    240:                        if (!*C1)
                    241:                                break;
                    242:                        for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
                    243:                        abuf[sizeof(abuf) - 1] = *C2 = '\0';
                    244:                        (void)strncpy(abuf, C1, sizeof(abuf) - 1);
                    245:                        fclose(fp);
                    246:                        return (abuf);
                    247:                }
                    248:        }
                    249:        fclose(fp);
                    250:        return (NULL);
                    251: }

unix.superglobalmegacorp.com

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