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