|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.