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