1997-06-03 00:25:43 +00:00
|
|
|
/* resolv.c
|
|
|
|
|
|
|
|
Parser for /etc/resolv.conf file. */
|
|
|
|
|
|
|
|
/*
|
2017-07-12 09:23:23 -04:00
|
|
|
* Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
|
2005-03-17 20:15:29 +00:00
|
|
|
* Copyright (c) 1996-2003 by Internet Software Consortium
|
1997-06-03 00:25:43 +00:00
|
|
|
*
|
2017-07-12 09:23:23 -04:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
1997-06-03 00:25:43 +00:00
|
|
|
*
|
2005-03-17 20:15:29 +00:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
|
|
|
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
1997-06-03 00:25:43 +00:00
|
|
|
*
|
2005-03-17 20:15:29 +00:00
|
|
|
* Internet Systems Consortium, Inc.
|
2022-01-19 20:13:19 +01:00
|
|
|
* PO Box 360
|
|
|
|
* Newmarket, NH 03857 USA
|
2005-03-17 20:15:29 +00:00
|
|
|
* <info@isc.org>
|
2009-07-23 18:52:21 +00:00
|
|
|
* https://www.isc.org/
|
2000-03-17 04:00:32 +00:00
|
|
|
*
|
1997-06-03 00:25:43 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "dhcpd.h"
|
|
|
|
|
|
|
|
struct name_server *name_servers;
|
|
|
|
struct domain_search_list *domains;
|
|
|
|
char path_resolv_conf [] = _PATH_RESOLV_CONF;
|
|
|
|
|
|
|
|
void read_resolv_conf (parse_time)
|
|
|
|
TIME parse_time;
|
|
|
|
{
|
1999-10-01 03:42:12 +00:00
|
|
|
int file;
|
|
|
|
struct parse *cfile;
|
1999-10-07 06:36:35 +00:00
|
|
|
const char *val;
|
1997-06-03 00:25:43 +00:00
|
|
|
int token;
|
|
|
|
struct name_server *sp, *sl, *ns;
|
|
|
|
struct domain_search_list *dp, *dl, *nd;
|
2008-03-07 20:12:44 +00:00
|
|
|
isc_result_t status;
|
1997-06-03 00:25:43 +00:00
|
|
|
|
1999-10-21 12:32:16 +00:00
|
|
|
if ((file = open (path_resolv_conf, O_RDONLY)) < 0) {
|
1999-02-24 17:56:53 +00:00
|
|
|
log_error ("Can't open %s: %m", path_resolv_conf);
|
1997-06-08 04:05:21 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-03-07 20:12:44 +00:00
|
|
|
cfile = NULL;
|
|
|
|
status = new_parse(&cfile, file, NULL, 0, path_resolv_conf, 1);
|
|
|
|
if (status != ISC_R_SUCCESS || cfile == NULL)
|
|
|
|
return;
|
1999-10-01 03:42:12 +00:00
|
|
|
|
1997-06-03 00:25:43 +00:00
|
|
|
do {
|
2001-03-17 00:47:39 +00:00
|
|
|
token = next_token (&val, (unsigned *)0, cfile);
|
2001-03-01 18:17:09 +00:00
|
|
|
if (token == END_OF_FILE)
|
1997-06-03 00:25:43 +00:00
|
|
|
break;
|
|
|
|
else if (token == EOL)
|
|
|
|
continue;
|
|
|
|
else if (token == DOMAIN || token == SEARCH) {
|
|
|
|
do {
|
|
|
|
struct domain_search_list *nd, **dp;
|
|
|
|
char *dn;
|
|
|
|
|
|
|
|
dn = parse_host_name (cfile);
|
|
|
|
if (!dn)
|
|
|
|
break;
|
|
|
|
|
|
|
|
dp = &domains;
|
|
|
|
for (nd = domains; nd; nd = nd -> next) {
|
|
|
|
dp = &nd -> next;
|
|
|
|
if (!strcmp (nd -> domain, dn))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!nd) {
|
2000-01-26 14:56:18 +00:00
|
|
|
nd = new_domain_search_list (MDL);
|
1997-06-03 00:25:43 +00:00
|
|
|
if (!nd)
|
1999-10-01 03:42:12 +00:00
|
|
|
log_fatal ("No memory for %s",
|
|
|
|
dn);
|
1997-06-03 00:25:43 +00:00
|
|
|
nd -> next =
|
|
|
|
(struct domain_search_list *)0;
|
|
|
|
*dp = nd;
|
|
|
|
nd -> domain = dn;
|
|
|
|
}
|
|
|
|
nd -> rcdate = parse_time;
|
2001-03-17 00:47:39 +00:00
|
|
|
token = peek_token (&val,
|
|
|
|
(unsigned *)0, cfile);
|
1997-06-03 00:47:40 +00:00
|
|
|
} while (token != EOL);
|
1997-06-03 00:25:43 +00:00
|
|
|
if (token != EOL) {
|
1999-10-01 03:42:12 +00:00
|
|
|
parse_warn (cfile,
|
|
|
|
"junk after domain declaration");
|
1997-06-03 00:25:43 +00:00
|
|
|
skip_to_semi (cfile);
|
|
|
|
}
|
2013-05-15 10:49:54 +10:00
|
|
|
skip_token(&val, (unsigned *)0, cfile);
|
1997-06-03 00:25:43 +00:00
|
|
|
} else if (token == NAMESERVER) {
|
|
|
|
struct name_server *ns, **sp;
|
|
|
|
struct iaddr iaddr;
|
|
|
|
|
|
|
|
parse_ip_addr (cfile, &iaddr);
|
|
|
|
|
|
|
|
sp = &name_servers;
|
|
|
|
for (ns = name_servers; ns; ns = ns -> next) {
|
|
|
|
sp = &ns -> next;
|
|
|
|
if (!memcmp (&ns -> addr.sin_addr,
|
|
|
|
iaddr.iabuf, iaddr.len))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!ns) {
|
2000-01-26 14:56:18 +00:00
|
|
|
ns = new_name_server (MDL);
|
1997-06-03 00:25:43 +00:00
|
|
|
if (!ns)
|
1999-10-01 03:42:12 +00:00
|
|
|
log_fatal ("No memory for nameserver %s",
|
1997-06-03 00:25:43 +00:00
|
|
|
piaddr (iaddr));
|
|
|
|
ns -> next = (struct name_server *)0;
|
|
|
|
*sp = ns;
|
|
|
|
memcpy (&ns -> addr.sin_addr,
|
|
|
|
iaddr.iabuf, iaddr.len);
|
|
|
|
#ifdef HAVE_SA_LEN
|
|
|
|
ns -> addr.sin_len = sizeof ns -> addr;
|
|
|
|
#endif
|
|
|
|
ns -> addr.sin_family = AF_INET;
|
|
|
|
ns -> addr.sin_port = htons (53);
|
|
|
|
memset (ns -> addr.sin_zero, 0,
|
|
|
|
sizeof ns -> addr.sin_zero);
|
|
|
|
}
|
|
|
|
ns -> rcdate = parse_time;
|
|
|
|
skip_to_semi (cfile);
|
1997-12-06 04:04:07 +00:00
|
|
|
} else
|
|
|
|
skip_to_semi (cfile); /* Ignore what we don't grok. */
|
1997-06-03 00:25:43 +00:00
|
|
|
} while (1);
|
2013-05-15 10:49:54 +10:00
|
|
|
skip_token(&val, (unsigned *)0, cfile);
|
1997-06-03 00:25:43 +00:00
|
|
|
|
|
|
|
/* Lose servers that are no longer in /etc/resolv.conf. */
|
|
|
|
sl = (struct name_server *)0;
|
|
|
|
for (sp = name_servers; sp; sp = ns) {
|
|
|
|
ns = sp -> next;
|
|
|
|
if (sp -> rcdate != parse_time) {
|
|
|
|
if (sl)
|
|
|
|
sl -> next = sp -> next;
|
|
|
|
else
|
|
|
|
name_servers = sp -> next;
|
1998-01-12 01:01:44 +00:00
|
|
|
/* We can't actually free the name server structure,
|
|
|
|
because somebody might be hanging on to it. If
|
|
|
|
your /etc/resolv.conf file changes a lot, this
|
2007-11-30 21:51:43 +00:00
|
|
|
could be a noticeable memory leak. */
|
1997-06-03 00:25:43 +00:00
|
|
|
} else
|
|
|
|
sl = sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Lose domains that are no longer in /etc/resolv.conf. */
|
|
|
|
dl = (struct domain_search_list *)0;
|
|
|
|
for (dp = domains; dp; dp = nd) {
|
|
|
|
nd = dp -> next;
|
|
|
|
if (dp -> rcdate != parse_time) {
|
|
|
|
if (dl)
|
|
|
|
dl -> next = dp -> next;
|
|
|
|
else
|
|
|
|
domains = dp -> next;
|
2000-01-26 14:56:18 +00:00
|
|
|
free_domain_search_list (dp, MDL);
|
1997-06-03 00:25:43 +00:00
|
|
|
} else
|
|
|
|
dl = dp;
|
|
|
|
}
|
1999-10-01 03:42:12 +00:00
|
|
|
end_parse (&cfile);
|
1997-06-03 00:25:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Pick a name server from the /etc/resolv.conf file. */
|
|
|
|
|
1998-01-12 01:01:44 +00:00
|
|
|
struct name_server *first_name_server ()
|
1997-06-03 00:25:43 +00:00
|
|
|
{
|
|
|
|
static TIME rcdate;
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
/* Check /etc/resolv.conf and reload it if it's changed. */
|
|
|
|
if (cur_time > rcdate) {
|
1997-06-08 04:05:21 +00:00
|
|
|
if (stat (path_resolv_conf, &st) < 0) {
|
1999-02-24 17:56:53 +00:00
|
|
|
log_error ("Can't stat %s", path_resolv_conf);
|
1998-01-12 01:01:44 +00:00
|
|
|
return (struct name_server *)0;
|
1997-06-08 04:05:21 +00:00
|
|
|
}
|
1997-06-03 00:25:43 +00:00
|
|
|
if (st.st_mtime > rcdate) {
|
|
|
|
rcdate = cur_time + 1;
|
|
|
|
|
|
|
|
read_resolv_conf (rcdate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-01-12 01:01:44 +00:00
|
|
|
return name_servers;
|
1997-06-03 00:25:43 +00:00
|
|
|
}
|