common/resolv.c

Go to the documentation of this file.
00001 /* resolv.c
00002 
00003    Parser for /etc/resolv.conf file. */
00004 
00005 /*
00006  * Copyright (c) 2009,2014 by Internet Systems Consortium, Inc. ("ISC")
00007  * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
00008  * Copyright (c) 1996-2003 by Internet Software Consortium
00009  *
00010  * Permission to use, copy, modify, and distribute this software for any
00011  * purpose with or without fee is hereby granted, provided that the above
00012  * copyright notice and this permission notice appear in all copies.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00015  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00016  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00017  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00018  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00019  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00020  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00021  *
00022  *   Internet Systems Consortium, Inc.
00023  *   950 Charter Street
00024  *   Redwood City, CA 94063
00025  *   <info@isc.org>
00026  *   https://www.isc.org/
00027  *
00028  */
00029 
00030 #include "dhcpd.h"
00031 
00032 struct name_server *name_servers;
00033 struct domain_search_list *domains;
00034 char path_resolv_conf [] = _PATH_RESOLV_CONF;
00035 
00036 void read_resolv_conf (parse_time)
00037         TIME parse_time;
00038 {
00039         int file;
00040         struct parse *cfile;
00041         const char *val;
00042         int token;
00043         struct name_server *sp, *sl, *ns;
00044         struct domain_search_list *dp, *dl, *nd;
00045         isc_result_t status;
00046 
00047         if ((file = open (path_resolv_conf, O_RDONLY | O_CLOEXEC)) < 0) {
00048                 log_error ("Can't open %s: %m", path_resolv_conf);
00049                 return;
00050         }
00051 
00052         cfile = NULL;
00053         status = new_parse(&cfile, file, NULL, 0, path_resolv_conf, 1);
00054         if (status != ISC_R_SUCCESS || cfile == NULL)
00055                 return;
00056 
00057         do {
00058                 token = next_token (&val, (unsigned *)0, cfile);
00059                 if (token == END_OF_FILE)
00060                         break;
00061                 else if (token == EOL)
00062                         continue;
00063                 else if (token == DOMAIN || token == SEARCH) {
00064                         do {
00065                                 struct domain_search_list *nd, **dp;
00066                                 char *dn;
00067 
00068                                 dn = parse_host_name (cfile);
00069                                 if (!dn)
00070                                         break;
00071 
00072                                 dp = &domains;
00073                                 for (nd = domains; nd; nd = nd -> next) {
00074                                         dp = &nd -> next;
00075                                         if (!strcmp (nd -> domain, dn))
00076                                                 break;
00077                                 }
00078                                 if (!nd) {
00079                                         nd = new_domain_search_list (MDL);
00080                                         if (!nd)
00081                                                 log_fatal ("No memory for %s",
00082                                                            dn);
00083                                         nd -> next =
00084                                                 (struct domain_search_list *)0;
00085                                         *dp = nd;
00086                                         nd -> domain = dn;
00087                                 }
00088                                 nd -> rcdate = parse_time;
00089                                 token = peek_token (&val,
00090                                                     (unsigned *)0, cfile);
00091                         } while (token != EOL);
00092                         if (token != EOL) {
00093                                 parse_warn (cfile,
00094                                             "junk after domain declaration");
00095                                 skip_to_semi (cfile);
00096                         }
00097                         skip_token(&val, (unsigned *)0, cfile);
00098                 } else if (token == NAMESERVER) {
00099                         struct name_server *ns, **sp;
00100                         struct iaddr iaddr;
00101 
00102                         parse_ip_addr (cfile, &iaddr);
00103 
00104                         sp = &name_servers;
00105                         for (ns = name_servers; ns; ns = ns -> next) {
00106                                 sp = &ns -> next;
00107                                 if (!memcmp (&ns -> addr.sin_addr,
00108                                              iaddr.iabuf, iaddr.len))
00109                                         break;
00110                         }
00111                         if (!ns) {
00112                                 ns = new_name_server (MDL);
00113                                 if (!ns)
00114                                     log_fatal ("No memory for nameserver %s",
00115                                                piaddr (iaddr));
00116                                 ns -> next = (struct name_server *)0;
00117                                 *sp = ns;
00118                                 memcpy (&ns -> addr.sin_addr,
00119                                         iaddr.iabuf, iaddr.len);
00120 #ifdef HAVE_SA_LEN
00121                                 ns -> addr.sin_len = sizeof ns -> addr;
00122 #endif
00123                                 ns -> addr.sin_family = AF_INET;
00124                                 ns -> addr.sin_port = htons (53);
00125                                 memset (ns -> addr.sin_zero, 0,
00126                                         sizeof ns -> addr.sin_zero);
00127                         }
00128                         ns -> rcdate = parse_time;
00129                         skip_to_semi (cfile);
00130                 } else
00131                         skip_to_semi (cfile); /* Ignore what we don't grok. */
00132         } while (1);
00133         skip_token(&val, (unsigned *)0, cfile);
00134 
00135         /* Lose servers that are no longer in /etc/resolv.conf. */
00136         sl = (struct name_server *)0;
00137         for (sp = name_servers; sp; sp = ns) {
00138                 ns = sp -> next;
00139                 if (sp -> rcdate != parse_time) {
00140                         if (sl)
00141                                 sl -> next = sp -> next;
00142                         else
00143                                 name_servers = sp -> next;
00144                         /* We can't actually free the name server structure,
00145                            because somebody might be hanging on to it.    If
00146                            your /etc/resolv.conf file changes a lot, this
00147                            could be a noticeable memory leak. */
00148                 } else
00149                         sl = sp;
00150         }
00151 
00152         /* Lose domains that are no longer in /etc/resolv.conf. */
00153         dl = (struct domain_search_list *)0;
00154         for (dp = domains; dp; dp = nd) {
00155                 nd = dp -> next;
00156                 if (dp -> rcdate != parse_time) {
00157                         if (dl)
00158                                 dl -> next = dp -> next;
00159                         else
00160                                 domains = dp -> next;
00161                         free_domain_search_list (dp, MDL);
00162                 } else
00163                         dl = dp;
00164         }
00165         end_parse (&cfile);
00166 }
00167 
00168 /* Pick a name server from the /etc/resolv.conf file. */
00169 
00170 struct name_server *first_name_server ()
00171 {
00172         static TIME rcdate;
00173         struct stat st;
00174 
00175         /* Check /etc/resolv.conf and reload it if it's changed. */
00176         if (cur_time > rcdate) {
00177                 if (stat (path_resolv_conf, &st) < 0) {
00178                         log_error ("Can't stat %s", path_resolv_conf);
00179                         return (struct name_server *)0;
00180                 }
00181                 if (st.st_mtime > rcdate) {
00182                         rcdate = cur_time + 1;
00183                         
00184                         read_resolv_conf (rcdate);
00185                 }
00186         }
00187 
00188         return name_servers;
00189 }

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1