]> git.ipfire.org Git - thirdparty/dhcp.git/blob - common/resolv.c
- Merge changes between 3.0.3RC1 and 3.0.4-BETA-3 into HEAD (silence
[thirdparty/dhcp.git] / common / resolv.c
1 /* resolv.c
2
3 Parser for /etc/resolv.conf file. */
4
5 /*
6 * Copyright (c) 2004-2006 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 * http://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 * ``http://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 #ifndef lint
36 static char copyright[] =
37 "$Id: resolv.c,v 1.18 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
38 #endif /* not lint */
39
40 #include "dhcpd.h"
41
42 struct name_server *name_servers;
43 struct domain_search_list *domains;
44 char path_resolv_conf [] = _PATH_RESOLV_CONF;
45
46 void read_resolv_conf (parse_time)
47 TIME parse_time;
48 {
49 int file;
50 struct parse *cfile;
51 const char *val;
52 int token;
53 int declaration = 0;
54 struct name_server *sp, *sl, *ns;
55 struct domain_search_list *dp, *dl, *nd;
56 struct iaddr *iaddr;
57
58 if ((file = open (path_resolv_conf, O_RDONLY)) < 0) {
59 log_error ("Can't open %s: %m", path_resolv_conf);
60 return;
61 }
62
63 cfile = (struct parse *)0;
64 new_parse (&cfile, file, (char *)0, 0, path_resolv_conf, 1);
65
66 do {
67 token = next_token (&val, (unsigned *)0, cfile);
68 if (token == END_OF_FILE)
69 break;
70 else if (token == EOL)
71 continue;
72 else if (token == DOMAIN || token == SEARCH) {
73 do {
74 struct domain_search_list *nd, **dp;
75 char *dn;
76
77 dn = parse_host_name (cfile);
78 if (!dn)
79 break;
80
81 dp = &domains;
82 for (nd = domains; nd; nd = nd -> next) {
83 dp = &nd -> next;
84 if (!strcmp (nd -> domain, dn))
85 break;
86 }
87 if (!nd) {
88 nd = new_domain_search_list (MDL);
89 if (!nd)
90 log_fatal ("No memory for %s",
91 dn);
92 nd -> next =
93 (struct domain_search_list *)0;
94 *dp = nd;
95 nd -> domain = dn;
96 dn = (char *)0;
97 }
98 nd -> rcdate = parse_time;
99 token = peek_token (&val,
100 (unsigned *)0, cfile);
101 } while (token != EOL);
102 if (token != EOL) {
103 parse_warn (cfile,
104 "junk after domain declaration");
105 skip_to_semi (cfile);
106 }
107 token = next_token (&val, (unsigned *)0, cfile);
108 } else if (token == NAMESERVER) {
109 struct name_server *ns, **sp;
110 struct iaddr iaddr;
111
112 parse_ip_addr (cfile, &iaddr);
113
114 sp = &name_servers;
115 for (ns = name_servers; ns; ns = ns -> next) {
116 sp = &ns -> next;
117 if (!memcmp (&ns -> addr.sin_addr,
118 iaddr.iabuf, iaddr.len))
119 break;
120 }
121 if (!ns) {
122 ns = new_name_server (MDL);
123 if (!ns)
124 log_fatal ("No memory for nameserver %s",
125 piaddr (iaddr));
126 ns -> next = (struct name_server *)0;
127 *sp = ns;
128 memcpy (&ns -> addr.sin_addr,
129 iaddr.iabuf, iaddr.len);
130 #ifdef HAVE_SA_LEN
131 ns -> addr.sin_len = sizeof ns -> addr;
132 #endif
133 ns -> addr.sin_family = AF_INET;
134 ns -> addr.sin_port = htons (53);
135 memset (ns -> addr.sin_zero, 0,
136 sizeof ns -> addr.sin_zero);
137 }
138 ns -> rcdate = parse_time;
139 skip_to_semi (cfile);
140 } else
141 skip_to_semi (cfile); /* Ignore what we don't grok. */
142 } while (1);
143 token = next_token (&val, (unsigned *)0, cfile);
144
145 /* Lose servers that are no longer in /etc/resolv.conf. */
146 sl = (struct name_server *)0;
147 for (sp = name_servers; sp; sp = ns) {
148 ns = sp -> next;
149 if (sp -> rcdate != parse_time) {
150 if (sl)
151 sl -> next = sp -> next;
152 else
153 name_servers = sp -> next;
154 /* We can't actually free the name server structure,
155 because somebody might be hanging on to it. If
156 your /etc/resolv.conf file changes a lot, this
157 could be a noticable memory leak. */
158 } else
159 sl = sp;
160 }
161
162 /* Lose domains that are no longer in /etc/resolv.conf. */
163 dl = (struct domain_search_list *)0;
164 for (dp = domains; dp; dp = nd) {
165 nd = dp -> next;
166 if (dp -> rcdate != parse_time) {
167 if (dl)
168 dl -> next = dp -> next;
169 else
170 domains = dp -> next;
171 free_domain_search_list (dp, MDL);
172 } else
173 dl = dp;
174 }
175 end_parse (&cfile);
176 }
177
178 /* Pick a name server from the /etc/resolv.conf file. */
179
180 struct name_server *first_name_server ()
181 {
182 FILE *rc;
183 static TIME rcdate;
184 struct stat st;
185
186 /* Check /etc/resolv.conf and reload it if it's changed. */
187 if (cur_time > rcdate) {
188 if (stat (path_resolv_conf, &st) < 0) {
189 log_error ("Can't stat %s", path_resolv_conf);
190 return (struct name_server *)0;
191 }
192 if (st.st_mtime > rcdate) {
193 char rcbuf [512];
194 char *s, *t, *u;
195 rcdate = cur_time + 1;
196
197 read_resolv_conf (rcdate);
198 }
199 }
200
201 return name_servers;
202 }