]>
Commit | Line | Data |
---|---|---|
a7de06ee TL |
1 | /* resolv.c |
2 | ||
3 | Parser for /etc/resolv.conf file. */ | |
4 | ||
5 | /* | |
f39b6e00 TL |
6 | * Copyright (c) 1996-1999 Internet Software Consortium. |
7 | * Use is subject to license terms which appear in the file named | |
8 | * ISC-LICENSE that should have accompanied this file when you | |
9 | * received it. If a file named ISC-LICENSE did not accompany this | |
10 | * file, or you are not sure the one you have is correct, you may | |
11 | * obtain an applicable copy of the license at: | |
a7de06ee | 12 | * |
f39b6e00 | 13 | * http://www.isc.org/isc-license-1.0.html. |
a7de06ee | 14 | * |
f39b6e00 TL |
15 | * This file is part of the ISC DHCP distribution. The documentation |
16 | * associated with this file is listed in the file DOCUMENTATION, | |
17 | * included in the top-level directory of this release. | |
a7de06ee | 18 | * |
f39b6e00 TL |
19 | * Support and other services are available for ISC products - see |
20 | * http://www.isc.org for more information. | |
a7de06ee TL |
21 | */ |
22 | ||
23 | #ifndef lint | |
24 | static char copyright[] = | |
f39b6e00 | 25 | "$Id: resolv.c,v 1.8 1999/03/16 05:50:37 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; |
a7de06ee TL |
26 | #endif /* not lint */ |
27 | ||
28 | #include "dhcpd.h" | |
29 | #include "dhctoken.h" | |
30 | ||
31 | struct name_server *name_servers; | |
32 | struct domain_search_list *domains; | |
33 | char path_resolv_conf [] = _PATH_RESOLV_CONF; | |
34 | ||
35 | void read_resolv_conf (parse_time) | |
36 | TIME parse_time; | |
37 | { | |
38 | FILE *cfile; | |
39 | char *val; | |
40 | int token; | |
41 | int declaration = 0; | |
42 | struct name_server *sp, *sl, *ns; | |
43 | struct domain_search_list *dp, *dl, *nd; | |
44 | struct iaddr *iaddr; | |
45 | ||
46 | new_parse (path_resolv_conf); | |
47 | ||
48 | eol_token = 1; | |
732a90b2 | 49 | if ((cfile = fopen (path_resolv_conf, "r")) == NULL) { |
8ae2d595 | 50 | log_error ("Can't open %s: %m", path_resolv_conf); |
732a90b2 TL |
51 | return; |
52 | } | |
53 | ||
a7de06ee TL |
54 | do { |
55 | token = next_token (&val, cfile); | |
56 | if (token == EOF) | |
57 | break; | |
58 | else if (token == EOL) | |
59 | continue; | |
60 | else if (token == DOMAIN || token == SEARCH) { | |
61 | do { | |
62 | struct domain_search_list *nd, **dp; | |
63 | char *dn; | |
64 | ||
65 | dn = parse_host_name (cfile); | |
66 | if (!dn) | |
67 | break; | |
68 | ||
69 | dp = &domains; | |
70 | for (nd = domains; nd; nd = nd -> next) { | |
71 | dp = &nd -> next; | |
72 | if (!strcmp (nd -> domain, dn)) | |
73 | break; | |
74 | } | |
75 | if (!nd) { | |
76 | nd = new_domain_search_list | |
77 | ("read_resolv_conf"); | |
78 | if (!nd) | |
8ae2d595 | 79 | log_fatal ("No memory for %s", dn); |
a7de06ee TL |
80 | nd -> next = |
81 | (struct domain_search_list *)0; | |
82 | *dp = nd; | |
83 | nd -> domain = dn; | |
84 | dn = (char *)0; | |
85 | } | |
86 | nd -> rcdate = parse_time; | |
c5fc5996 | 87 | token = peek_token (&val, cfile); |
2c50133e | 88 | } while (token != EOL); |
a7de06ee TL |
89 | if (token != EOL) { |
90 | parse_warn ("junk after domain declaration"); | |
91 | skip_to_semi (cfile); | |
92 | } | |
2c50133e | 93 | token = next_token (&val, cfile); |
a7de06ee TL |
94 | } else if (token == NAMESERVER) { |
95 | struct name_server *ns, **sp; | |
96 | struct iaddr iaddr; | |
97 | ||
98 | parse_ip_addr (cfile, &iaddr); | |
99 | ||
100 | sp = &name_servers; | |
101 | for (ns = name_servers; ns; ns = ns -> next) { | |
102 | sp = &ns -> next; | |
103 | if (!memcmp (&ns -> addr.sin_addr, | |
104 | iaddr.iabuf, iaddr.len)) | |
105 | break; | |
106 | } | |
107 | if (!ns) { | |
108 | ns = new_name_server ("read_resolv_conf"); | |
109 | if (!ns) | |
8ae2d595 | 110 | log_fatal ("No memory for nameserver %s", |
a7de06ee TL |
111 | piaddr (iaddr)); |
112 | ns -> next = (struct name_server *)0; | |
113 | *sp = ns; | |
114 | memcpy (&ns -> addr.sin_addr, | |
115 | iaddr.iabuf, iaddr.len); | |
116 | #ifdef HAVE_SA_LEN | |
117 | ns -> addr.sin_len = sizeof ns -> addr; | |
118 | #endif | |
119 | ns -> addr.sin_family = AF_INET; | |
120 | ns -> addr.sin_port = htons (53); | |
121 | memset (ns -> addr.sin_zero, 0, | |
122 | sizeof ns -> addr.sin_zero); | |
123 | } | |
124 | ns -> rcdate = parse_time; | |
125 | skip_to_semi (cfile); | |
357708da TL |
126 | } else |
127 | skip_to_semi (cfile); /* Ignore what we don't grok. */ | |
a7de06ee TL |
128 | } while (1); |
129 | token = next_token (&val, cfile); /* Clear the peek buffer */ | |
130 | ||
131 | /* Lose servers that are no longer in /etc/resolv.conf. */ | |
132 | sl = (struct name_server *)0; | |
133 | for (sp = name_servers; sp; sp = ns) { | |
134 | ns = sp -> next; | |
135 | if (sp -> rcdate != parse_time) { | |
136 | if (sl) | |
137 | sl -> next = sp -> next; | |
138 | else | |
139 | name_servers = sp -> next; | |
7e204261 TL |
140 | /* We can't actually free the name server structure, |
141 | because somebody might be hanging on to it. If | |
142 | your /etc/resolv.conf file changes a lot, this | |
143 | could be a noticable memory leak. */ | |
a7de06ee TL |
144 | } else |
145 | sl = sp; | |
146 | } | |
147 | ||
148 | /* Lose domains that are no longer in /etc/resolv.conf. */ | |
149 | dl = (struct domain_search_list *)0; | |
150 | for (dp = domains; dp; dp = nd) { | |
151 | nd = dp -> next; | |
152 | if (dp -> rcdate != parse_time) { | |
153 | if (dl) | |
154 | dl -> next = dp -> next; | |
155 | else | |
156 | domains = dp -> next; | |
157 | free_domain_search_list (dp, "pick_name_server"); | |
158 | } else | |
159 | dl = dp; | |
160 | } | |
161 | eol_token = 0; | |
162 | } | |
163 | ||
164 | /* Pick a name server from the /etc/resolv.conf file. */ | |
165 | ||
7e204261 | 166 | struct name_server *first_name_server () |
a7de06ee TL |
167 | { |
168 | FILE *rc; | |
169 | static TIME rcdate; | |
170 | struct stat st; | |
171 | ||
172 | /* Check /etc/resolv.conf and reload it if it's changed. */ | |
173 | if (cur_time > rcdate) { | |
732a90b2 | 174 | if (stat (path_resolv_conf, &st) < 0) { |
8ae2d595 | 175 | log_error ("Can't stat %s", path_resolv_conf); |
7e204261 | 176 | return (struct name_server *)0; |
732a90b2 | 177 | } |
a7de06ee TL |
178 | if (st.st_mtime > rcdate) { |
179 | char rcbuf [512]; | |
180 | char *s, *t, *u; | |
181 | rcdate = cur_time + 1; | |
182 | ||
183 | read_resolv_conf (rcdate); | |
184 | } | |
185 | } | |
186 | ||
7e204261 | 187 | return name_servers; |
a7de06ee | 188 | } |