1 /* $NetBSD: resolv.c,v 1.1.1.2 2014/07/12 11:57:46 spz Exp $ */
4 Parser for /etc/resolv.conf file. */
7 * Copyright (c) 2009,2014 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 1996-2003 by Internet Software Consortium
11 * Permission to use, copy, modify, and distribute this software for any
12 * purpose with or without fee is hereby granted, provided that the above
13 * copyright notice and this permission notice appear in all copies.
15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Internet Systems Consortium, Inc.
25 * Redwood City, CA 94063
27 * https://www.isc.org/
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: resolv.c,v 1.1.1.2 2014/07/12 11:57:46 spz Exp $");
36 struct name_server
*name_servers
;
37 struct domain_search_list
*domains
;
38 char path_resolv_conf
[] = _PATH_RESOLV_CONF
;
40 void read_resolv_conf (parse_time
)
47 struct name_server
*sp
, *sl
, *ns
;
48 struct domain_search_list
*dp
, *dl
, *nd
;
51 if ((file
= open (path_resolv_conf
, O_RDONLY
)) < 0) {
52 log_error ("Can't open %s: %m", path_resolv_conf
);
57 status
= new_parse(&cfile
, file
, NULL
, 0, path_resolv_conf
, 1);
58 if (status
!= ISC_R_SUCCESS
|| cfile
== NULL
)
62 token
= next_token (&val
, (unsigned *)0, cfile
);
63 if (token
== END_OF_FILE
)
65 else if (token
== EOL
)
67 else if (token
== DOMAIN
|| token
== SEARCH
) {
69 struct domain_search_list
*nd
, **dp
;
72 dn
= parse_host_name (cfile
);
77 for (nd
= domains
; nd
; nd
= nd
-> next
) {
79 if (!strcmp (nd
-> domain
, dn
))
83 nd
= new_domain_search_list (MDL
);
85 log_fatal ("No memory for %s",
88 (struct domain_search_list
*)0;
92 nd
-> rcdate
= parse_time
;
93 token
= peek_token (&val
,
94 (unsigned *)0, cfile
);
95 } while (token
!= EOL
);
98 "junk after domain declaration");
101 skip_token(&val
, (unsigned *)0, cfile
);
102 } else if (token
== NAMESERVER
) {
103 struct name_server
*ns
, **sp
;
106 parse_ip_addr (cfile
, &iaddr
);
109 for (ns
= name_servers
; ns
; ns
= ns
-> next
) {
111 if (!memcmp (&ns
-> addr
.sin_addr
,
112 iaddr
.iabuf
, iaddr
.len
))
116 ns
= new_name_server (MDL
);
118 log_fatal ("No memory for nameserver %s",
120 ns
-> next
= (struct name_server
*)0;
122 memcpy (&ns
-> addr
.sin_addr
,
123 iaddr
.iabuf
, iaddr
.len
);
125 ns
-> addr
.sin_len
= sizeof ns
-> addr
;
127 ns
-> addr
.sin_family
= AF_INET
;
128 ns
-> addr
.sin_port
= htons (53);
129 memset (ns
-> addr
.sin_zero
, 0,
130 sizeof ns
-> addr
.sin_zero
);
132 ns
-> rcdate
= parse_time
;
133 skip_to_semi (cfile
);
135 skip_to_semi (cfile
); /* Ignore what we don't grok. */
137 skip_token(&val
, (unsigned *)0, cfile
);
139 /* Lose servers that are no longer in /etc/resolv.conf. */
140 sl
= (struct name_server
*)0;
141 for (sp
= name_servers
; sp
; sp
= ns
) {
143 if (sp
-> rcdate
!= parse_time
) {
145 sl
-> next
= sp
-> next
;
147 name_servers
= sp
-> next
;
148 /* We can't actually free the name server structure,
149 because somebody might be hanging on to it. If
150 your /etc/resolv.conf file changes a lot, this
151 could be a noticeable memory leak. */
156 /* Lose domains that are no longer in /etc/resolv.conf. */
157 dl
= (struct domain_search_list
*)0;
158 for (dp
= domains
; dp
; dp
= nd
) {
160 if (dp
-> rcdate
!= parse_time
) {
162 dl
-> next
= dp
-> next
;
164 domains
= dp
-> next
;
165 free_domain_search_list (dp
, MDL
);
172 /* Pick a name server from the /etc/resolv.conf file. */
174 struct name_server
*first_name_server ()
179 /* Check /etc/resolv.conf and reload it if it's changed. */
180 if (cur_time
> rcdate
) {
181 if (stat (path_resolv_conf
, &st
) < 0) {
182 log_error ("Can't stat %s", path_resolv_conf
);
183 return (struct name_server
*)0;
185 if (st
.st_mtime
> rcdate
) {
186 rcdate
= cur_time
+ 1;
188 read_resolv_conf (rcdate
);