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