|
|
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.