1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67: #if defined(LIBC_SCCS) && !defined(lint)
68: static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
69: static const char rcsid[] = "$BINDId: res_query.c,v 8.20 2000/02/29 05:39:12 vixie Exp $";
70: #endif
71:
72: #include <assert.h>
73: #include <sys/types.h>
74: #include <sys/param.h>
75: #include <netinet/in.h>
76: #include <arpa/inet.h>
77: #include <arpa/nameser.h>
78: #include <ctype.h>
79: #include <errno.h>
80: #include <netdb.h>
81: #include <resolv.h>
82: #include <stdio.h>
83: #include <stdlib.h>
84: #include <string.h>
85:
86:
87:
88:
89: #if PACKETSZ > 65536
90: #define MAXPACKET PACKETSZ
91: #else
92: #define MAXPACKET 65536
93: #endif
94:
95: #define QUERYSIZE (HFIXEDSZ + QFIXEDSZ + MAXCDNAME + 1)
96:
97: static int
98: __libc_res_nquerydomain(res_state statp, const char *name, const char *domain,
99: int class, int type, u_char *answer, int anslen,
100: u_char **answerp);
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112: int
113: __libc_res_nquery(res_state statp,
114: const char *name,
115: int class, int type,
116: u_char *answer,
117: int anslen,
118: u_char **answerp)
119: {
120: u_char *buf;
121: HEADER *hp = (HEADER *) answer;
122: int n, use_malloc = 0;
123: u_int oflags = statp->_flags;
124:
125: size_t bufsize = QUERYSIZE;
126: buf = alloca (bufsize);
127:
128: again:
129: hp->rcode = NOERROR;
130:
131: #ifdef DEBUG
132: if (statp->options & RES_DEBUG)
133: printf(";; res_query(%s, %d, %d)\n", name, class, type);
134: #endif
135:
136: n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
137: buf, bufsize);
138: if (n > 0
139: && (oflags & RES_F_EDNS0ERR) == 0
140: && (statp->options & RES_USE_EDNS0) != 0)
141: n = __res_nopt(statp, n, buf, bufsize, anslen);
142: if (__builtin_expect (n <= 0, 0) && !use_malloc) {
143:
144:
145: bufsize = MAXPACKET;
146: buf = malloc (bufsize);
147: if (buf != NULL) {
148: use_malloc = 1;
149: goto again;
150: }
151: }
152: if (__builtin_expect (n <= 0, 0)) {
153:
154: if ((statp->options & RES_USE_EDNS0) != 0
155: && ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) {
156: statp->_flags |= RES_F_EDNS0ERR;
157: if (statp->options & RES_DEBUG)
158: printf(";; res_nquery: retry without EDNS0\n");
159: goto again;
160: }
161: #ifdef DEBUG
162: if (statp->options & RES_DEBUG)
163: printf(";; res_query: mkquery failed\n");
164: #endif
165: RES_SET_H_ERRNO(statp, NO_RECOVERY);
166: if (use_malloc)
167: free (buf);
168: return (n);
169: }
170: assert (answerp == NULL || (void *) *answerp == (void *) answer);
171: n = __libc_res_nsend(statp, buf, n, answer, anslen, answerp);
172: if (use_malloc)
173: free (buf);
174: if (n < 0) {
175: #ifdef DEBUG
176: if (statp->options & RES_DEBUG)
177: printf(";; res_query: send error\n");
178: #endif
179: RES_SET_H_ERRNO(statp, TRY_AGAIN);
180: return (n);
181: }
182:
183: if (answerp != NULL)
184:
185: hp = (HEADER *) *answerp;
186:
187: if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
188: #ifdef DEBUG
189: if (statp->options & RES_DEBUG)
190: printf(";; rcode = %d, ancount=%d\n", hp->rcode,
191: ntohs(hp->ancount));
192: #endif
193: switch (hp->rcode) {
194: case NXDOMAIN:
195: RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
196: break;
197: case SERVFAIL:
198: RES_SET_H_ERRNO(statp, TRY_AGAIN);
199: break;
200: case NOERROR:
201: RES_SET_H_ERRNO(statp, NO_DATA);
202: break;
203: case FORMERR:
204: case NOTIMP:
205: case REFUSED:
206: default:
207: RES_SET_H_ERRNO(statp, NO_RECOVERY);
208: break;
209: }
210: return (-1);
211: }
212: return (n);
213: }
214: libresolv_hidden_def (__libc_res_nquery)
215:
216: int
217: res_nquery(res_state statp,
218: const char *name,
219: int class, int type,
220: u_char *answer,
221: int anslen)
222: {
223: return __libc_res_nquery(statp, name, class, type, answer, anslen,
224: NULL);
225: }
226: libresolv_hidden_def (res_nquery)
227:
228:
229:
230:
231:
232:
233:
234: int
235: __libc_res_nsearch(res_state statp,
236: const char *name,
237: int class, int type,
238: u_char *answer,
239: int anslen,
240: u_char **answerp)
241: {
242: const char *cp, * const *domain;
243: HEADER *hp = (HEADER *) answer;
244: char tmp[NS_MAXDNAME];
245: u_int dots;
246: int trailing_dot, ret, saved_herrno;
247: int got_nodata = 0, got_servfail = 0, root_on_list = 0;
248: int tried_as_is = 0;
249:
250: __set_errno (0);
251: RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
252:
253: dots = 0;
254: for (cp = name; *cp != '\0'; cp++)
255: dots += (*cp == '.');
256: trailing_dot = 0;
257: if (cp > name && *--cp == '.')
258: trailing_dot++;
259:
260:
261: if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
262: return (__libc_res_nquery(statp, cp, class, type, answer,
263: anslen, answerp));
264:
265: #ifdef DEBUG
266: if (statp->options & RES_DEBUG)
267: printf("dots=%d, statp->ndots=%d, trailing_dot=%d, name=%s\n",
268: (int)dots,(int)statp->ndots,(int)trailing_dot,name);
269: #endif
270:
271:
272:
273:
274:
275:
276: saved_herrno = -1;
277: if (dots >= statp->ndots || trailing_dot) {
278: ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
279: answer, anslen, answerp);
280: if (ret > 0 || trailing_dot)
281: return (ret);
282: saved_herrno = h_errno;
283: tried_as_is++;
284: if (answerp && *answerp != answer) {
285: answer = *answerp;
286: anslen = MAXPACKET;
287: }
288: }
289:
290:
291:
292:
293:
294:
295:
296: if ((!dots && (statp->options & RES_DEFNAMES) != 0) ||
297: (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) {
298: int done = 0;
299:
300: for (domain = (const char * const *)statp->dnsrch;
301: *domain && !done;
302: domain++) {
303:
304: if (domain[0][0] == '\0' ||
305: (domain[0][0] == '.' && domain[0][1] == '\0'))
306: root_on_list++;
307:
308: ret = __libc_res_nquerydomain(statp, name, *domain,
309: class, type,
310: answer, anslen, answerp);
311: if (ret > 0)
312: return (ret);
313:
314: if (answerp && *answerp != answer) {
315: answer = *answerp;
316: anslen = MAXPACKET;
317: }
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332: if (errno == ECONNREFUSED) {
333: RES_SET_H_ERRNO(statp, TRY_AGAIN);
334: return (-1);
335: }
336:
337: switch (statp->res_h_errno) {
338: case NO_DATA:
339: got_nodata++;
340:
341: case HOST_NOT_FOUND:
342:
343: break;
344: case TRY_AGAIN:
345: if (hp->rcode == SERVFAIL) {
346:
347: got_servfail++;
348: break;
349: }
350:
351: default:
352:
353: done++;
354: }
355:
356:
357:
358:
359: if ((statp->options & RES_DNSRCH) == 0)
360: done++;
361: }
362: }
363:
364:
365:
366:
367:
368:
369: if (dots && !(tried_as_is || root_on_list)) {
370: ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
371: answer, anslen, answerp);
372: if (ret > 0)
373: return (ret);
374: }
375:
376:
377:
378:
379:
380:
381:
382:
383: if (saved_herrno != -1)
384: RES_SET_H_ERRNO(statp, saved_herrno);
385: else if (got_nodata)
386: RES_SET_H_ERRNO(statp, NO_DATA);
387: else if (got_servfail)
388: RES_SET_H_ERRNO(statp, TRY_AGAIN);
389: return (-1);
390: }
391: libresolv_hidden_def (__libc_res_nsearch)
392:
393: int
394: res_nsearch(res_state statp,
395: const char *name,
396: int class, int type,
397: u_char *answer,
398: int anslen)
399: {
400: return __libc_res_nsearch(statp, name, class, type, answer,
401: anslen, NULL);
402: }
403: libresolv_hidden_def (res_nsearch)
404:
405:
406:
407:
408:
409: static int
410: __libc_res_nquerydomain(res_state statp,
411: const char *name,
412: const char *domain,
413: int class, int type,
414: u_char *answer,
415: int anslen,
416: u_char **answerp)
417: {
418: char nbuf[MAXDNAME];
419: const char *longname = nbuf;
420: int n, d;
421:
422: #ifdef DEBUG
423: if (statp->options & RES_DEBUG)
424: printf(";; res_nquerydomain(%s, %s, %d, %d)\n",
425: name, domain?domain:"<Nil>", class, type);
426: #endif
427: if (domain == NULL) {
428:
429:
430:
431:
432: n = strlen(name);
433: if (n >= MAXDNAME) {
434: RES_SET_H_ERRNO(statp, NO_RECOVERY);
435: return (-1);
436: }
437: n--;
438: if (n >= 0 && name[n] == '.') {
439: strncpy(nbuf, name, n);
440: nbuf[n] = '\0';
441: } else
442: longname = name;
443: } else {
444: n = strlen(name);
445: d = strlen(domain);
446: if (n + d + 1 >= MAXDNAME) {
447: RES_SET_H_ERRNO(statp, NO_RECOVERY);
448: return (-1);
449: }
450: sprintf(nbuf, "%s.%s", name, domain);
451: }
452: return (__libc_res_nquery(statp, longname, class, type, answer,
453: anslen, answerp));
454: }
455:
456: int
457: res_nquerydomain(res_state statp,
458: const char *name,
459: const char *domain,
460: int class, int type,
461: u_char *answer,
462: int anslen)
463: {
464: return __libc_res_nquerydomain(statp, name, domain, class, type,
465: answer, anslen, NULL);
466: }
467: libresolv_hidden_def (res_nquerydomain)
468:
469: const char *
470: res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
471: char *file, *cp1, *cp2;
472: char buf[BUFSIZ];
473: FILE *fp;
474:
475: if (statp->options & RES_NOALIASES)
476: return (NULL);
477: file = getenv("HOSTALIASES");
478: if (file == NULL || (fp = fopen(file, "r")) == NULL)
479: return (NULL);
480: setbuf(fp, NULL);
481: buf[sizeof(buf) - 1] = '\0';
482: while (fgets(buf, sizeof(buf), fp)) {
483: for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
484: ;
485: if (!*cp1)
486: break;
487: *cp1 = '\0';
488: if (ns_samename(buf, name) == 1) {
489: while (isspace(*++cp1))
490: ;
491: if (!*cp1)
492: break;
493: for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
494: ;
495: *cp2 = '\0';
496: strncpy(dst, cp1, siz - 1);
497: dst[siz - 1] = '\0';
498: fclose(fp);
499: return (dst);
500: }
501: }
502: fclose(fp);
503: return (NULL);
504: }
505: libresolv_hidden_def (res_hostalias)