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