ISC DHCP  4.4.2b1
A reference DHCPv4 and DHCPv6 implementation
resolv.c
Go to the documentation of this file.
1 /* resolv.c
2 
3  Parser for /etc/resolv.conf file. */
4 
5 /*
6  * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1996-2003 by Internet Software Consortium
8  *
9  * This Source Code Form is subject to the terms of the Mozilla Public
10  * License, v. 2.0. If a copy of the MPL was not distributed with this
11  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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  * https://www.isc.org/
26  *
27  */
28 
29 #include "dhcpd.h"
30 
34 
35 void read_resolv_conf (parse_time)
36  TIME parse_time;
37 {
38  int file;
39  struct parse *cfile;
40  const char *val;
41  int token;
42  struct name_server *sp, *sl, *ns;
43  struct domain_search_list *dp, *dl, *nd;
44  isc_result_t status;
45 
46  if ((file = open (path_resolv_conf, O_RDONLY | O_CLOEXEC)) < 0) {
47  log_error ("Can't open %s: %m", path_resolv_conf);
48  return;
49  }
50 
51  cfile = NULL;
52  status = new_parse(&cfile, file, NULL, 0, path_resolv_conf, 1);
53  if (status != ISC_R_SUCCESS || cfile == NULL)
54  return;
55 
56  do {
57  token = next_token (&val, (unsigned *)0, cfile);
58  if (token == END_OF_FILE)
59  break;
60  else if (token == EOL)
61  continue;
62  else if (token == DOMAIN || token == SEARCH) {
63  do {
64  struct domain_search_list *nd, **dp;
65  char *dn;
66 
67  dn = parse_host_name (cfile);
68  if (!dn)
69  break;
70 
71  dp = &domains;
72  for (nd = domains; nd; nd = nd -> next) {
73  dp = &nd -> next;
74  if (!strcmp (nd -> domain, dn))
75  break;
76  }
77  if (!nd) {
79  if (!nd)
80  log_fatal ("No memory for %s",
81  dn);
82  nd -> next =
83  (struct domain_search_list *)0;
84  *dp = nd;
85  nd -> domain = dn;
86  }
87  nd -> rcdate = parse_time;
88  token = peek_token (&val,
89  (unsigned *)0, cfile);
90  } while (token != EOL);
91  if (token != EOL) {
92  parse_warn (cfile,
93  "junk after domain declaration");
94  skip_to_semi (cfile);
95  }
96  skip_token(&val, (unsigned *)0, cfile);
97  } else if (token == NAMESERVER) {
98  struct name_server *ns, **sp;
99  struct iaddr iaddr;
100 
101  parse_ip_addr (cfile, &iaddr);
102 
103  sp = &name_servers;
104  for (ns = name_servers; ns; ns = ns -> next) {
105  sp = &ns -> next;
106  if (!memcmp (&ns -> addr.sin_addr,
107  iaddr.iabuf, iaddr.len))
108  break;
109  }
110  if (!ns) {
111  ns = new_name_server (MDL);
112  if (!ns)
113  log_fatal ("No memory for nameserver %s",
114  piaddr (iaddr));
115  ns -> next = (struct name_server *)0;
116  *sp = ns;
117  memcpy (&ns -> addr.sin_addr,
118  iaddr.iabuf, iaddr.len);
119 #ifdef HAVE_SA_LEN
120  ns -> addr.sin_len = sizeof ns -> addr;
121 #endif
122  ns -> addr.sin_family = AF_INET;
123  ns -> addr.sin_port = htons (53);
124  memset (ns -> addr.sin_zero, 0,
125  sizeof ns -> addr.sin_zero);
126  }
127  ns -> rcdate = parse_time;
128  skip_to_semi (cfile);
129  } else
130  skip_to_semi (cfile); /* Ignore what we don't grok. */
131  } while (1);
132  skip_token(&val, (unsigned *)0, cfile);
133 
134  /* Lose servers that are no longer in /etc/resolv.conf. */
135  sl = (struct name_server *)0;
136  for (sp = name_servers; sp; sp = ns) {
137  ns = sp -> next;
138  if (sp -> rcdate != parse_time) {
139  if (sl)
140  sl -> next = sp -> next;
141  else
142  name_servers = sp -> next;
143  /* We can't actually free the name server structure,
144  because somebody might be hanging on to it. If
145  your /etc/resolv.conf file changes a lot, this
146  could be a noticeable memory leak. */
147  } else
148  sl = sp;
149  }
150 
151  /* Lose domains that are no longer in /etc/resolv.conf. */
152  dl = (struct domain_search_list *)0;
153  for (dp = domains; dp; dp = nd) {
154  nd = dp -> next;
155  if (dp -> rcdate != parse_time) {
156  if (dl)
157  dl -> next = dp -> next;
158  else
159  domains = dp -> next;
161  } else
162  dl = dp;
163  }
164  end_parse (&cfile);
165 }
166 
167 /* Pick a name server from the /etc/resolv.conf file. */
168 
170 {
171  static TIME rcdate;
172  struct stat st;
173 
174  /* Check /etc/resolv.conf and reload it if it's changed. */
175  if (cur_time > rcdate) {
176  if (stat (path_resolv_conf, &st) < 0) {
177  log_error ("Can't stat %s", path_resolv_conf);
178  return (struct name_server *)0;
179  }
180  if (st.st_mtime > rcdate) {
181  rcdate = cur_time + 1;
182 
183  read_resolv_conf (rcdate);
184  }
185  }
186 
187  return name_servers;
188 }
void free_domain_search_list(struct domain_search_list *ptr, const char *file, int line)
Definition: alloc.c:337
struct name_server * new_name_server(char *file, int line) const
Definition: alloc.c:283
struct domain_search_list * new_domain_search_list(char *file, int line) const
Definition: alloc.c:274
enum dhcp_token peek_token(const char **rval, unsigned *rlen, struct parse *cfile)
Definition: conflex.c:443
enum dhcp_token next_token(const char **rval, unsigned *rlen, struct parse *cfile)
Definition: conflex.c:369
isc_result_t end_parse(struct parse **cfile)
Definition: conflex.c:103
isc_result_t new_parse(struct parse **cfile, int file, char *inbuf, unsigned buflen, const char *name, int eolp)
Definition: conflex.c:41
char * parse_host_name(struct parse *cfile)
Definition: parse.c:196
void skip_to_semi(struct parse *cfile)
Definition: parse.c:81
int parse_warn(struct parse *cfile, const char *fmt,...)
Definition: parse.c:5643
int parse_ip_addr(struct parse *cfile, struct iaddr *addr)
Definition: parse.c:336
#define skip_token(a, b, c)
Definition: dhcpd.h:2187
#define _PATH_RESOLV_CONF
Definition: dhcpd.h:1610
time_t TIME
Definition: dhcpd.h:85
#define EOL
Definition: dhcpd.h:88
#define cur_time
Definition: dhcpd.h:2121
const char * file
Definition: dhcpd.h:3793
@ NAMESERVER
Definition: dhctoken.h:125
@ DOMAIN
Definition: dhctoken.h:126
@ END_OF_FILE
Definition: dhctoken.h:307
@ SEARCH
Definition: dhctoken.h:127
const char * piaddr(const struct iaddr addr)
Definition: inet.c:579
#define ISC_R_SUCCESS
#define MDL
Definition: omapip.h:567
int log_error(const char *,...) __attribute__((__format__(__printf__
void log_fatal(const char *,...) __attribute__((__format__(__printf__
struct name_server * name_servers
Definition: resolv.c:31
struct domain_search_list * domains
Definition: resolv.c:32
char path_resolv_conf[]
Definition: resolv.c:33
struct name_server * first_name_server()
Definition: resolv.c:169
void read_resolv_conf(TIME parse_time)
Definition: resolv.c:35
char * domain
Definition: dhcpd.h:362
struct domain_search_list * next
Definition: dhcpd.h:361
Definition: inet.h:31
unsigned char iabuf[16]
Definition: inet.h:33
unsigned len
Definition: inet.h:32
TIME rcdate
Definition: dhcpd.h:356
struct name_server * next
Definition: dhcpd.h:354
struct sockaddr_in addr
Definition: dhcpd.h:355
Definition: dhcpd.h:288
enum dhcp_token token
Definition: dhcpd.h:320