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_init.c 8.1 (Berkeley) 6/7/93";
69: static const char rcsid[] = "$BINDId: res_init.c,v 8.16 2000/05/09 07:10:12 vixie Exp $";
70: #endif
71:
72: #include <sys/types.h>
73: #include <sys/param.h>
74: #include <sys/socket.h>
75: #include <sys/time.h>
76:
77: #include <netinet/in.h>
78: #include <arpa/inet.h>
79: #include <arpa/nameser.h>
80:
81: #include <ctype.h>
82: #include <resolv.h>
83: #include <stdio.h>
84: #include <stdio_ext.h>
85: #include <stdlib.h>
86: #include <string.h>
87: #include <unistd.h>
88:
89: #include <not-cancel.h>
90:
91:
92: #define RESOLVSORT
93: #define RFC1535
94:
95:
96: static void res_setoptions (res_state, const char *, const char *)
97: internal_function;
98:
99: #ifdef RESOLVSORT
100: static const char sort_mask_chars[] = "/&";
101: #define ISSORTMASK(ch) (strchr(sort_mask_chars, ch) != NULL)
102: static u_int32_t net_mask (struct in_addr) __THROW;
103: #endif
104:
105: #if !defined(isascii)
106: # define isascii(c) (!(c & 0200))
107: #endif
108:
109: #ifdef _LIBC
110: unsigned long long int __res_initstamp attribute_hidden;
111: #endif
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138: int
139: res_ninit(res_state statp) {
140: extern int __res_vinit(res_state, int);
141:
142: return (__res_vinit(statp, 0));
143: }
144: #ifdef _LIBC
145: libc_hidden_def (__res_ninit)
146: #endif
147:
148:
149: int
150: __res_vinit(res_state statp, int preinit) {
151: register FILE *fp;
152: register char *cp, **pp;
153: register int n;
154: char buf[BUFSIZ];
155: int nserv = 0;
156: #ifdef _LIBC
157: int nservall = 0;
158: #endif
159: int haveenv = 0;
160: int havesearch = 0;
161: #ifdef RESOLVSORT
162: int nsort = 0;
163: char *net;
164: #endif
165: #ifndef RFC1535
166: int dots;
167: #endif
168: #ifdef _LIBC
169: statp->_u._ext.initstamp = __res_initstamp;
170: #endif
171:
172: if (!preinit) {
173: statp->retrans = RES_TIMEOUT;
174: statp->retry = RES_DFLRETRY;
175: statp->options = RES_DEFAULT;
176: statp->id = res_randomid();
177: }
178:
179: #ifdef USELOOPBACK
180: statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
181: #else
182: statp->nsaddr.sin_addr.s_addr = INADDR_ANY;
183: #endif
184: statp->nsaddr.sin_family = AF_INET;
185: statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
186: statp->nscount = 1;
187: statp->ndots = 1;
188: statp->pfcode = 0;
189: statp->_vcsock = -1;
190: statp->_flags = 0;
191: statp->qhook = NULL;
192: statp->rhook = NULL;
193: statp->_u._ext.nsinit = 0;
194: statp->_u._ext.nscount = 0;
195: #ifdef _LIBC
196: statp->_u._ext.nscount6 = 0;
197: for (n = 0; n < MAXNS; n++) {
198: statp->_u._ext.nsaddrs[n] = NULL;
199: statp->_u._ext.nsmap[n] = MAXNS;
200: }
201: #endif
202:
203:
204: if ((cp = getenv("LOCALDOMAIN")) != NULL) {
205: (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
206: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
207: haveenv++;
208:
209:
210:
211:
212:
213:
214:
215:
216: cp = statp->defdname;
217: pp = statp->dnsrch;
218: *pp++ = cp;
219: for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
220: if (*cp == '\n')
221: break;
222: else if (*cp == ' ' || *cp == '\t') {
223: *cp = 0;
224: n = 1;
225: } else if (n) {
226: *pp++ = cp;
227: n = 0;
228: havesearch = 1;
229: }
230: }
231:
232: while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
233: cp++;
234: *cp = '\0';
235: *pp++ = 0;
236: }
237:
238: #define MATCH(line, name) \
239: (!strncmp(line, name, sizeof(name) - 1) && \
240: (line[sizeof(name) - 1] == ' ' || \
241: line[sizeof(name) - 1] == '\t'))
242:
243: if ((fp = fopen(_PATH_RESCONF, "rc")) != NULL) {
244:
245: __fsetlocking (fp, FSETLOCKING_BYCALLER);
246:
247: while (fgets_unlocked(buf, sizeof(buf), fp) != NULL) {
248:
249: if (*buf == ';' || *buf == '#')
250: continue;
251:
252: if (MATCH(buf, "domain")) {
253: if (haveenv)
254: continue;
255: cp = buf + sizeof("domain") - 1;
256: while (*cp == ' ' || *cp == '\t')
257: cp++;
258: if ((*cp == '\0') || (*cp == '\n'))
259: continue;
260: strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
261: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
262: if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
263: *cp = '\0';
264: havesearch = 0;
265: continue;
266: }
267:
268: if (MATCH(buf, "search")) {
269: if (haveenv)
270: continue;
271: cp = buf + sizeof("search") - 1;
272: while (*cp == ' ' || *cp == '\t')
273: cp++;
274: if ((*cp == '\0') || (*cp == '\n'))
275: continue;
276: strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
277: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
278: if ((cp = strchr(statp->defdname, '\n')) != NULL)
279: *cp = '\0';
280:
281:
282:
283:
284: cp = statp->defdname;
285: pp = statp->dnsrch;
286: *pp++ = cp;
287: for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
288: if (*cp == ' ' || *cp == '\t') {
289: *cp = 0;
290: n = 1;
291: } else if (n) {
292: *pp++ = cp;
293: n = 0;
294: }
295: }
296:
297: while (*cp != '\0' && *cp != ' ' && *cp != '\t')
298: cp++;
299: *cp = '\0';
300: *pp++ = 0;
301: havesearch = 1;
302: continue;
303: }
304:
305: #ifdef _LIBC
306: if (MATCH(buf, "nameserver") && nservall < MAXNS) {
307: #else
308: if (MATCH(buf, "nameserver") && nserv < MAXNS) {
309: #endif
310: struct in_addr a;
311:
312: cp = buf + sizeof("nameserver") - 1;
313: while (*cp == ' ' || *cp == '\t')
314: cp++;
315: if ((*cp != '\0') && (*cp != '\n')
316: && __inet_aton(cp, &a)) {
317: statp->nsaddr_list[nserv].sin_addr = a;
318: statp->nsaddr_list[nserv].sin_family = AF_INET;
319: statp->nsaddr_list[nserv].sin_port =
320: htons(NAMESERVER_PORT);
321: nserv++;
322: #ifdef _LIBC
323: nservall++;
324: } else {
325: struct in6_addr a6;
326: char *el;
327:
328: if ((el = strchr(cp, '\n')) != NULL)
329: *el = '\0';
330: if ((*cp != '\0') &&
331: (inet_pton(AF_INET6, cp, &a6) > 0)) {
332: struct sockaddr_in6 *sa6;
333:
334: sa6 = malloc(sizeof(*sa6));
335: if (sa6 != NULL) {
336: sa6->sin6_addr = a6;
337: sa6->sin6_family = AF_INET6;
338: sa6->sin6_port = htons(NAMESERVER_PORT);
339: statp->_u._ext.nsaddrs[nservall] = sa6;
340: statp->_u._ext.nssocks[nservall] = -1;
341: statp->_u._ext.nsmap[nservall] = MAXNS + 1;
342: nservall++;
343: }
344: }
345: #endif
346: }
347: continue;
348: }
349: #ifdef RESOLVSORT
350: if (MATCH(buf, "sortlist")) {
351: struct in_addr a;
352:
353: cp = buf + sizeof("sortlist") - 1;
354: while (nsort < MAXRESOLVSORT) {
355: while (*cp == ' ' || *cp == '\t')
356: cp++;
357: if (*cp == '\0' || *cp == '\n' || *cp == ';')
358: break;
359: net = cp;
360: while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
361: isascii(*cp) && !isspace(*cp))
362: cp++;
363: n = *cp;
364: *cp = 0;
365: if (__inet_aton(net, &a)) {
366: statp->sort_list[nsort].addr = a;
367: if (ISSORTMASK(n)) {
368: *cp++ = n;
369: net = cp;
370: while (*cp && *cp != ';' &&
371: isascii(*cp) && !isspace(*cp))
372: cp++;
373: n = *cp;
374: *cp = 0;
375: if (__inet_aton(net, &a)) {
376: statp->sort_list[nsort].mask = a.s_addr;
377: } else {
378: statp->sort_list[nsort].mask =
379: net_mask(statp->sort_list[nsort].addr);
380: }
381: } else {
382: statp->sort_list[nsort].mask =
383: net_mask(statp->sort_list[nsort].addr);
384: }
385: nsort++;
386: }
387: *cp = n;
388: }
389: continue;
390: }
391: #endif
392: if (MATCH(buf, "options")) {
393: res_setoptions(statp, buf + sizeof("options") - 1, "conf");
394: continue;
395: }
396: }
397: if (nserv > 1)
398: statp->nscount = nserv;
399: #ifdef _LIBC
400: if (nservall - nserv > 0) {
401: statp->_u._ext.nscount6 = nservall - nserv;
402:
403: statp->ipv6_unavail = false;
404: }
405: #endif
406: #ifdef RESOLVSORT
407: statp->nsort = nsort;
408: #endif
409: (void) fclose(fp);
410: }
411: if (statp->defdname[0] == 0 &&
412: __gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
413: (cp = strchr(buf, '.')) != NULL)
414: strcpy(statp->defdname, cp + 1);
415:
416:
417: if (havesearch == 0) {
418: pp = statp->dnsrch;
419: *pp++ = statp->defdname;
420: *pp = NULL;
421:
422: #ifndef RFC1535
423: dots = 0;
424: for (cp = statp->defdname; *cp; cp++)
425: dots += (*cp == '.');
426:
427: cp = statp->defdname;
428: while (pp < statp->dnsrch + MAXDFLSRCH) {
429: if (dots < LOCALDOMAINPARTS)
430: break;
431: cp = __rawmemchr(cp, '.') + 1;
432: *pp++ = cp;
433: dots--;
434: }
435: *pp = NULL;
436: #ifdef DEBUG
437: if (statp->options & RES_DEBUG) {
438: printf(";; res_init()... default dnsrch list:\n");
439: for (pp = statp->dnsrch; *pp; pp++)
440: printf(";;\t%s\n", *pp);
441: printf(";;\t..END..\n");
442: }
443: #endif
444: #endif
445: }
446:
447: if ((cp = getenv("RES_OPTIONS")) != NULL)
448: res_setoptions(statp, cp, "env");
449: statp->options |= RES_INIT;
450: return (0);
451: }
452:
453: static void
454: internal_function
455: res_setoptions(res_state statp, const char *options, const char *source) {
456: const char *cp = options;
457: int i;
458:
459: #ifdef DEBUG
460: if (statp->options & RES_DEBUG)
461: printf(";; res_setoptions(\"%s\", \"%s\")...\n",
462: options, source);
463: #endif
464: while (*cp) {
465:
466: while (*cp == ' ' || *cp == '\t')
467: cp++;
468:
469: if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
470: i = atoi(cp + sizeof("ndots:") - 1);
471: if (i <= RES_MAXNDOTS)
472: statp->ndots = i;
473: else
474: statp->ndots = RES_MAXNDOTS;
475: #ifdef DEBUG
476: if (statp->options & RES_DEBUG)
477: printf(";;\tndots=%d\n", statp->ndots);
478: #endif
479: } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
480: i = atoi(cp + sizeof("timeout:") - 1);
481: if (i <= RES_MAXRETRANS)
482: statp->retrans = i;
483: else
484: statp->retrans = RES_MAXRETRANS;
485: } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
486: i = atoi(cp + sizeof("attempts:") - 1);
487: if (i <= RES_MAXRETRY)
488: statp->retry = i;
489: else
490: statp->retry = RES_MAXRETRY;
491: } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
492: #ifdef DEBUG
493: if (!(statp->options & RES_DEBUG)) {
494: printf(";; res_setoptions(\"%s\", \"%s\")..\n",
495: options, source);
496: statp->options |= RES_DEBUG;
497: }
498: printf(";;\tdebug\n");
499: #endif
500: } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
501: statp->options |= RES_USE_INET6;
502: } else if (!strncmp(cp, "ip6-bytestring",
503: sizeof("ip6-bytestring") - 1)) {
504: statp->options |= RES_USEBSTRING;
505: } else if (!strncmp(cp, "no-ip6-dotint",
506: sizeof("no-ip6-dotint") - 1)) {
507: statp->options |= RES_NOIP6DOTINT;
508: } else if (!strncmp(cp, "ip6-dotint",
509: sizeof("ip6-dotint") - 1)) {
510: statp->options &= ~RES_NOIP6DOTINT;
511: } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
512: statp->options |= RES_ROTATE;
513: } else if (!strncmp(cp, "no-check-names",
514: sizeof("no-check-names") - 1)) {
515: statp->options |=