blob: 8662f540cd943e8f1a8654539ed4dec23d148bc4 [file] [log] [blame]
Simon Kelleyd1ced3a2018-01-01 22:18:03 +00001/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
Simon Kelley824af852008-02-12 20:43:05 +000012
Simon Kelley73a08a22009-02-05 20:28:08 +000013 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
17#include "dnsmasq.h"
18
Simon Kelley5aabfc72007-08-29 11:24:47 +010019static struct crec *cache_head = NULL, *cache_tail = NULL, **hash_table = NULL;
Simon Kelley7622fc02009-06-04 20:32:05 +010020#ifdef HAVE_DHCP
21static struct crec *dhcp_spare = NULL;
22#endif
23static struct crec *new_chain = NULL;
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +010024static int insert_error;
Simon Kelley5aabfc72007-08-29 11:24:47 +010025static union bigname *big_free = NULL;
26static int bignames_left, hash_size;
Simon Kelley9e4abcb2004-01-22 19:47:41 +000027
Simon Kelleyb6f926f2018-08-21 17:46:52 +010028static void make_non_terminals(struct crec *source);
Simon Kelleya799ca02018-10-18 19:35:29 +010029static struct crec *really_insert(char *name, struct all_addr *addr,
30 time_t now, unsigned long ttl, unsigned short flags);
Simon Kelleyb6f926f2018-08-21 17:46:52 +010031
Simon Kelley16972692006-10-16 20:04:18 +010032/* type->string mapping: this is also used by the name-hash function as a mixing table. */
33static const struct {
34 unsigned int type;
35 const char * const name;
36} typestr[] = {
37 { 1, "A" },
38 { 2, "NS" },
39 { 5, "CNAME" },
40 { 6, "SOA" },
41 { 10, "NULL" },
42 { 11, "WKS" },
43 { 12, "PTR" },
44 { 13, "HINFO" },
45 { 15, "MX" },
46 { 16, "TXT" },
47 { 22, "NSAP" },
48 { 23, "NSAP_PTR" },
49 { 24, "SIG" },
50 { 25, "KEY" },
51 { 28, "AAAA" },
Simon Kelleyaa6f8322017-10-27 22:52:26 +010052 { 29, "LOC" },
Simon Kelley16972692006-10-16 20:04:18 +010053 { 33, "SRV" },
Simon Kelley1a6bca82008-07-11 11:11:42 +010054 { 35, "NAPTR" },
Simon Kelley16972692006-10-16 20:04:18 +010055 { 36, "KX" },
56 { 37, "CERT" },
57 { 38, "A6" },
58 { 39, "DNAME" },
59 { 41, "OPT" },
Simon Kelley0fc2f312014-01-08 10:26:58 +000060 { 43, "DS" },
61 { 46, "RRSIG" },
Simon Kelley610e7822014-02-06 14:45:17 +000062 { 47, "NSEC" },
Simon Kelley832af0b2007-01-21 20:01:28 +000063 { 48, "DNSKEY" },
Simon Kelley610e7822014-02-06 14:45:17 +000064 { 50, "NSEC3" },
Simon Kelleyaa6f8322017-10-27 22:52:26 +010065 { 51, "NSEC3PARAM" },
66 { 52, "TLSA" },
67 { 53, "SMIMEA" },
68 { 55, "HIP" },
Simon Kelley832af0b2007-01-21 20:01:28 +000069 { 249, "TKEY" },
Simon Kelley16972692006-10-16 20:04:18 +010070 { 250, "TSIG" },
71 { 251, "IXFR" },
72 { 252, "AXFR" },
73 { 253, "MAILB" },
74 { 254, "MAILA" },
Simon Kelleyb758b672018-08-23 21:41:23 +010075 { 255, "ANY" },
76 { 257, "CAA" }
Simon Kelley16972692006-10-16 20:04:18 +010077};
78
Simon Kelley9e4abcb2004-01-22 19:47:41 +000079static void cache_free(struct crec *crecp);
80static void cache_unlink(struct crec *crecp);
81static void cache_link(struct crec *crecp);
Simon Kelley4011c4e2006-10-28 16:26:19 +010082static void rehash(int size);
83static void cache_hash(struct crec *crecp);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000084
Simon Kelley45d8a242018-07-17 21:01:14 +010085void next_uid(struct crec *crecp)
Simon Kelley3f7483e2014-03-16 22:56:58 +000086{
Andyd5082152014-03-17 19:50:29 +000087 static unsigned int uid = 0;
Simon Kelley3f7483e2014-03-16 22:56:58 +000088
Simon Kelley45d8a242018-07-17 21:01:14 +010089 if (crecp->uid == UID_NONE)
90 {
91 uid++;
Andyd5082152014-03-17 19:50:29 +000092
Simon Kelley45d8a242018-07-17 21:01:14 +010093 /* uid == 0 used to indicate CNAME to interface name. */
94 if (uid == UID_NONE)
95 uid++;
96
97 crecp->uid = uid;
98 }
Simon Kelley3f7483e2014-03-16 22:56:58 +000099}
100
Simon Kelley5aabfc72007-08-29 11:24:47 +0100101void cache_init(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000102{
103 struct crec *crecp;
104 int i;
Simon Kelleyd56a6042013-10-11 14:39:03 +0100105
Simon Kelley5aabfc72007-08-29 11:24:47 +0100106 bignames_left = daemon->cachesize/10;
107
108 if (daemon->cachesize > 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000109 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100110 crecp = safe_malloc(daemon->cachesize*sizeof(struct crec));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000111
Simon Kelley5aabfc72007-08-29 11:24:47 +0100112 for (i=0; i < daemon->cachesize; i++, crecp++)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000113 {
114 cache_link(crecp);
115 crecp->flags = 0;
Simon Kelley45d8a242018-07-17 21:01:14 +0100116 crecp->uid = UID_NONE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000117 }
118 }
119
Simon Kelley4011c4e2006-10-28 16:26:19 +0100120 /* create initial hash table*/
Simon Kelley5aabfc72007-08-29 11:24:47 +0100121 rehash(daemon->cachesize);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000122}
123
Simon Kelley4011c4e2006-10-28 16:26:19 +0100124/* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
125 but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
126 will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
127 expand the table. */
128static void rehash(int size)
129{
130 struct crec **new, **old, *p, *tmp;
131 int i, new_size, old_size;
132
133 /* hash_size is a power of two. */
134 for (new_size = 64; new_size < size/10; new_size = new_size << 1);
135
136 /* must succeed in getting first instance, failure later is non-fatal */
137 if (!hash_table)
138 new = safe_malloc(new_size * sizeof(struct crec *));
Simon Kelley5aabfc72007-08-29 11:24:47 +0100139 else if (new_size <= hash_size || !(new = whine_malloc(new_size * sizeof(struct crec *))))
Simon Kelley4011c4e2006-10-28 16:26:19 +0100140 return;
141
142 for(i = 0; i < new_size; i++)
143 new[i] = NULL;
144
145 old = hash_table;
146 old_size = hash_size;
147 hash_table = new;
148 hash_size = new_size;
149
150 if (old)
151 {
152 for (i = 0; i < old_size; i++)
153 for (p = old[i]; p ; p = tmp)
154 {
155 tmp = p->hash_next;
156 cache_hash(p);
157 }
158 free(old);
159 }
160}
161
Simon Kelley3d8df262005-08-29 12:19:27 +0100162static struct crec **hash_bucket(char *name)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000163{
Simon Kelley4011c4e2006-10-28 16:26:19 +0100164 unsigned int c, val = 017465; /* Barker code - minimum self-correlation in cyclic shift */
Simon Kelley16972692006-10-16 20:04:18 +0100165 const unsigned char *mix_tab = (const unsigned char*)typestr;
166
Simon Kelley3d8df262005-08-29 12:19:27 +0100167 while((c = (unsigned char) *name++))
Simon Kelley16972692006-10-16 20:04:18 +0100168 {
169 /* don't use tolower and friends here - they may be messed up by LOCALE */
170 if (c >= 'A' && c <= 'Z')
171 c += 'a' - 'A';
Simon Kelley4011c4e2006-10-28 16:26:19 +0100172 val = ((val << 7) | (val >> (32 - 7))) + (mix_tab[(val + c) & 0x3F] ^ c);
Simon Kelley16972692006-10-16 20:04:18 +0100173 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000174
175 /* hash_size is a power of two */
Simon Kelley16972692006-10-16 20:04:18 +0100176 return hash_table + ((val ^ (val >> 16)) & (hash_size - 1));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000177}
178
179static void cache_hash(struct crec *crecp)
180{
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000181 /* maintain an invariant that all entries with F_REVERSE set
182 are at the start of the hash-chain and all non-reverse
183 immortal entries are at the end of the hash-chain.
184 This allows reverse searches and garbage collection to be optimised */
185
186 struct crec **up = hash_bucket(cache_get_name(crecp));
187
188 if (!(crecp->flags & F_REVERSE))
189 {
190 while (*up && ((*up)->flags & F_REVERSE))
191 up = &((*up)->hash_next);
192
193 if (crecp->flags & F_IMMORTAL)
Simon Kelley6b010842007-02-12 20:32:07 +0000194 while (*up && !((*up)->flags & F_IMMORTAL))
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000195 up = &((*up)->hash_next);
196 }
197 crecp->hash_next = *up;
198 *up = crecp;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000199}
Simon Kelley82e3f452014-01-31 21:05:48 +0000200
201#ifdef HAVE_DNSSEC
202static void cache_blockdata_free(struct crec *crecp)
203{
204 if (crecp->flags & F_DNSKEY)
Simon Kelley93be5b12015-12-15 12:04:40 +0000205 blockdata_free(crecp->addr.key.keydata);
Simon Kelleye3f14552014-03-01 17:58:28 +0000206 else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG))
Simon Kelley82e3f452014-01-31 21:05:48 +0000207 blockdata_free(crecp->addr.ds.keydata);
208}
209#endif
210
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000211static void cache_free(struct crec *crecp)
212{
213 crecp->flags &= ~F_FORWARD;
214 crecp->flags &= ~F_REVERSE;
Simon Kelley45d8a242018-07-17 21:01:14 +0100215 crecp->uid = UID_NONE; /* invalidate CNAMES pointing to this. */
Simon Kelleyd56a6042013-10-11 14:39:03 +0100216
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000217 if (cache_tail)
218 cache_tail->next = crecp;
219 else
220 cache_head = crecp;
221 crecp->prev = cache_tail;
222 crecp->next = NULL;
223 cache_tail = crecp;
224
225 /* retrieve big name for further use. */
226 if (crecp->flags & F_BIGNAME)
227 {
228 crecp->name.bname->next = big_free;
229 big_free = crecp->name.bname;
230 crecp->flags &= ~F_BIGNAME;
231 }
Simon Kelley072e81b2014-01-31 12:42:54 +0000232
Simon Kelley7b4ad2e2012-04-04 14:05:35 +0100233#ifdef HAVE_DNSSEC
Simon Kelley82e3f452014-01-31 21:05:48 +0000234 cache_blockdata_free(crecp);
Simon Kelley7b4ad2e2012-04-04 14:05:35 +0100235#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000236}
237
238/* insert a new cache entry at the head of the list (youngest entry) */
239static void cache_link(struct crec *crecp)
240{
241 if (cache_head) /* check needed for init code */
242 cache_head->prev = crecp;
243 crecp->next = cache_head;
244 crecp->prev = NULL;
245 cache_head = crecp;
246 if (!cache_tail)
247 cache_tail = crecp;
248}
249
250/* remove an arbitrary cache entry for promotion */
251static void cache_unlink (struct crec *crecp)
252{
253 if (crecp->prev)
254 crecp->prev->next = crecp->next;
255 else
256 cache_head = crecp->next;
257
258 if (crecp->next)
259 crecp->next->prev = crecp->prev;
260 else
261 cache_tail = crecp->prev;
262}
263
264char *cache_get_name(struct crec *crecp)
265{
266 if (crecp->flags & F_BIGNAME)
267 return crecp->name.bname->name;
Simon Kelley28866e92011-02-14 20:19:14 +0000268 else if (crecp->flags & F_NAMEP)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000269 return crecp->name.namep;
270
271 return crecp->name.sname;
272}
273
Simon Kelleyd56a6042013-10-11 14:39:03 +0100274char *cache_get_cname_target(struct crec *crecp)
275{
Simon Kelley19c51cf2014-03-18 22:38:30 +0000276 if (crecp->addr.cname.uid != SRC_INTERFACE)
Simon Kelleyd56a6042013-10-11 14:39:03 +0100277 return cache_get_name(crecp->addr.cname.target.cache);
278
279 return crecp->addr.cname.target.int_name->name;
280}
281
282
283
Simon Kelleyb75e9362012-12-07 11:50:41 +0000284struct crec *cache_enumerate(int init)
285{
286 static int bucket;
287 static struct crec *cache;
288
289 if (init)
290 {
291 bucket = 0;
292 cache = NULL;
293 }
294 else if (cache && cache->hash_next)
295 cache = cache->hash_next;
296 else
297 {
298 cache = NULL;
299 while (bucket < hash_size)
300 if ((cache = hash_table[bucket++]))
301 break;
302 }
303
304 return cache;
305}
306
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100307static int is_outdated_cname_pointer(struct crec *crecp)
308{
Andy3e21a1a2014-03-22 19:10:07 +0000309 if (!(crecp->flags & F_CNAME) || crecp->addr.cname.uid == SRC_INTERFACE)
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100310 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100311
Simon Kelleycdbee9a2012-04-04 21:55:59 +0100312 /* NB. record may be reused as DS or DNSKEY, where uid is
313 overloaded for something completely different */
Simon Kelleyd56a6042013-10-11 14:39:03 +0100314 if (crecp->addr.cname.target.cache &&
315 (crecp->addr.cname.target.cache->flags & (F_IPV4 | F_IPV6 | F_CNAME)) &&
316 crecp->addr.cname.uid == crecp->addr.cname.target.cache->uid)
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100317 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100318
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100319 return 1;
320}
321
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000322static int is_expired(time_t now, struct crec *crecp)
323{
324 if (crecp->flags & F_IMMORTAL)
325 return 0;
326
327 if (difftime(now, crecp->ttd) < 0)
328 return 0;
Simon Kelley4011c4e2006-10-28 16:26:19 +0100329
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000330 return 1;
331}
332
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100333static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags,
334 struct crec **target_crec, unsigned int *target_uid)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000335{
336 /* Scan and remove old entries.
337 If (flags & F_FORWARD) then remove any forward entries for name and any expired
338 entries but only in the same hash bucket as name.
339 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
340 entries in the whole cache.
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000341 If (flags == 0) remove any expired entries in the whole cache.
342
Simon Kelleycbc65242014-12-21 21:21:53 +0000343 In the flags & F_FORWARD case, the return code is valid, and returns a non-NULL pointer
344 to a cache entry if the name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000345
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000346 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100347 so that when we hit an entry which isn't reverse and is immortal, we're done.
348
349 If we free a crec which is a CNAME target, return the entry and uid in target_crec and target_uid.
350 This entry will get re-used with the same name, to preserve CNAMEs. */
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000351
352 struct crec *crecp, **up;
353
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000354 if (flags & F_FORWARD)
355 {
Simon Kelley6b010842007-02-12 20:32:07 +0000356 for (up = hash_bucket(name), crecp = *up; crecp; crecp = crecp->hash_next)
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000357 {
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000358 if ((crecp->flags & F_FORWARD) && hostname_isequal(cache_get_name(crecp), name))
359 {
Simon Kelleye7829ae2014-01-22 22:21:51 +0000360 /* Don't delete DNSSEC in favour of a CNAME, they can co-exist */
361 if ((flags & crecp->flags & (F_IPV4 | F_IPV6)) ||
Simon Kelley6429e422014-01-23 12:09:36 +0000362 (((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))))
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000363 {
364 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
Simon Kelleycbc65242014-12-21 21:21:53 +0000365 return crecp;
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000366 *up = crecp->hash_next;
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100367 /* If this record is for the name we're inserting and is the target
368 of a CNAME record. Make the new record for the same name, in the same
369 crec, with the same uid to avoid breaking the existing CNAME. */
370 if (crecp->uid != UID_NONE)
371 {
372 if (target_crec)
373 *target_crec = crecp;
374 if (target_uid)
375 *target_uid = crecp->uid;
376 }
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000377 cache_unlink(crecp);
378 cache_free(crecp);
379 continue;
380 }
381
382#ifdef HAVE_DNSSEC
Simon Kelley93be5b12015-12-15 12:04:40 +0000383 /* Deletion has to be class-sensitive for DS and DNSKEY */
384 if ((flags & crecp->flags & (F_DNSKEY | F_DS)) && crecp->uid == addr->addr.dnssec.class)
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000385 {
Simon Kelley824202e2014-01-23 20:59:46 +0000386 if (crecp->flags & F_CONFIG)
Simon Kelleycbc65242014-12-21 21:21:53 +0000387 return crecp;
Simon Kelley824202e2014-01-23 20:59:46 +0000388 *up = crecp->hash_next;
389 cache_unlink(crecp);
390 cache_free(crecp);
391 continue;
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000392 }
393#endif
394 }
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100395
396 if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp))
397 {
398 *up = crecp->hash_next;
399 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
400 {
401 cache_unlink(crecp);
402 cache_free(crecp);
403 }
404 continue;
405 }
406
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000407 up = &crecp->hash_next;
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000408 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000409 }
410 else
411 {
412 int i;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000413 int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ;
Simon Kelleyee875042018-10-23 22:10:17 +0100414
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000415 for (i = 0; i < hash_size; i++)
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000416 for (crecp = hash_table[i], up = &hash_table[i];
417 crecp && ((crecp->flags & F_REVERSE) || !(crecp->flags & F_IMMORTAL));
418 crecp = crecp->hash_next)
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000419 if (is_expired(now, crecp))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000420 {
421 *up = crecp->hash_next;
Simon Kelley25439062013-11-25 21:14:51 +0000422 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000423 {
424 cache_unlink(crecp);
425 cache_free(crecp);
426 }
427 }
Simon Kelley25439062013-11-25 21:14:51 +0000428 else if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) &&
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000429 (flags & crecp->flags & F_REVERSE) &&
430 (flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
431 memcmp(&crecp->addr.addr, addr, addrlen) == 0)
432 {
433 *up = crecp->hash_next;
434 cache_unlink(crecp);
435 cache_free(crecp);
436 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000437 else
438 up = &crecp->hash_next;
439 }
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000440
Simon Kelleycbc65242014-12-21 21:21:53 +0000441 return NULL;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000442}
443
444/* Note: The normal calling sequence is
445 cache_start_insert
446 cache_insert * n
447 cache_end_insert
448
449 but an abort can cause the cache_end_insert to be missed
450 in which can the next cache_start_insert cleans things up. */
451
452void cache_start_insert(void)
453{
454 /* Free any entries which didn't get committed during the last
455 insert due to error.
456 */
457 while (new_chain)
458 {
459 struct crec *tmp = new_chain->next;
460 cache_free(new_chain);
461 new_chain = tmp;
462 }
463 new_chain = NULL;
464 insert_error = 0;
465}
Simon Kelleya799ca02018-10-18 19:35:29 +0100466
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100467struct crec *cache_insert(char *name, struct all_addr *addr,
468 time_t now, unsigned long ttl, unsigned short flags)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000469{
Simon Kelleya0ab18f2014-02-13 16:38:23 +0000470 /* Don't log DNSSEC records here, done elsewhere */
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000471 if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
Simon Kelleya0ab18f2014-02-13 16:38:23 +0000472 {
473 log_query(flags | F_UPSTREAM, name, addr, NULL);
RinSatsuki28de3872015-01-10 15:22:21 +0000474 /* Don't mess with TTL for DNSSEC records. */
Simon Kelleya0ab18f2014-02-13 16:38:23 +0000475 if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
476 ttl = daemon->max_cache_ttl;
RinSatsuki28de3872015-01-10 15:22:21 +0000477 if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl)
478 ttl = daemon->min_cache_ttl;
Simon Kelleya0ab18f2014-02-13 16:38:23 +0000479 }
Simon Kelleya799ca02018-10-18 19:35:29 +0100480
481 return really_insert(name, addr, now, ttl, flags);
482}
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000483
Simon Kelleya799ca02018-10-18 19:35:29 +0100484
485static struct crec *really_insert(char *name, struct all_addr *addr,
486 time_t now, unsigned long ttl, unsigned short flags)
487{
488 struct crec *new, *target_crec = NULL;
489 union bigname *big_name = NULL;
490 int freed_all = flags & F_REVERSE;
491 int free_avail = 0;
492 unsigned int target_uid;
493
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000494 /* if previous insertion failed give up now. */
495 if (insert_error)
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100496 return NULL;
Simon Kelley8d718cb2014-02-03 16:27:37 +0000497
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000498 /* First remove any expired entries and entries for the name/address we
Simon Kelleycbc65242014-12-21 21:21:53 +0000499 are currently inserting. */
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100500 if ((new = cache_scan_free(name, addr, now, flags, &target_crec, &target_uid)))
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000501 {
Simon Kelleycbc65242014-12-21 21:21:53 +0000502 /* We're trying to insert a record over one from
503 /etc/hosts or DHCP, or other config. If the
504 existing record is for an A or AAAA and
505 the record we're trying to insert is the same,
506 just drop the insert, but don't error the whole process. */
Edwin Török41a8d9e2015-11-14 17:45:48 +0000507 if ((flags & (F_IPV4 | F_IPV6)) && (flags & F_FORWARD) && addr)
Simon Kelleycbc65242014-12-21 21:21:53 +0000508 {
509 if ((flags & F_IPV4) && (new->flags & F_IPV4) &&
510 new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr)
511 return new;
Simon Kelleycbc65242014-12-21 21:21:53 +0000512 else if ((flags & F_IPV6) && (new->flags & F_IPV6) &&
513 IN6_ARE_ADDR_EQUAL(&new->addr.addr.addr.addr6, &addr->addr.addr6))
514 return new;
Simon Kelleycbc65242014-12-21 21:21:53 +0000515 }
516
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000517 insert_error = 1;
518 return NULL;
519 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000520
521 /* Now get a cache entry from the end of the LRU list */
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100522 if (!target_crec)
523 while (1) {
524 if (!(new = cache_tail)) /* no entries left - cache is too small, bail */
525 {
526 insert_error = 1;
527 return NULL;
528 }
529
530 /* Free entry at end of LRU list, use it. */
531 if (!(new->flags & (F_FORWARD | F_REVERSE)))
532 break;
Simon Kelley8d718cb2014-02-03 16:27:37 +0000533
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100534 /* End of LRU list is still in use: if we didn't scan all the hash
535 chains for expired entries do that now. If we already tried that
536 then it's time to start spilling things. */
537
538 /* If free_avail set, we believe that an entry has been freed.
539 Bugs have been known to make this not true, resulting in
540 a tight loop here. If that happens, abandon the
541 insert. Once in this state, all inserts will probably fail. */
542 if (free_avail)
543 {
544 static int warned = 0;
545 if (!warned)
546 {
547 my_syslog(LOG_ERR, _("Internal error in cache."));
548 warned = 1;
549 }
550 insert_error = 1;
551 return NULL;
552 }
553
554 if (freed_all)
555 {
556 struct all_addr free_addr = new->addr.addr;;
557
Simon Kelley8d718cb2014-02-03 16:27:37 +0000558#ifdef HAVE_DNSSEC
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100559 /* For DNSSEC records, addr holds class. */
560 if (new->flags & (F_DS | F_DNSKEY))
561 free_addr.addr.dnssec.class = new->uid;
Simon Kelley8d718cb2014-02-03 16:27:37 +0000562#endif
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100563
564 free_avail = 1; /* Must be free space now. */
565 cache_scan_free(cache_get_name(new), &free_addr, now, new->flags, NULL, NULL);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +0100566 daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]++;
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100567 }
568 else
569 {
570 cache_scan_free(NULL, NULL, now, 0, NULL, NULL);
571 freed_all = 1;
572 }
573 }
574
575 /* Check if we need to and can allocate extra memory for a long name.
576 If that fails, give up now, always succeed for DNSSEC records. */
577 if (name && (strlen(name) > SMALLDNAME-1))
578 {
579 if (big_free)
580 {
581 big_name = big_free;
582 big_free = big_free->next;
583 }
584 else if ((bignames_left == 0 && !(flags & (F_DS | F_DNSKEY))) ||
585 !(big_name = (union bigname *)whine_malloc(sizeof(union bigname))))
586 {
587 insert_error = 1;
588 return NULL;
589 }
590 else if (bignames_left != 0)
591 bignames_left--;
592
593 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000594
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100595 /* If we freed a cache entry for our name which was a CNAME target, use that.
596 and preserve the uid, so that existing CNAMES are not broken. */
597 if (target_crec)
598 {
599 new = target_crec;
600 new->uid = target_uid;
601 }
602
603 /* Got the rest: finally grab entry. */
604 cache_unlink(new);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000605
606 new->flags = flags;
607 if (big_name)
608 {
609 new->name.bname = big_name;
610 new->flags |= F_BIGNAME;
611 }
Simon Kelley5aabfc72007-08-29 11:24:47 +0100612
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000613 if (name)
614 strcpy(cache_get_name(new), name);
615 else
616 *cache_get_name(new) = 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100617
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000618 if (addr)
Simon Kelleyb8eac192014-02-27 14:30:03 +0000619 {
620#ifdef HAVE_DNSSEC
621 if (flags & (F_DS | F_DNSKEY))
622 new->uid = addr->addr.dnssec.class;
623 else
624#endif
625 new->addr.addr = *addr;
626 }
Simon Kelley7b4ad2e2012-04-04 14:05:35 +0100627
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000628 new->ttd = now + (time_t)ttl;
629 new->next = new_chain;
630 new_chain = new;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100631
632 return new;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000633}
634
635/* after end of insertion, commit the new entries */
636void cache_end_insert(void)
637{
638 if (insert_error)
639 return;
640
641 while (new_chain)
642 {
643 struct crec *tmp = new_chain->next;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100644 /* drop CNAMEs which didn't find a target. */
645 if (is_outdated_cname_pointer(new_chain))
646 cache_free(new_chain);
647 else
648 {
649 cache_hash(new_chain);
650 cache_link(new_chain);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +0100651 daemon->metrics[METRIC_DNS_CACHE_INSERTED]++;
Simon Kelleya799ca02018-10-18 19:35:29 +0100652
653 /* If we're a child process, send this cache entry up the pipe to the master.
654 The marshalling process is rather nasty. */
655 if (daemon->pipe_to_parent != -1)
656 {
657 char *name = cache_get_name(new_chain);
658 ssize_t m = strlen(name);
659 unsigned short flags = new_chain->flags;
660#ifdef HAVE_DNSSEC
661 u16 class = new_chain->uid;
662#endif
663
664 read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), 0);
665 read_write(daemon->pipe_to_parent, (unsigned char *)name, m, 0);
666 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->ttd, sizeof(new_chain->ttd), 0);
667 read_write(daemon->pipe_to_parent, (unsigned char *)&flags, sizeof(flags), 0);
668
669 if (flags & (F_IPV4 | F_IPV6))
670 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), 0);
671#ifdef HAVE_DNSSEC
672 else if (flags & F_DNSKEY)
673 {
674 read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0);
675 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.algo, sizeof(new_chain->addr.key.algo), 0);
676 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.keytag, sizeof(new_chain->addr.key.keytag), 0);
677 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.flags, sizeof(new_chain->addr.key.flags), 0);
678 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.keylen, sizeof(new_chain->addr.key.keylen), 0);
679 blockdata_write(new_chain->addr.key.keydata, new_chain->addr.key.keylen, daemon->pipe_to_parent);
680 }
681 else if (flags & F_DS)
682 {
683 read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0);
684 /* A negative DS entry is possible and has no data, obviously. */
685 if (!(flags & F_NEG))
686 {
687 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.algo, sizeof(new_chain->addr.ds.algo), 0);
688 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.keytag, sizeof(new_chain->addr.ds.keytag), 0);
689 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.digest, sizeof(new_chain->addr.ds.digest), 0);
690 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.keylen, sizeof(new_chain->addr.ds.keylen), 0);
691 blockdata_write(new_chain->addr.ds.keydata, new_chain->addr.ds.keylen, daemon->pipe_to_parent);
692 }
693 }
694#endif
695
696 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100697 }
Simon Kelleya799ca02018-10-18 19:35:29 +0100698
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000699 new_chain = tmp;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000700 }
Simon Kelleya799ca02018-10-18 19:35:29 +0100701
702 /* signal end of cache insert in master process */
703 if (daemon->pipe_to_parent != -1)
704 {
705 ssize_t m = -1;
706 read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), 0);
707 }
708
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000709 new_chain = NULL;
710}
711
Simon Kelleya799ca02018-10-18 19:35:29 +0100712
713/* A marshalled cache entry arrives on fd, read, unmarshall and insert into cache of master process. */
714int cache_recv_insert(time_t now, int fd)
715{
716 ssize_t m;
717 struct all_addr addr;
718 unsigned long ttl;
719 time_t ttd;
720 unsigned short flags;
721 struct crec *crecp = NULL;
722
723 cache_start_insert();
724
725 while(1)
726 {
727
728 if (!read_write(fd, (unsigned char *)&m, sizeof(m), 1))
729 return 0;
730
731 if (m == -1)
732 {
733 cache_end_insert();
734 return 1;
735 }
736
737 if (!read_write(fd, (unsigned char *)daemon->namebuff, m, 1) ||
738 !read_write(fd, (unsigned char *)&ttd, sizeof(ttd), 1) ||
739 !read_write(fd, (unsigned char *)&flags, sizeof(flags), 1))
740 return 0;
741
742 daemon->namebuff[m] = 0;
743
744 ttl = difftime(ttd, now);
745
746 if (flags & (F_IPV4 | F_IPV6))
747 {
748 if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
749 return 0;
750 crecp = really_insert(daemon->namebuff, &addr, now, ttl, flags);
751 }
752 else if (flags & F_CNAME)
753 {
754 struct crec *newc = really_insert(daemon->namebuff, NULL, now, ttl, flags);
755 /* This relies on the fact the the target of a CNAME immediately preceeds
756 it because of the order of extraction in extract_addresses, and
757 the order reversal on the new_chain. */
758 if (newc)
759 {
760 if (!crecp)
761 {
762 newc->addr.cname.target.cache = NULL;
763 /* anything other than zero, to avoid being mistaken for CNAME to interface-name */
764 newc->addr.cname.uid = 1;
765 }
766 else
767 {
768 next_uid(crecp);
769 newc->addr.cname.target.cache = crecp;
770 newc->addr.cname.uid = crecp->uid;
771 }
772 }
773 }
774#ifdef HAVE_DNSSEC
775 else if (flags & (F_DNSKEY | F_DS))
776 {
777 unsigned short class, keylen, keyflags, keytag;
778 unsigned char algo, digest;
779 struct blockdata *keydata;
780
781 if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1))
782 return 0;
783 /* Cache needs to known class for DNSSEC stuff */
784 addr.addr.dnssec.class = class;
785
786 crecp = really_insert(daemon->namebuff, &addr, now, ttl, flags);
787
788 if (flags & F_DNSKEY)
789 {
790 if (!read_write(fd, (unsigned char *)&algo, sizeof(algo), 1) ||
791 !read_write(fd, (unsigned char *)&keytag, sizeof(keytag), 1) ||
792 !read_write(fd, (unsigned char *)&keyflags, sizeof(keyflags), 1) ||
793 !read_write(fd, (unsigned char *)&keylen, sizeof(keylen), 1) ||
794 !(keydata = blockdata_read(fd, keylen)))
795 return 0;
796 }
797 else if (!(flags & F_NEG))
798 {
799 if (!read_write(fd, (unsigned char *)&algo, sizeof(algo), 1) ||
800 !read_write(fd, (unsigned char *)&keytag, sizeof(keytag), 1) ||
801 !read_write(fd, (unsigned char *)&digest, sizeof(digest), 1) ||
802 !read_write(fd, (unsigned char *)&keylen, sizeof(keylen), 1) ||
803 !(keydata = blockdata_read(fd, keylen)))
804 return 0;
805 }
806
807 if (crecp)
808 {
809 if (flags & F_DNSKEY)
810 {
811 crecp->addr.key.algo = algo;
812 crecp->addr.key.keytag = keytag;
813 crecp->addr.key.flags = flags;
814 crecp->addr.key.keylen = keylen;
815 crecp->addr.key.keydata = keydata;
816 }
817 else if (!(flags & F_NEG))
818 {
819 crecp->addr.ds.algo = algo;
820 crecp->addr.ds.keytag = keytag;
821 crecp->addr.ds.digest = digest;
822 crecp->addr.ds.keylen = keylen;
823 crecp->addr.ds.keydata = keydata;
824 }
825 }
826 }
827#endif
828 }
829}
830
Simon Kelleyb6f926f2018-08-21 17:46:52 +0100831int cache_find_non_terminal(char *name, time_t now)
832{
833 struct crec *crecp;
834
835 for (crecp = *hash_bucket(name); crecp; crecp = crecp->hash_next)
836 if (!is_outdated_cname_pointer(crecp) &&
837 !is_expired(now, crecp) &&
838 (crecp->flags & F_FORWARD) &&
839 hostname_isequal(name, cache_get_name(crecp)))
840 return 1;
841
842 return 0;
843}
844
Simon Kelley12fae492014-02-04 22:03:06 +0000845struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned int prot)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000846{
847 struct crec *ans;
Simon Kelley12fae492014-02-04 22:03:06 +0000848 int no_rr = prot & F_NO_RR;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000849
Simon Kelley12fae492014-02-04 22:03:06 +0000850 prot &= ~F_NO_RR;
851
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000852 if (crecp) /* iterating */
853 ans = crecp->next;
854 else
855 {
856 /* first search, look for relevant entries and push to top of list
857 also free anything which has expired */
858 struct crec *next, **up, **insert = NULL, **chainp = &ans;
Simon Kelley28866e92011-02-14 20:19:14 +0000859 unsigned short ins_flags = 0;
Simon Kelley824af852008-02-12 20:43:05 +0000860
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000861 for (up = hash_bucket(name), crecp = *up; crecp; crecp = next)
862 {
863 next = crecp->hash_next;
864
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000865 if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000866 {
867 if ((crecp->flags & F_FORWARD) &&
868 (crecp->flags & prot) &&
869 hostname_isequal(cache_get_name(crecp), name))
870 {
Simon Kelley25439062013-11-25 21:14:51 +0000871 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000872 {
873 *chainp = crecp;
874 chainp = &crecp->next;
875 }
876 else
877 {
878 cache_unlink(crecp);
879 cache_link(crecp);
880 }
881
Simon Kelley824af852008-02-12 20:43:05 +0000882 /* Move all but the first entry up the hash chain
883 this implements round-robin.
884 Make sure that re-ordering doesn't break the hash-chain
885 order invariants.
886 */
Simon Kelley9e038942008-05-30 20:06:34 +0100887 if (insert && (crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000888 {
889 *up = crecp->hash_next;
890 crecp->hash_next = *insert;
891 *insert = crecp;
892 insert = &crecp->hash_next;
893 }
Simon Kelley9e038942008-05-30 20:06:34 +0100894 else
895 {
Simon Kelley12fae492014-02-04 22:03:06 +0000896 if (!insert && !no_rr)
Simon Kelley9e038942008-05-30 20:06:34 +0100897 {
898 insert = up;
899 ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
900 }
901 up = &crecp->hash_next;
902 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000903 }
904 else
905 /* case : not expired, incorrect entry. */
906 up = &crecp->hash_next;
907 }
908 else
909 {
910 /* expired entry, free it */
911 *up = crecp->hash_next;
Simon Kelley25439062013-11-25 21:14:51 +0000912 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000913 {
914 cache_unlink(crecp);
915 cache_free(crecp);
916 }
917 }
918 }
919
920 *chainp = cache_head;
921 }
922
923 if (ans &&
924 (ans->flags & F_FORWARD) &&
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000925 (ans->flags & prot) &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000926 hostname_isequal(cache_get_name(ans), name))
927 return ans;
928
929 return NULL;
930}
931
932struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
Simon Kelley12fae492014-02-04 22:03:06 +0000933 time_t now, unsigned int prot)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000934{
935 struct crec *ans;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000936 int addrlen = (prot == F_IPV6) ? IN6ADDRSZ : INADDRSZ;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000937
938 if (crecp) /* iterating */
939 ans = crecp->next;
940 else
941 {
942 /* first search, look for relevant entries and push to top of list
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000943 also free anything which has expired. All the reverse entries are at the
944 start of the hash chain, so we can give up when we find the first
945 non-REVERSE one. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000946 int i;
947 struct crec **up, **chainp = &ans;
948
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000949 for (i=0; i<hash_size; i++)
950 for (crecp = hash_table[i], up = &hash_table[i];
951 crecp && (crecp->flags & F_REVERSE);
952 crecp = crecp->hash_next)
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000953 if (!is_expired(now, crecp))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000954 {
Simon Kelley6b010842007-02-12 20:32:07 +0000955 if ((crecp->flags & prot) &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100956 memcmp(&crecp->addr.addr, addr, addrlen) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000957 {
Simon Kelley25439062013-11-25 21:14:51 +0000958 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000959 {
960 *chainp = crecp;
961 chainp = &crecp->next;
962 }
963 else
964 {
965 cache_unlink(crecp);
966 cache_link(crecp);
967 }
968 }
969 up = &crecp->hash_next;
970 }
971 else
972 {
973 *up = crecp->hash_next;
Simon Kelley25439062013-11-25 21:14:51 +0000974 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000975 {
976 cache_unlink(crecp);
977 cache_free(crecp);
978 }
979 }
980
981 *chainp = cache_head;
982 }
983
984 if (ans &&
985 (ans->flags & F_REVERSE) &&
986 (ans->flags & prot) &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100987 memcmp(&ans->addr.addr, addr, addrlen) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000988 return ans;
989
990 return NULL;
991}
992
Simon Kelley611ebc52012-07-16 16:23:46 +0100993static void add_hosts_cname(struct crec *target)
994{
995 struct crec *crec;
996 struct cname *a;
997
998 for (a = daemon->cnames; a; a = a->next)
Simon Kelleyb637d782016-12-13 16:44:11 +0000999 if (a->alias[1] != '*' &&
1000 hostname_isequal(cache_get_name(target), a->target) &&
Simon Kelley3a610a02018-09-26 16:50:35 +01001001 (crec = whine_malloc(SIZEOF_POINTER_CREC)))
Simon Kelley611ebc52012-07-16 16:23:46 +01001002 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001003 crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001004 crec->ttd = a->ttl;
Simon Kelley611ebc52012-07-16 16:23:46 +01001005 crec->name.namep = a->alias;
Simon Kelleyd56a6042013-10-11 14:39:03 +01001006 crec->addr.cname.target.cache = target;
Simon Kelley45d8a242018-07-17 21:01:14 +01001007 next_uid(target);
Simon Kelley611ebc52012-07-16 16:23:46 +01001008 crec->addr.cname.uid = target->uid;
Simon Kelley45d8a242018-07-17 21:01:14 +01001009 crec->uid = UID_NONE;
Simon Kelley611ebc52012-07-16 16:23:46 +01001010 cache_hash(crec);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001011 make_non_terminals(crec);
1012
Simon Kelley611ebc52012-07-16 16:23:46 +01001013 add_hosts_cname(crec); /* handle chains */
1014 }
1015}
1016
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001017static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
Simon Kelley19c51cf2014-03-18 22:38:30 +00001018 unsigned int index, struct crec **rhash, int hashsz)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001019{
Simon Kelleye759d422012-03-16 13:18:57 +00001020 struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6));
Simon Kelley9009d742008-11-14 20:04:27 +00001021 int i, nameexists = 0;
Simon Kelley205fafa2012-01-11 21:31:51 +00001022 unsigned int j;
Simon Kelley9009d742008-11-14 20:04:27 +00001023
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001024 /* Remove duplicates in hosts files. */
Simon Kelley9009d742008-11-14 20:04:27 +00001025 if (lookup && (lookup->flags & F_HOSTS))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001026 {
Simon Kelley9009d742008-11-14 20:04:27 +00001027 nameexists = 1;
1028 if (memcmp(&lookup->addr.addr, addr, addrlen) == 0)
1029 {
1030 free(cache);
1031 return;
1032 }
1033 }
1034
1035 /* Ensure there is only one address -> name mapping (first one trumps)
Simon Kelley205fafa2012-01-11 21:31:51 +00001036 We do this by steam here, The entries are kept in hash chains, linked
1037 by ->next (which is unused at this point) held in hash buckets in
Simon Kelley1ab62ae2012-01-12 11:33:16 +00001038 the array rhash, hashed on address. Note that rhash and the values
1039 in ->next are only valid whilst reading hosts files: the buckets are
1040 then freed, and the ->next pointer used for other things.
Simon Kelley205fafa2012-01-11 21:31:51 +00001041
Simon Kelley1ab62ae2012-01-12 11:33:16 +00001042 Only insert each unique address once into this hashing structure.
Simon Kelley205fafa2012-01-11 21:31:51 +00001043
1044 This complexity avoids O(n^2) divergent CPU use whilst reading
Simon Kelley70d18732015-01-31 19:59:29 +00001045 large (10000 entry) hosts files.
1046
1047 Note that we only do this process when bulk-reading hosts files,
1048 for incremental reads, rhash is NULL, and we use cache lookups
1049 instead.
1050 */
Simon Kelley9009d742008-11-14 20:04:27 +00001051
Simon Kelley70d18732015-01-31 19:59:29 +00001052 if (rhash)
Simon Kelley915363f2012-01-11 22:00:48 +00001053 {
Simon Kelley70d18732015-01-31 19:59:29 +00001054 /* hash address */
1055 for (j = 0, i = 0; i < addrlen; i++)
1056 j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
1057
1058 for (lookup = rhash[j]; lookup; lookup = lookup->next)
1059 if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) &&
1060 memcmp(&lookup->addr.addr, addr, addrlen) == 0)
1061 {
1062 cache->flags &= ~F_REVERSE;
1063 break;
1064 }
1065
1066 /* maintain address hash chain, insert new unique address */
1067 if (!lookup)
1068 {
1069 cache->next = rhash[j];
1070 rhash[j] = cache;
1071 }
Simon Kelley915363f2012-01-11 22:00:48 +00001072 }
Simon Kelley70d18732015-01-31 19:59:29 +00001073 else
1074 {
1075 /* incremental read, lookup in cache */
1076 lookup = cache_find_by_addr(NULL, addr, 0, cache->flags & (F_IPV4 | F_IPV6));
1077 if (lookup && lookup->flags & F_HOSTS)
1078 cache->flags &= ~F_REVERSE;
1079 }
1080
Simon Kelley9009d742008-11-14 20:04:27 +00001081 cache->uid = index;
Simon Kelley915363f2012-01-11 22:00:48 +00001082 memcpy(&cache->addr.addr, addr, addrlen);
Simon Kelley9009d742008-11-14 20:04:27 +00001083 cache_hash(cache);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001084 make_non_terminals(cache);
Simon Kelley9009d742008-11-14 20:04:27 +00001085
1086 /* don't need to do alias stuff for second and subsequent addresses. */
1087 if (!nameexists)
Simon Kelley611ebc52012-07-16 16:23:46 +01001088 add_hosts_cname(cache);
Simon Kelley9009d742008-11-14 20:04:27 +00001089}
1090
1091static int eatspace(FILE *f)
1092{
1093 int c, nl = 0;
1094
1095 while (1)
1096 {
1097 if ((c = getc(f)) == '#')
1098 while (c != '\n' && c != EOF)
1099 c = getc(f);
Simon Kelley832af0b2007-01-21 20:01:28 +00001100
Simon Kelley9009d742008-11-14 20:04:27 +00001101 if (c == EOF)
1102 return 1;
1103
1104 if (!isspace(c))
1105 {
1106 ungetc(c, f);
1107 return nl;
1108 }
1109
1110 if (c == '\n')
1111 nl = 1;
1112 }
1113}
1114
1115static int gettok(FILE *f, char *token)
1116{
1117 int c, count = 0;
1118
1119 while (1)
1120 {
1121 if ((c = getc(f)) == EOF)
1122 return (count == 0) ? EOF : 1;
1123
1124 if (isspace(c) || c == '#')
1125 {
1126 ungetc(c, f);
1127 return eatspace(f);
1128 }
1129
1130 if (count < (MAXDNAME - 1))
1131 {
1132 token[count++] = c;
1133 token[count] = 0;
1134 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001135 }
1136}
1137
Simon Kelley70d18732015-01-31 19:59:29 +00001138int read_hostsfile(char *filename, unsigned int index, int cache_size, struct crec **rhash, int hashsz)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001139{
1140 FILE *f = fopen(filename, "r");
Simon Kelley9009d742008-11-14 20:04:27 +00001141 char *token = daemon->namebuff, *domain_suffix = NULL;
Simon Kelley4011c4e2006-10-28 16:26:19 +01001142 int addr_count = 0, name_count = cache_size, lineno = 0;
Simon Kelley205fafa2012-01-11 21:31:51 +00001143 unsigned short flags = 0;
1144 struct all_addr addr;
1145 int atnl, addrlen = 0;
Simon Kelley4011c4e2006-10-28 16:26:19 +01001146
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001147 if (!f)
1148 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001149 my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
André Glüpkereddf3652016-01-12 12:54:17 +00001150 return cache_size;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001151 }
Simon Kelley9009d742008-11-14 20:04:27 +00001152
1153 eatspace(f);
1154
1155 while ((atnl = gettok(f, token)) != EOF)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001156 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001157 lineno++;
Simon Kelley9009d742008-11-14 20:04:27 +00001158
Simon Kelley3d8df262005-08-29 12:19:27 +01001159 if (inet_pton(AF_INET, token, &addr) > 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001160 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001161 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001162 addrlen = INADDRSZ;
Simon Kelley9009d742008-11-14 20:04:27 +00001163 domain_suffix = get_domain(addr.addr.addr4);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001164 }
Simon Kelley3d8df262005-08-29 12:19:27 +01001165 else if (inet_pton(AF_INET6, token, &addr) > 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001166 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001167 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001168 addrlen = IN6ADDRSZ;
Simon Kelley4cb1b322012-02-06 14:30:41 +00001169 domain_suffix = get_domain6(&addr.addr.addr6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001170 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001171 else
Simon Kelleyb8187c82005-11-26 21:46:27 +00001172 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001173 my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
Simon Kelley9009d742008-11-14 20:04:27 +00001174 while (atnl == 0)
1175 atnl = gettok(f, token);
Simon Kelleyb8187c82005-11-26 21:46:27 +00001176 continue;
1177 }
Simon Kelley9009d742008-11-14 20:04:27 +00001178
Simon Kelley9009d742008-11-14 20:04:27 +00001179 addr_count++;
1180
1181 /* rehash every 1000 names. */
Simon Kelley70d18732015-01-31 19:59:29 +00001182 if (rhash && ((name_count - cache_size) > 1000))
Simon Kelley9009d742008-11-14 20:04:27 +00001183 {
1184 rehash(name_count);
1185 cache_size = name_count;
1186 }
1187
1188 while (atnl == 0)
1189 {
1190 struct crec *cache;
Simon Kelley1f15b812009-10-13 17:49:32 +01001191 int fqdn, nomem;
1192 char *canon;
Simon Kelley9009d742008-11-14 20:04:27 +00001193
1194 if ((atnl = gettok(f, token)) == EOF)
1195 break;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001196
Simon Kelley9009d742008-11-14 20:04:27 +00001197 fqdn = !!strchr(token, '.');
1198
Simon Kelley1f15b812009-10-13 17:49:32 +01001199 if ((canon = canonicalise(token, &nomem)))
Simon Kelley9009d742008-11-14 20:04:27 +00001200 {
1201 /* If set, add a version of the name with a default domain appended */
Simon Kelley28866e92011-02-14 20:19:14 +00001202 if (option_bool(OPT_EXPAND) && domain_suffix && !fqdn &&
Simon Kelley3a610a02018-09-26 16:50:35 +01001203 (cache = whine_malloc(SIZEOF_BARE_CREC + strlen(canon) + 2 + strlen(domain_suffix))))
Simon Kelley9009d742008-11-14 20:04:27 +00001204 {
Simon Kelley1f15b812009-10-13 17:49:32 +01001205 strcpy(cache->name.sname, canon);
Simon Kelley9009d742008-11-14 20:04:27 +00001206 strcat(cache->name.sname, ".");
1207 strcat(cache->name.sname, domain_suffix);
Simon Kelleye759d422012-03-16 13:18:57 +00001208 cache->flags = flags;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001209 cache->ttd = daemon->local_ttl;
Simon Kelleye759d422012-03-16 13:18:57 +00001210 add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
Simon Kelley9009d742008-11-14 20:04:27 +00001211 name_count++;
1212 }
Simon Kelley3a610a02018-09-26 16:50:35 +01001213 if ((cache = whine_malloc(SIZEOF_BARE_CREC + strlen(canon) + 1)))
Simon Kelley9009d742008-11-14 20:04:27 +00001214 {
Simon Kelley1f15b812009-10-13 17:49:32 +01001215 strcpy(cache->name.sname, canon);
Simon Kelleye759d422012-03-16 13:18:57 +00001216 cache->flags = flags;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001217 cache->ttd = daemon->local_ttl;
Simon Kelleye759d422012-03-16 13:18:57 +00001218 add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
Simon Kelley9009d742008-11-14 20:04:27 +00001219 name_count++;
1220 }
Simon Kelley1f15b812009-10-13 17:49:32 +01001221 free(canon);
1222
Simon Kelley9009d742008-11-14 20:04:27 +00001223 }
Simon Kelley1f15b812009-10-13 17:49:32 +01001224 else if (!nomem)
Simon Kelley9009d742008-11-14 20:04:27 +00001225 my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
1226 }
1227 }
1228
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001229 fclose(f);
Simon Kelley9009d742008-11-14 20:04:27 +00001230
Simon Kelley70d18732015-01-31 19:59:29 +00001231 if (rhash)
Simon Kelleyf9c86372015-02-03 21:52:48 +00001232 rehash(name_count);
1233
1234 my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
1235
Simon Kelley4011c4e2006-10-28 16:26:19 +01001236 return name_count;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001237}
1238
Simon Kelley7622fc02009-06-04 20:32:05 +01001239void cache_reload(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001240{
1241 struct crec *cache, **up, *tmp;
Simon Kelley1ab62ae2012-01-12 11:33:16 +00001242 int revhashsz, i, total_size = daemon->cachesize;
Simon Kelley7622fc02009-06-04 20:32:05 +01001243 struct hostsfile *ah;
Simon Kelleye759d422012-03-16 13:18:57 +00001244 struct host_record *hr;
1245 struct name_list *nl;
Simon Kelleyd56a6042013-10-11 14:39:03 +01001246 struct cname *a;
1247 struct interface_name *intr;
Simon Kelley0fc2f312014-01-08 10:26:58 +00001248#ifdef HAVE_DNSSEC
Simon Kelleyee415862014-02-11 11:07:22 +00001249 struct ds_config *ds;
Simon Kelley0fc2f312014-01-08 10:26:58 +00001250#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001251
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001252 daemon->metrics[METRIC_DNS_CACHE_INSERTED] = 0;
1253 daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED] = 0;
Simon Kelley59353a62004-11-21 19:34:28 +00001254
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001255 for (i=0; i<hash_size; i++)
1256 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
1257 {
Simon Kelley0fc2f312014-01-08 10:26:58 +00001258#ifdef HAVE_DNSSEC
Simon Kelley82e3f452014-01-31 21:05:48 +00001259 cache_blockdata_free(cache);
Simon Kelley0fc2f312014-01-08 10:26:58 +00001260#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001261 tmp = cache->hash_next;
Simon Kelley25439062013-11-25 21:14:51 +00001262 if (cache->flags & (F_HOSTS | F_CONFIG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001263 {
1264 *up = cache->hash_next;
1265 free(cache);
1266 }
1267 else if (!(cache->flags & F_DHCP))
1268 {
1269 *up = cache->hash_next;
1270 if (cache->flags & F_BIGNAME)
1271 {
1272 cache->name.bname->next = big_free;
1273 big_free = cache->name.bname;
1274 }
1275 cache->flags = 0;
1276 }
1277 else
1278 up = &cache->hash_next;
1279 }
1280
Simon Kelleyd56a6042013-10-11 14:39:03 +01001281 /* Add CNAMEs to interface_names to the cache */
1282 for (a = daemon->cnames; a; a = a->next)
1283 for (intr = daemon->int_names; intr; intr = intr->next)
Simon Kelleyb637d782016-12-13 16:44:11 +00001284 if (a->alias[1] != '*' &&
1285 hostname_isequal(a->target, intr->name) &&
Simon Kelley3a610a02018-09-26 16:50:35 +01001286 ((cache = whine_malloc(SIZEOF_POINTER_CREC))))
Simon Kelleyd56a6042013-10-11 14:39:03 +01001287 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001288 cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001289 cache->ttd = a->ttl;
Simon Kelley532066e2013-11-26 10:14:47 +00001290 cache->name.namep = a->alias;
1291 cache->addr.cname.target.int_name = intr;
Simon Kelley19c51cf2014-03-18 22:38:30 +00001292 cache->addr.cname.uid = SRC_INTERFACE;
Simon Kelley45d8a242018-07-17 21:01:14 +01001293 cache->uid = UID_NONE;
Simon Kelley532066e2013-11-26 10:14:47 +00001294 cache_hash(cache);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001295 make_non_terminals(cache);
Simon Kelley532066e2013-11-26 10:14:47 +00001296 add_hosts_cname(cache); /* handle chains */
Simon Kelleyd56a6042013-10-11 14:39:03 +01001297 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001298
1299#ifdef HAVE_DNSSEC
Simon Kelleyee415862014-02-11 11:07:22 +00001300 for (ds = daemon->ds; ds; ds = ds->next)
Simon Kelley3a610a02018-09-26 16:50:35 +01001301 if ((cache = whine_malloc(SIZEOF_POINTER_CREC)) &&
Simon Kelleyee415862014-02-11 11:07:22 +00001302 (cache->addr.ds.keydata = blockdata_alloc(ds->digest, ds->digestlen)))
Simon Kelley0fc2f312014-01-08 10:26:58 +00001303 {
Simon Kelleyee415862014-02-11 11:07:22 +00001304 cache->flags = F_FORWARD | F_IMMORTAL | F_DS | F_CONFIG | F_NAMEP;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001305 cache->ttd = daemon->local_ttl;
Simon Kelleyee415862014-02-11 11:07:22 +00001306 cache->name.namep = ds->name;
1307 cache->addr.ds.keylen = ds->digestlen;
1308 cache->addr.ds.algo = ds->algo;
1309 cache->addr.ds.keytag = ds->keytag;
1310 cache->addr.ds.digest = ds->digest_type;
1311 cache->uid = ds->class;
Simon Kelley0fc2f312014-01-08 10:26:58 +00001312 cache_hash(cache);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001313 make_non_terminals(cache);
Simon Kelley0fc2f312014-01-08 10:26:58 +00001314 }
1315#endif
Simon Kelleyd56a6042013-10-11 14:39:03 +01001316
Simon Kelleye759d422012-03-16 13:18:57 +00001317 /* borrow the packet buffer for a temporary by-address hash */
1318 memset(daemon->packet, 0, daemon->packet_buff_sz);
1319 revhashsz = daemon->packet_buff_sz / sizeof(struct crec *);
1320 /* we overwrote the buffer... */
1321 daemon->srv_save = NULL;
1322
1323 /* Do host_records in config. */
1324 for (hr = daemon->host_records; hr; hr = hr->next)
1325 for (nl = hr->names; nl; nl = nl->next)
1326 {
1327 if (hr->addr.s_addr != 0 &&
Simon Kelley3a610a02018-09-26 16:50:35 +01001328 (cache = whine_malloc(SIZEOF_POINTER_CREC)))
Simon Kelleye759d422012-03-16 13:18:57 +00001329 {
1330 cache->name.namep = nl->name;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001331 cache->ttd = hr->ttl;
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001332 cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG;
Simon Kelley19c51cf2014-03-18 22:38:30 +00001333 add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
Simon Kelleye759d422012-03-16 13:18:57 +00001334 }
Simon Kelleyee875042018-10-23 22:10:17 +01001335
Simon Kelleye759d422012-03-16 13:18:57 +00001336 if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) &&
Simon Kelley3a610a02018-09-26 16:50:35 +01001337 (cache = whine_malloc(SIZEOF_POINTER_CREC)))
Simon Kelleye759d422012-03-16 13:18:57 +00001338 {
1339 cache->name.namep = nl->name;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001340 cache->ttd = hr->ttl;
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001341 cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG;
Simon Kelley19c51cf2014-03-18 22:38:30 +00001342 add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
Simon Kelleye759d422012-03-16 13:18:57 +00001343 }
Simon Kelleye759d422012-03-16 13:18:57 +00001344 }
1345
Simon Kelley28866e92011-02-14 20:19:14 +00001346 if (option_bool(OPT_NO_HOSTS) && !daemon->addn_hosts)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001347 {
Simon Kelley5aabfc72007-08-29 11:24:47 +01001348 if (daemon->cachesize > 0)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001349 my_syslog(LOG_INFO, _("cleared cache"));
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001350 }
Simon Kelleycaeea192015-02-14 20:08:56 +00001351 else
1352 {
1353 if (!option_bool(OPT_NO_HOSTS))
1354 total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
1355
1356 daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
1357 for (ah = daemon->addn_hosts; ah; ah = ah->next)
1358 if (!(ah->flags & AH_INACTIVE))
1359 total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
1360 }
1361
Simon Kelley70d18732015-01-31 19:59:29 +00001362#ifdef HAVE_INOTIFY
1363 set_dynamic_inotify(AH_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
1364#endif
1365
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001366}
1367
Simon Kelley7622fc02009-06-04 20:32:05 +01001368#ifdef HAVE_DHCP
Simon Kelley7de060b2011-08-26 17:24:52 +01001369struct in_addr a_record_from_hosts(char *name, time_t now)
1370{
1371 struct crec *crecp = NULL;
1372 struct in_addr ret;
1373
1374 while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
1375 if (crecp->flags & F_HOSTS)
1376 return *(struct in_addr *)&crecp->addr;
1377
1378 my_syslog(MS_DHCP | LOG_WARNING, _("No IPv4 address found for %s"), name);
1379
1380 ret.s_addr = 0;
1381 return ret;
1382}
1383
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001384void cache_unhash_dhcp(void)
1385{
Simon Kelley6b010842007-02-12 20:32:07 +00001386 struct crec *cache, **up;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001387 int i;
1388
1389 for (i=0; i<hash_size; i++)
1390 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next)
1391 if (cache->flags & F_DHCP)
Simon Kelley6b010842007-02-12 20:32:07 +00001392 {
1393 *up = cache->hash_next;
1394 cache->next = dhcp_spare;
1395 dhcp_spare = cache;
1396 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001397 else
1398 up = &cache->hash_next;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001399}
1400
Simon Kelley611ebc52012-07-16 16:23:46 +01001401static void add_dhcp_cname(struct crec *target, time_t ttd)
1402{
1403 struct crec *aliasc;
1404 struct cname *a;
1405
1406 for (a = daemon->cnames; a; a = a->next)
Simon Kelleyb637d782016-12-13 16:44:11 +00001407 if (a->alias[1] != '*' &&
1408 hostname_isequal(cache_get_name(target), a->target))
Simon Kelley611ebc52012-07-16 16:23:46 +01001409 {
1410 if ((aliasc = dhcp_spare))
1411 dhcp_spare = dhcp_spare->next;
1412 else /* need new one */
Simon Kelley3a610a02018-09-26 16:50:35 +01001413 aliasc = whine_malloc(SIZEOF_POINTER_CREC);
Simon Kelley611ebc52012-07-16 16:23:46 +01001414
1415 if (aliasc)
1416 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001417 aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME | F_CONFIG;
Simon Kelley611ebc52012-07-16 16:23:46 +01001418 if (ttd == 0)
1419 aliasc->flags |= F_IMMORTAL;
1420 else
1421 aliasc->ttd = ttd;
1422 aliasc->name.namep = a->alias;
Simon Kelleyd56a6042013-10-11 14:39:03 +01001423 aliasc->addr.cname.target.cache = target;
Simon Kelley45d8a242018-07-17 21:01:14 +01001424 next_uid(target);
Simon Kelley611ebc52012-07-16 16:23:46 +01001425 aliasc->addr.cname.uid = target->uid;
Simon Kelley45d8a242018-07-17 21:01:14 +01001426 aliasc->uid = UID_NONE;
Simon Kelley611ebc52012-07-16 16:23:46 +01001427 cache_hash(aliasc);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001428 make_non_terminals(aliasc);
Simon Kelley611ebc52012-07-16 16:23:46 +01001429 add_dhcp_cname(aliasc, ttd);
1430 }
1431 }
1432}
1433
Simon Kelley4cb1b322012-02-06 14:30:41 +00001434void cache_add_dhcp_entry(char *host_name, int prot,
1435 struct all_addr *host_address, time_t ttd)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001436{
Simon Kelley12d71ed2012-08-30 15:16:41 +01001437 struct crec *crec = NULL, *fail_crec = NULL;
Simon Kelley4cb1b322012-02-06 14:30:41 +00001438 unsigned short flags = F_IPV4;
Simon Kelley824af852008-02-12 20:43:05 +00001439 int in_hosts = 0;
Simon Kelley4cb1b322012-02-06 14:30:41 +00001440 size_t addrlen = sizeof(struct in_addr);
1441
Simon Kelley4cb1b322012-02-06 14:30:41 +00001442 if (prot == AF_INET6)
1443 {
1444 flags = F_IPV6;
1445 addrlen = sizeof(struct in6_addr);
1446 }
Simon Kelley9009d742008-11-14 20:04:27 +00001447
Simon Kelley12d71ed2012-08-30 15:16:41 +01001448 inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN);
1449
Simon Kelley4cb1b322012-02-06 14:30:41 +00001450 while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001451 {
Simon Kelley824af852008-02-12 20:43:05 +00001452 /* check all addresses associated with name */
Simon Kelley25439062013-11-25 21:14:51 +00001453 if (crec->flags & (F_HOSTS | F_CONFIG))
Simon Kelley1ab84e22004-01-29 16:48:35 +00001454 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001455 if (crec->flags & F_CNAME)
Simon Kelley28866e92011-02-14 20:19:14 +00001456 my_syslog(MS_DHCP | LOG_WARNING,
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001457 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
Simon Kelley4cb1b322012-02-06 14:30:41 +00001458 host_name, daemon->addrbuff);
Simon Kelley12d71ed2012-08-30 15:16:41 +01001459 else if (memcmp(&crec->addr.addr, host_address, addrlen) == 0)
1460 in_hosts = 1;
1461 else
1462 fail_crec = crec;
Simon Kelley1ab84e22004-01-29 16:48:35 +00001463 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001464 else if (!(crec->flags & F_DHCP))
Simon Kelley824af852008-02-12 20:43:05 +00001465 {
Simon Kelleyeb1fe152018-07-18 20:59:52 +01001466 cache_scan_free(host_name, NULL, 0, crec->flags & (flags | F_CNAME | F_FORWARD), NULL, NULL);
Simon Kelley824af852008-02-12 20:43:05 +00001467 /* scan_free deletes all addresses associated with name */
1468 break;
1469 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001470 }
Simon Kelley824af852008-02-12 20:43:05 +00001471
Simon Kelley12d71ed2012-08-30 15:16:41 +01001472 /* if in hosts, don't need DHCP record */
1473 if (in_hosts)
Simon Kelley824af852008-02-12 20:43:05 +00001474 return;
Simon Kelley12d71ed2012-08-30 15:16:41 +01001475
1476 /* Name in hosts, address doesn't match */
1477 if (fail_crec)
1478 {
1479 inet_ntop(prot, &fail_crec->addr.addr, daemon->namebuff, MAXDNAME);
1480 my_syslog(MS_DHCP | LOG_WARNING,
1481 _("not giving name %s to the DHCP lease of %s because "
1482 "the name exists in %s with address %s"),
1483 host_name, daemon->addrbuff,
1484 record_source(fail_crec->uid), daemon->namebuff);
1485 return;
1486 }
1487
1488 if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, flags)))
1489 {
1490 if (crec->flags & F_NEG)
1491 {
1492 flags |= F_REVERSE;
Simon Kelleyeb1fe152018-07-18 20:59:52 +01001493 cache_scan_free(NULL, (struct all_addr *)host_address, 0, flags, NULL, NULL);
Simon Kelley12d71ed2012-08-30 15:16:41 +01001494 }
1495 }
1496 else
1497 flags |= F_REVERSE;
1498
1499 if ((crec = dhcp_spare))
Simon Kelley6b010842007-02-12 20:32:07 +00001500 dhcp_spare = dhcp_spare->next;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001501 else /* need new one */
Simon Kelley3a610a02018-09-26 16:50:35 +01001502 crec = whine_malloc(SIZEOF_POINTER_CREC);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001503
1504 if (crec) /* malloc may fail */
1505 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001506 crec->flags = flags | F_NAMEP | F_DHCP | F_FORWARD;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001507 if (ttd == 0)
1508 crec->flags |= F_IMMORTAL;
1509 else
1510 crec->ttd = ttd;
Simon Kelley4cb1b322012-02-06 14:30:41 +00001511 crec->addr.addr = *host_address;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001512 crec->name.namep = host_name;
Simon Kelley45d8a242018-07-17 21:01:14 +01001513 crec->uid = UID_NONE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001514 cache_hash(crec);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001515 make_non_terminals(crec);
Simon Kelley9009d742008-11-14 20:04:27 +00001516
Simon Kelley611ebc52012-07-16 16:23:46 +01001517 add_dhcp_cname(crec, ttd);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001518 }
1519}
Simon Kelley7622fc02009-06-04 20:32:05 +01001520#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001521
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001522/* Called when we put a local or DHCP name into the cache.
1523 Creates empty cache entries for subnames (ie,
1524 for three.two.one, for two.one and one), without
1525 F_IPV4 or F_IPV6 or F_CNAME set. These convert
1526 NXDOMAIN answers to NoData ones. */
1527static void make_non_terminals(struct crec *source)
1528{
1529 char *name = cache_get_name(source);
Simon Kelleyea6cc332018-09-18 23:21:17 +01001530 struct crec *crecp, *tmp, **up;
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001531 int type = F_HOSTS | F_CONFIG;
1532#ifdef HAVE_DHCP
1533 if (source->flags & F_DHCP)
1534 type = F_DHCP;
1535#endif
1536
1537 /* First delete any empty entries for our new real name. Note that
1538 we only delete empty entries deriving from DHCP for a new DHCP-derived
1539 entry and vice-versa for HOSTS and CONFIG. This ensures that
1540 non-terminals from DHCP go when we reload DHCP and
1541 for HOSTS/CONFIG when we re-read. */
1542 for (up = hash_bucket(name), crecp = *up; crecp; crecp = tmp)
1543 {
1544 tmp = crecp->hash_next;
1545
1546 if (!is_outdated_cname_pointer(crecp) &&
1547 (crecp->flags & F_FORWARD) &&
1548 (crecp->flags & type) &&
Simon Kelleycbfbd172018-08-21 18:25:18 +01001549 !(crecp->flags & (F_IPV4 | F_IPV6 | F_CNAME | F_DNSKEY | F_DS)) &&
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001550 hostname_isequal(name, cache_get_name(crecp)))
1551 {
1552 *up = crecp->hash_next;
1553#ifdef HAVE_DHCP
1554 if (type & F_DHCP)
1555 {
1556 crecp->next = dhcp_spare;
1557 dhcp_spare = crecp;
1558 }
1559 else
1560#endif
1561 free(crecp);
1562 break;
1563 }
1564 else
1565 up = &crecp->hash_next;
1566 }
1567
1568 while ((name = strchr(name, '.')))
1569 {
1570 name++;
1571
1572 /* Look for one existing, don't need another */
1573 for (crecp = *hash_bucket(name); crecp; crecp = crecp->hash_next)
1574 if (!is_outdated_cname_pointer(crecp) &&
1575 (crecp->flags & F_FORWARD) &&
1576 (crecp->flags & type) &&
1577 hostname_isequal(name, cache_get_name(crecp)))
1578 break;
1579
1580 if (crecp)
1581 {
1582 /* If the new name expires later, transfer that time to
1583 empty non-terminal entry. */
1584 if (!(crecp->flags & F_IMMORTAL))
1585 {
1586 if (source->flags & F_IMMORTAL)
1587 crecp->flags |= F_IMMORTAL;
1588 else if (difftime(crecp->ttd, source->ttd) < 0)
1589 crecp->ttd = source->ttd;
1590 }
1591 continue;
1592 }
1593
1594#ifdef HAVE_DHCP
1595 if ((source->flags & F_DHCP) && dhcp_spare)
1596 {
1597 crecp = dhcp_spare;
1598 dhcp_spare = dhcp_spare->next;
1599 }
1600 else
1601#endif
Simon Kelley3a610a02018-09-26 16:50:35 +01001602 crecp = whine_malloc(SIZEOF_POINTER_CREC);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001603
Simon Kelleyea6cc332018-09-18 23:21:17 +01001604 if (crecp)
1605 {
Simon Kelley48b090c2018-09-26 12:53:59 +01001606 crecp->flags = (source->flags | F_NAMEP) & ~(F_IPV4 | F_IPV6 | F_CNAME | F_DNSKEY | F_DS | F_REVERSE);
1607 crecp->ttd = source->ttd;
Simon Kelleyea6cc332018-09-18 23:21:17 +01001608 crecp->name.namep = name;
1609
1610 cache_hash(crecp);
1611 }
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001612 }
1613}
1614
Kevin Darbyshire-Bryant7ac9ae12016-09-09 20:52:08 +01001615#ifndef NO_ID
Simon Kelleyfec216d2014-03-27 20:54:34 +00001616int cache_make_stat(struct txt_record *t)
1617{
1618 static char *buff = NULL;
1619 static int bufflen = 60;
1620 int len;
1621 struct server *serv, *serv1;
1622 char *p;
1623
1624 if (!buff && !(buff = whine_malloc(60)))
1625 return 0;
1626
1627 p = buff;
1628
1629 switch (t->stat)
1630 {
1631 case TXT_STAT_CACHESIZE:
1632 sprintf(buff+1, "%d", daemon->cachesize);
1633 break;
1634
1635 case TXT_STAT_INSERTS:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001636 sprintf(buff+1, "%d", daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001637 break;
1638
1639 case TXT_STAT_EVICTIONS:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001640 sprintf(buff+1, "%d", daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001641 break;
1642
1643 case TXT_STAT_MISSES:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001644 sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001645 break;
1646
1647 case TXT_STAT_HITS:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001648 sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001649 break;
1650
1651#ifdef HAVE_AUTH
1652 case TXT_STAT_AUTH:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001653 sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001654 break;
1655#endif
1656
1657 case TXT_STAT_SERVERS:
1658 /* sum counts from different records for same server */
1659 for (serv = daemon->servers; serv; serv = serv->next)
1660 serv->flags &= ~SERV_COUNTED;
1661
1662 for (serv = daemon->servers; serv; serv = serv->next)
1663 if (!(serv->flags &
1664 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
1665 {
1666 char *new, *lenp;
1667 int port, newlen, bytes_avail, bytes_needed;
1668 unsigned int queries = 0, failed_queries = 0;
1669 for (serv1 = serv; serv1; serv1 = serv1->next)
1670 if (!(serv1->flags &
1671 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
1672 sockaddr_isequal(&serv->addr, &serv1->addr))
1673 {
1674 serv1->flags |= SERV_COUNTED;
1675 queries += serv1->queries;
1676 failed_queries += serv1->failed_queries;
1677 }
1678 port = prettyprint_addr(&serv->addr, daemon->addrbuff);
1679 lenp = p++; /* length */
Simon Kelley04b0ac02015-04-06 17:19:13 +01001680 bytes_avail = bufflen - (p - buff );
Simon Kelleyfec216d2014-03-27 20:54:34 +00001681 bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
1682 if (bytes_needed >= bytes_avail)
1683 {
1684 /* expand buffer if necessary */
1685 newlen = bytes_needed + 1 + bufflen - bytes_avail;
1686 if (!(new = whine_malloc(newlen)))
1687 return 0;
1688 memcpy(new, buff, bufflen);
1689 free(buff);
1690 p = new + (p - buff);
1691 lenp = p - 1;
1692 buff = new;
1693 bufflen = newlen;
Simon Kelley04b0ac02015-04-06 17:19:13 +01001694 bytes_avail = bufflen - (p - buff );
Simon Kelleyfec216d2014-03-27 20:54:34 +00001695 bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
1696 }
1697 *lenp = bytes_needed;
1698 p += bytes_needed;
1699 }
1700 t->txt = (unsigned char *)buff;
1701 t->len = p - buff;
1702 return 1;
1703 }
1704
1705 len = strlen(buff+1);
1706 t->txt = (unsigned char *)buff;
1707 t->len = len + 1;
1708 *buff = len;
1709 return 1;
1710}
Kevin Darbyshire-Bryant7ac9ae12016-09-09 20:52:08 +01001711#endif
Simon Kelley9009d742008-11-14 20:04:27 +00001712
Simon Kelley394ff492015-03-29 22:17:14 +01001713/* There can be names in the cache containing control chars, don't
1714 mess up logging or open security holes. */
1715static char *sanitise(char *name)
1716{
1717 unsigned char *r;
Simon Kelley794fccc2015-03-29 22:35:44 +01001718 if (name)
1719 for (r = (unsigned char *)name; *r; r++)
1720 if (!isprint((int)*r))
1721 return "<name unprintable>";
Simon Kelley394ff492015-03-29 22:17:14 +01001722
1723 return name;
1724}
1725
1726
Simon Kelley5aabfc72007-08-29 11:24:47 +01001727void dump_cache(time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001728{
Simon Kelley824af852008-02-12 20:43:05 +00001729 struct server *serv, *serv1;
1730
1731 my_syslog(LOG_INFO, _("time %lu"), (unsigned long)now);
1732 my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001733 daemon->cachesize, daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED], daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
Simon Kelley824af852008-02-12 20:43:05 +00001734 my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001735 daemon->metrics[METRIC_DNS_QUERIES_FORWARDED], daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
Simon Kelleyb485ed92013-10-18 22:00:39 +01001736#ifdef HAVE_AUTH
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001737 my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
Simon Kelleyb485ed92013-10-18 22:00:39 +01001738#endif
Simon Kelleyc2207682014-01-08 18:04:20 +00001739#ifdef HAVE_DNSSEC
1740 blockdata_report();
1741#endif
Simon Kelley824af852008-02-12 20:43:05 +00001742
Simon Kelley824af852008-02-12 20:43:05 +00001743 /* sum counts from different records for same server */
1744 for (serv = daemon->servers; serv; serv = serv->next)
1745 serv->flags &= ~SERV_COUNTED;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001746
Simon Kelley824af852008-02-12 20:43:05 +00001747 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley28866e92011-02-14 20:19:14 +00001748 if (!(serv->flags &
1749 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley824af852008-02-12 20:43:05 +00001750 {
1751 int port;
1752 unsigned int queries = 0, failed_queries = 0;
1753 for (serv1 = serv; serv1; serv1 = serv1->next)
Simon Kelley28866e92011-02-14 20:19:14 +00001754 if (!(serv1->flags &
1755 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
1756 sockaddr_isequal(&serv->addr, &serv1->addr))
Simon Kelley824af852008-02-12 20:43:05 +00001757 {
1758 serv1->flags |= SERV_COUNTED;
1759 queries += serv1->queries;
1760 failed_queries += serv1->failed_queries;
1761 }
Simon Kelleyc72daea2012-01-05 21:33:27 +00001762 port = prettyprint_addr(&serv->addr, daemon->addrbuff);
1763 my_syslog(LOG_INFO, _("server %s#%d: queries sent %u, retried or failed %u"), daemon->addrbuff, port, queries, failed_queries);
Simon Kelley824af852008-02-12 20:43:05 +00001764 }
1765
Simon Kelley28866e92011-02-14 20:19:14 +00001766 if (option_bool(OPT_DEBUG) || option_bool(OPT_LOG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001767 {
1768 struct crec *cache ;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001769 int i;
Simon Kelleye7829ae2014-01-22 22:21:51 +00001770 my_syslog(LOG_INFO, "Host Address Flags Expires");
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001771
1772 for (i=0; i<hash_size; i++)
1773 for (cache = hash_table[i]; cache; cache = cache->hash_next)
1774 {
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001775 char *t = " ";
Simon Kelley0fc2f312014-01-08 10:26:58 +00001776 char *a = daemon->addrbuff, *p = daemon->namebuff, *n = cache_get_name(cache);
1777 *a = 0;
Simon Kelley2d33bda2014-01-24 22:37:25 +00001778 if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
Simon Kelley0fc2f312014-01-08 10:26:58 +00001779 n = "<Root>";
Simon Kelley394ff492015-03-29 22:17:14 +01001780 p += sprintf(p, "%-30.30s ", sanitise(n));
Simon Kelley0fc2f312014-01-08 10:26:58 +00001781 if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
Simon Kelley394ff492015-03-29 22:17:14 +01001782 a = sanitise(cache_get_cname_target(cache));
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001783#ifdef HAVE_DNSSEC
Simon Kelleycdbee9a2012-04-04 21:55:59 +01001784 else if (cache->flags & F_DS)
1785 {
Simon Kelley93be5b12015-12-15 12:04:40 +00001786 if (!(cache->flags & F_NEG))
Simon Kelleyb8eac192014-02-27 14:30:03 +00001787 sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
1788 cache->addr.ds.algo, cache->addr.ds.digest);
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001789 }
1790 else if (cache->flags & F_DNSKEY)
Simon Kelleyb8eac192014-02-27 14:30:03 +00001791 sprintf(a, "%5u %3u %3u", cache->addr.key.keytag,
1792 cache->addr.key.algo, cache->addr.key.flags);
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001793#endif
Simon Kelley0fc2f312014-01-08 10:26:58 +00001794 else if (!(cache->flags & F_NEG) || !(cache->flags & F_FORWARD))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001795 {
Simon Kelleyc72daea2012-01-05 21:33:27 +00001796 a = daemon->addrbuff;
Simon Kelleyf2621c72007-04-29 19:47:21 +01001797 if (cache->flags & F_IPV4)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001798 inet_ntop(AF_INET, &cache->addr.addr, a, ADDRSTRLEN);
Simon Kelleyf2621c72007-04-29 19:47:21 +01001799 else if (cache->flags & F_IPV6)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001800 inet_ntop(AF_INET6, &cache->addr.addr, a, ADDRSTRLEN);
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001801 }
1802
Simon Kelleye7829ae2014-01-22 22:21:51 +00001803 if (cache->flags & F_IPV4)
1804 t = "4";
1805 else if (cache->flags & F_IPV6)
1806 t = "6";
1807 else if (cache->flags & F_CNAME)
1808 t = "C";
1809#ifdef HAVE_DNSSEC
Simon Kelleye7829ae2014-01-22 22:21:51 +00001810 else if (cache->flags & F_DS)
1811 t = "S";
1812 else if (cache->flags & F_DNSKEY)
1813 t = "K";
1814#endif
Simon Kelley32678042014-12-17 20:38:20 +00001815 p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s ", a, t,
Simon Kelleyf2621c72007-04-29 19:47:21 +01001816 cache->flags & F_FORWARD ? "F" : " ",
1817 cache->flags & F_REVERSE ? "R" : " ",
1818 cache->flags & F_IMMORTAL ? "I" : " ",
1819 cache->flags & F_DHCP ? "D" : " ",
1820 cache->flags & F_NEG ? "N" : " ",
1821 cache->flags & F_NXDOMAIN ? "X" : " ",
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001822 cache->flags & F_HOSTS ? "H" : " ",
1823 cache->flags & F_DNSSECOK ? "V" : " ");
Simon Kelley44a2a312004-03-10 20:04:35 +00001824#ifdef HAVE_BROKEN_RTC
Simon Kelleyf2621c72007-04-29 19:47:21 +01001825 p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
Simon Kelley44a2a312004-03-10 20:04:35 +00001826#else
Simon Kelleyf2621c72007-04-29 19:47:21 +01001827 p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd)));
1828 /* ctime includes trailing \n - eat it */
1829 *(p-1) = 0;
Simon Kelley44a2a312004-03-10 20:04:35 +00001830#endif
Rosen Penevcbd29e52017-06-27 22:29:51 +01001831 my_syslog(LOG_INFO, "%s", daemon->namebuff);
Simon Kelleyf2621c72007-04-29 19:47:21 +01001832 }
1833 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001834}
1835
Simon Kelley19c51cf2014-03-18 22:38:30 +00001836char *record_source(unsigned int index)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001837{
Simon Kelley7622fc02009-06-04 20:32:05 +01001838 struct hostsfile *ah;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001839
Simon Kelley19c51cf2014-03-18 22:38:30 +00001840 if (index == SRC_CONFIG)
1841 return "config";
1842 else if (index == SRC_HOSTS)
Simon Kelley7622fc02009-06-04 20:32:05 +01001843 return HOSTSFILE;
1844
1845 for (ah = daemon->addn_hosts; ah; ah = ah->next)
1846 if (ah->index == index)
1847 return ah->fname;
Simon Kelley70d18732015-01-31 19:59:29 +00001848
1849#ifdef HAVE_INOTIFY
1850 for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
1851 if (ah->index == index)
1852 return ah->fname;
1853#endif
1854
Simon Kelley7622fc02009-06-04 20:32:05 +01001855 return "<unknown>";
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001856}
Simon Kelleyc1bb8502004-08-11 18:40:17 +01001857
Simon Kelley610e7822014-02-06 14:45:17 +00001858char *querystr(char *desc, unsigned short type)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001859{
1860 unsigned int i;
Simon Kelley610e7822014-02-06 14:45:17 +00001861 int len = 10; /* strlen("type=xxxxx") */
1862 const char *types = NULL;
1863 static char *buff = NULL;
1864 static int bufflen = 0;
1865
Simon Kelley1a6bca82008-07-11 11:11:42 +01001866 for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
1867 if (typestr[i].type == type)
Simon Kelley610e7822014-02-06 14:45:17 +00001868 {
1869 types = typestr[i].name;
1870 len = strlen(types);
1871 break;
1872 }
1873
Simon Kelleyb758b672018-08-23 21:41:23 +01001874 if (desc)
1875 {
1876 len += 2; /* braces */
1877 len += strlen(desc);
1878 }
1879 len++; /* terminator */
1880
Simon Kelley610e7822014-02-06 14:45:17 +00001881 if (!buff || bufflen < len)
1882 {
1883 if (buff)
1884 free(buff);
1885 else if (len < 20)
1886 len = 20;
1887
1888 buff = whine_malloc(len);
1889 bufflen = len;
1890 }
1891
1892 if (buff)
1893 {
Simon Kelleyb758b672018-08-23 21:41:23 +01001894 if (desc)
1895 {
1896 if (types)
1897 sprintf(buff, "%s[%s]", desc, types);
1898 else
1899 sprintf(buff, "%s[type=%d]", desc, type);
1900 }
Simon Kelley610e7822014-02-06 14:45:17 +00001901 else
Simon Kelleyb758b672018-08-23 21:41:23 +01001902 {
1903 if (types)
1904 sprintf(buff, "<%s>", types);
1905 else
1906 sprintf(buff, "type=%d", type);
1907 }
Simon Kelley610e7822014-02-06 14:45:17 +00001908 }
Simon Kelleyb758b672018-08-23 21:41:23 +01001909
Simon Kelley610e7822014-02-06 14:45:17 +00001910 return buff ? buff : "";
Simon Kelley1a6bca82008-07-11 11:11:42 +01001911}
1912
Simon Kelley28866e92011-02-14 20:19:14 +00001913void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001914{
Simon Kelleyc72daea2012-01-05 21:33:27 +00001915 char *source, *dest = daemon->addrbuff;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001916 char *verb = "is";
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001917
Simon Kelley28866e92011-02-14 20:19:14 +00001918 if (!option_bool(OPT_LOG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001919 return;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001920
Simon Kelley394ff492015-03-29 22:17:14 +01001921 name = sanitise(name);
1922
Simon Kelley5aabfc72007-08-29 11:24:47 +01001923 if (addr)
1924 {
Simon Kelley0fc2f312014-01-08 10:26:58 +00001925 if (flags & F_KEYTAG)
Simon Kelley15379ea2015-12-21 18:31:55 +00001926 sprintf(daemon->addrbuff, arg, addr->addr.log.keytag, addr->addr.log.algo, addr->addr.log.digest);
Simon Kelley07ed5852018-05-04 21:52:22 +01001927 else if (flags & F_RCODE)
1928 {
1929 unsigned int rcode = addr->addr.rcode.rcode;
1930
1931 if (rcode == SERVFAIL)
1932 dest = "SERVFAIL";
1933 else if (rcode == REFUSED)
1934 dest = "REFUSED";
1935 else if (rcode == NOTIMP)
1936 dest = "not implemented";
1937 else
1938 sprintf(daemon->addrbuff, "%u", rcode);
1939 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001940 else
Simon Kelleyee875042018-10-23 22:10:17 +01001941 inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
1942 addr, daemon->addrbuff, ADDRSTRLEN);
1943
Simon Kelley5aabfc72007-08-29 11:24:47 +01001944 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001945 else
1946 dest = arg;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001947
1948 if (flags & F_REVERSE)
1949 {
1950 dest = name;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001951 name = daemon->addrbuff;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001952 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001953
1954 if (flags & F_NEG)
1955 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001956 if (flags & F_NXDOMAIN)
Simon Kelley40b695c2014-02-03 17:07:51 +00001957 dest = "NXDOMAIN";
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001958 else
Simon Kelley5aabfc72007-08-29 11:24:47 +01001959 {
1960 if (flags & F_IPV4)
1961 dest = "NODATA-IPv4";
Simon Kelley824af852008-02-12 20:43:05 +00001962 else if (flags & F_IPV6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001963 dest = "NODATA-IPv6";
Simon Kelley824af852008-02-12 20:43:05 +00001964 else
1965 dest = "NODATA";
Simon Kelley5aabfc72007-08-29 11:24:47 +01001966 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001967 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001968 else if (flags & F_CNAME)
Simon Kelley28866e92011-02-14 20:19:14 +00001969 dest = "<CNAME>";
1970 else if (flags & F_RRNAME)
1971 dest = arg;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001972
Simon Kelley1f15b812009-10-13 17:49:32 +01001973 if (flags & F_CONFIG)
1974 source = "config";
1975 else if (flags & F_DHCP)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001976 source = "DHCP";
1977 else if (flags & F_HOSTS)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001978 source = arg;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001979 else if (flags & F_UPSTREAM)
1980 source = "reply";
Simon Kelley0fc2f312014-01-08 10:26:58 +00001981 else if (flags & F_SECSTAT)
1982 source = "validation";
Simon Kelley4f7b3042012-11-28 21:27:02 +00001983 else if (flags & F_AUTH)
1984 source = "auth";
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001985 else if (flags & F_SERVER)
1986 {
1987 source = "forwarded";
1988 verb = "to";
1989 }
1990 else if (flags & F_QUERY)
1991 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01001992 source = arg;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001993 verb = "from";
1994 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001995 else if (flags & F_DNSSEC)
1996 {
1997 source = arg;
1998 verb = "to";
1999 }
Wang Jian49752b92014-03-28 20:52:47 +00002000 else if (flags & F_IPSET)
2001 {
2002 source = "ipset add";
2003 dest = name;
2004 name = arg;
2005 verb = daemon->addrbuff;
2006 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002007 else
2008 source = "cached";
2009
Simon Kelley3d8df262005-08-29 12:19:27 +01002010 if (strlen(name) == 0)
2011 name = ".";
2012
Simon Kelley25cf5e32015-01-09 15:53:03 +00002013 if (option_bool(OPT_EXTRALOG))
2014 {
Simon Kelley9f79ee42015-01-12 20:18:18 +00002015 int port = prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2);
Simon Kelley25cf5e32015-01-09 15:53:03 +00002016 if (flags & F_NOEXTRA)
Simon Kelley9f79ee42015-01-12 20:18:18 +00002017 my_syslog(LOG_INFO, "* %s/%u %s %s %s %s", daemon->addrbuff2, port, source, name, verb, dest);
Simon Kelley25cf5e32015-01-09 15:53:03 +00002018 else
Simon Kelley9f79ee42015-01-12 20:18:18 +00002019 my_syslog(LOG_INFO, "%u %s/%u %s %s %s %s", daemon->log_display_id, daemon->addrbuff2, port, source, name, verb, dest);
Simon Kelley25cf5e32015-01-09 15:53:03 +00002020 }
2021 else
2022 my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002023}
2024
Simon Kelley98c098b2014-01-08 17:31:16 +00002025