1: /* resolv.c
2:
3: Parser for /etc/resolv.conf file. */
4:
5: /*
6: * Copyright (c) 2004-2007,2009 by Internet Systems Consortium, Inc. ("ISC")
7: * Copyright (c) 1996-2003 by Internet Software Consortium
8: *
9: * Permission to use, copy, modify, and distribute this software for any
10: * purpose with or without fee is hereby granted, provided that the above
11: * copyright notice and this permission notice appear in all copies.
12: *
13: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20: *
21: * Internet Systems Consortium, Inc.
22: * 950 Charter Street
23: * Redwood City, CA 94063
24: * <info@isc.org>
25: * https://www.isc.org/
26: *
27: * This software has been written for Internet Systems Consortium
28: * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29: * To learn more about Internet Systems Consortium, see
30: * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
31: * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32: * ``http://www.nominum.com''.
33: */
34:
35: #include "dhcpd.h"
36:
37: struct name_server *name_servers;
38: struct domain_search_list *domains;
39: char path_resolv_conf [] = _PATH_RESOLV_CONF;
40:
41: void read_resolv_conf (parse_time)
42: TIME parse_time;
43: {
44: int file;
45: struct parse *cfile;
46: const char *val;
47: int token;
48: struct name_server *sp, *sl, *ns;
49: struct domain_search_list *dp, *dl, *nd;
50: isc_result_t status;
51:
52: if ((file = open (path_resolv_conf, O_RDONLY)) < 0) {
53: log_error ("Can't open %s: %m", path_resolv_conf);
54: return;
55: }
56:
57: cfile = NULL;
58: status = new_parse(&cfile, file, NULL, 0, path_resolv_conf, 1);
59: if (status != ISC_R_SUCCESS || cfile == NULL)
60: return;
61:
62: do {
63: token = next_token (&val, (unsigned *)0, cfile);
64: if (token == END_OF_FILE)
65: break;
66: else if (token == EOL)
67: continue;
68: else if (token == DOMAIN || token == SEARCH) {
69: do {
70: struct domain_search_list *nd, **dp;
71: char *dn;
72:
73: dn = parse_host_name (cfile);
74: if (!dn)
75: break;
76:
77: dp = &domains;
78: for (nd = domains; nd; nd = nd -> next) {
79: dp = &nd -> next;
80: if (!strcmp (nd -> domain, dn))
81: break;
82: }
83: if (!nd) {
84: nd = new_domain_search_list (MDL);
85: if (!nd)
86: log_fatal ("No memory for %s",
87: dn);
88: nd -> next =
89: (struct domain_search_list *)0;
90: *dp = nd;
91: nd -> domain = dn;
92: dn = (char *)0;
93: }
94: nd -> rcdate = parse_time;
95: token = peek_token (&val,
96: (unsigned *)0, cfile);
97: } while (token != EOL);
98: if (token != EOL) {
99: parse_warn (cfile,
100: "junk after domain declaration");
101: skip_to_semi (cfile);
102: }
103: token = next_token (&val, (unsigned *)0, cfile);
104: } else if (token == NAMESERVER) {
105: struct name_server *ns, **sp;
106: struct iaddr iaddr;
107:
108: parse_ip_addr (cfile, &iaddr);
109:
110: sp = &name_servers;
111: for (ns = name_servers; ns; ns = ns -> next) {
112: sp = &ns -> next;
113: if (!memcmp (&ns -> addr.sin_addr,
114: iaddr.iabuf, iaddr.len))
115: break;
116: }
117: if (!ns) {
118: ns = new_name_server (MDL);
119: if (!ns)
120: log_fatal ("No memory for nameserver %s",
121: piaddr (iaddr));
122: ns -> next = (struct name_server *)0;
123: *sp = ns;
124: memcpy (&ns -> addr.sin_addr,
125: iaddr.iabuf, iaddr.len);
126: #ifdef HAVE_SA_LEN
127: ns -> addr.sin_len = sizeof ns -> addr;
128: #endif
129: ns -> addr.sin_family = AF_INET;
130: ns -> addr.sin_port = htons (53);
131: memset (ns -> addr.sin_zero, 0,
132: sizeof ns -> addr.sin_zero);
133: }
134: ns -> rcdate = parse_time;
135: skip_to_semi (cfile);
136: } else
137: skip_to_semi (cfile); /* Ignore what we don't grok. */
138: } while (1);
139: token = next_token (&val, (unsigned *)0, cfile);
140:
141: /* Lose servers that are no longer in /etc/resolv.conf. */
142: sl = (struct name_server *)0;
143: for (sp = name_servers; sp; sp = ns) {
144: ns = sp -> next;
145: if (sp -> rcdate != parse_time) {
146: if (sl)
147: sl -> next = sp -> next;
148: else
149: name_servers = sp -> next;
150: /* We can't actually free the name server structure,
151: because somebody might be hanging on to it. If
152: your /etc/resolv.conf file changes a lot, this
153: could be a noticeable memory leak. */
154: } else
155: sl = sp;
156: }
157:
158: /* Lose domains that are no longer in /etc/resolv.conf. */
159: dl = (struct domain_search_list *)0;
160: for (dp = domains; dp; dp = nd) {
161: nd = dp -> next;
162: if (dp -> rcdate != parse_time) {
163: if (dl)
164: dl -> next = dp -> next;
165: else
166: domains = dp -> next;
167: free_domain_search_list (dp, MDL);
168: } else
169: dl = dp;
170: }
171: end_parse (&cfile);
172: }
173:
174: /* Pick a name server from the /etc/resolv.conf file. */
175:
176: struct name_server *first_name_server ()
177: {
178: static TIME rcdate;
179: struct stat st;
180:
181: /* Check /etc/resolv.conf and reload it if it's changed. */
182: if (cur_time > rcdate) {
183: if (stat (path_resolv_conf, &st) < 0) {
184: log_error ("Can't stat %s", path_resolv_conf);
185: return (struct name_server *)0;
186: }
187: if (st.st_mtime > rcdate) {
188: rcdate = cur_time + 1;
189:
190: read_resolv_conf (rcdate);
191: }
192: }
193:
194: return name_servers;
195: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>