3 Parser for /etc/resolv.conf file. */
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-2003 by Internet Software Consortium
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.
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.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
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''.
36 static char copyright
[] =
37 "$Id: resolv.c,v 1.4 2005/08/11 17:13:21 drochner Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
42 struct name_server
*name_servers
;
43 struct domain_search_list
*domains
;
44 char path_resolv_conf
[] = _PATH_RESOLV_CONF
;
46 void read_resolv_conf (parse_time
)
53 struct name_server
*sp
, *sl
, *ns
;
54 struct domain_search_list
*dp
, *dl
, *nd
;
56 if ((file
= open (path_resolv_conf
, O_RDONLY
)) < 0) {
57 log_error ("Can't open %s: %m", path_resolv_conf
);
61 cfile
= (struct parse
*)0;
62 new_parse (&cfile
, file
, (char *)0, 0, path_resolv_conf
, 1);
65 token
= next_token (&val
, (unsigned *)0, cfile
);
66 if (token
== END_OF_FILE
)
68 else if (token
== EOL
)
70 else if (token
== DOMAIN
|| token
== SEARCH
) {
72 struct domain_search_list
*nd
, **dp
;
75 dn
= parse_host_name (cfile
);
80 for (nd
= domains
; nd
; nd
= nd
-> next
) {
82 if (!strcmp (nd
-> domain
, dn
))
86 nd
= new_domain_search_list (MDL
);
88 log_fatal ("No memory for %s",
91 (struct domain_search_list
*)0;
96 nd
-> rcdate
= parse_time
;
97 token
= peek_token (&val
,
98 (unsigned *)0, cfile
);
99 } while (token
!= EOL
);
102 "junk after domain declaration");
103 skip_to_semi (cfile
);
105 token
= next_token (&val
, (unsigned *)0, cfile
);
106 } else if (token
== NAMESERVER
) {
107 struct name_server
*ns
, **sp
;
110 parse_ip_addr (cfile
, &iaddr
);
113 for (ns
= name_servers
; ns
; ns
= ns
-> next
) {
115 if (!memcmp (&ns
-> addr
.sin_addr
,
116 iaddr
.iabuf
, iaddr
.len
))
120 ns
= new_name_server (MDL
);
122 log_fatal ("No memory for nameserver %s",
124 ns
-> next
= (struct name_server
*)0;
126 memset (&ns
->addr
, 0, sizeof ns
->addr
);
127 memcpy (&ns
-> addr
.sin_addr
,
128 iaddr
.iabuf
, iaddr
.len
);
130 ns
-> addr
.sin_len
= sizeof ns
-> addr
;
132 ns
-> addr
.sin_family
= AF_INET
;
133 ns
-> addr
.sin_port
= htons (53);
135 ns
-> rcdate
= parse_time
;
136 skip_to_semi (cfile
);
138 skip_to_semi (cfile
); /* Ignore what we don't grok. */
140 token
= next_token (&val
, (unsigned *)0, cfile
);
142 /* Lose servers that are no longer in /etc/resolv.conf. */
143 sl
= (struct name_server
*)0;
144 for (sp
= name_servers
; sp
; sp
= ns
) {
146 if (sp
-> rcdate
!= parse_time
) {
148 sl
-> next
= sp
-> next
;
150 name_servers
= sp
-> next
;
151 /* We can't actually free the name server structure,
152 because somebody might be hanging on to it. If
153 your /etc/resolv.conf file changes a lot, this
154 could be a noticable memory leak. */
159 /* Lose domains that are no longer in /etc/resolv.conf. */
160 dl
= (struct domain_search_list
*)0;
161 for (dp
= domains
; dp
; dp
= nd
) {
163 if (dp
-> rcdate
!= parse_time
) {
165 dl
-> next
= dp
-> next
;
167 domains
= dp
-> next
;
168 free_domain_search_list (dp
, MDL
);
176 /* Pick a name server from the /etc/resolv.conf file. */
178 struct name_server
*first_name_server ()
183 /* Check /etc/resolv.conf and reload it if it's changed. */
184 if (cur_time
> rcdate
) {
185 if (stat (path_resolv_conf
, &st
) < 0) {
186 log_error ("Can't stat %s", path_resolv_conf
);
187 return (struct name_server
*)0;
189 if (st
.st_mtime
> rcdate
) {
190 rcdate
= cur_time
+ 1;
192 read_resolv_conf (rcdate
);