blob: 39f6dbeb6a1a15da2d85a9a230cfc99b6b71e740 [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;
413#ifdef HAVE_IPV6
414 int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ;
415#else
416 int addrlen = INADDRSZ;
417#endif
418 for (i = 0; i < hash_size; i++)
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000419 for (crecp = hash_table[i], up = &hash_table[i];
420 crecp && ((crecp->flags & F_REVERSE) || !(crecp->flags & F_IMMORTAL));
421 crecp = crecp->hash_next)
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000422 if (is_expired(now, crecp))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000423 {
424 *up = crecp->hash_next;
Simon Kelley25439062013-11-25 21:14:51 +0000425 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000426 {
427 cache_unlink(crecp);
428 cache_free(crecp);
429 }
430 }
Simon Kelley25439062013-11-25 21:14:51 +0000431 else if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) &&
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000432 (flags & crecp->flags & F_REVERSE) &&
433 (flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
434 memcmp(&crecp->addr.addr, addr, addrlen) == 0)
435 {
436 *up = crecp->hash_next;
437 cache_unlink(crecp);
438 cache_free(crecp);
439 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000440 else
441 up = &crecp->hash_next;
442 }
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000443
Simon Kelleycbc65242014-12-21 21:21:53 +0000444 return NULL;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000445}
446
447/* Note: The normal calling sequence is
448 cache_start_insert
449 cache_insert * n
450 cache_end_insert
451
452 but an abort can cause the cache_end_insert to be missed
453 in which can the next cache_start_insert cleans things up. */
454
455void cache_start_insert(void)
456{
457 /* Free any entries which didn't get committed during the last
458 insert due to error.
459 */
460 while (new_chain)
461 {
462 struct crec *tmp = new_chain->next;
463 cache_free(new_chain);
464 new_chain = tmp;
465 }
466 new_chain = NULL;
467 insert_error = 0;
468}
Simon Kelleya799ca02018-10-18 19:35:29 +0100469
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100470struct crec *cache_insert(char *name, struct all_addr *addr,
471 time_t now, unsigned long ttl, unsigned short flags)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000472{
Simon Kelleya0ab18f2014-02-13 16:38:23 +0000473 /* Don't log DNSSEC records here, done elsewhere */
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000474 if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
Simon Kelleya0ab18f2014-02-13 16:38:23 +0000475 {
476 log_query(flags | F_UPSTREAM, name, addr, NULL);
RinSatsuki28de3872015-01-10 15:22:21 +0000477 /* Don't mess with TTL for DNSSEC records. */
Simon Kelleya0ab18f2014-02-13 16:38:23 +0000478 if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
479 ttl = daemon->max_cache_ttl;
RinSatsuki28de3872015-01-10 15:22:21 +0000480 if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl)
481 ttl = daemon->min_cache_ttl;
Simon Kelleya0ab18f2014-02-13 16:38:23 +0000482 }
Simon Kelleya799ca02018-10-18 19:35:29 +0100483
484 return really_insert(name, addr, now, ttl, flags);
485}
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000486
Simon Kelleya799ca02018-10-18 19:35:29 +0100487
488static struct crec *really_insert(char *name, struct all_addr *addr,
489 time_t now, unsigned long ttl, unsigned short flags)
490{
491 struct crec *new, *target_crec = NULL;
492 union bigname *big_name = NULL;
493 int freed_all = flags & F_REVERSE;
494 int free_avail = 0;
495 unsigned int target_uid;
496
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000497 /* if previous insertion failed give up now. */
498 if (insert_error)
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100499 return NULL;
Simon Kelley8d718cb2014-02-03 16:27:37 +0000500
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000501 /* First remove any expired entries and entries for the name/address we
Simon Kelleycbc65242014-12-21 21:21:53 +0000502 are currently inserting. */
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100503 if ((new = cache_scan_free(name, addr, now, flags, &target_crec, &target_uid)))
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000504 {
Simon Kelleycbc65242014-12-21 21:21:53 +0000505 /* We're trying to insert a record over one from
506 /etc/hosts or DHCP, or other config. If the
507 existing record is for an A or AAAA and
508 the record we're trying to insert is the same,
509 just drop the insert, but don't error the whole process. */
Edwin Török41a8d9e2015-11-14 17:45:48 +0000510 if ((flags & (F_IPV4 | F_IPV6)) && (flags & F_FORWARD) && addr)
Simon Kelleycbc65242014-12-21 21:21:53 +0000511 {
512 if ((flags & F_IPV4) && (new->flags & F_IPV4) &&
513 new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr)
514 return new;
515#ifdef HAVE_IPV6
516 else if ((flags & F_IPV6) && (new->flags & F_IPV6) &&
517 IN6_ARE_ADDR_EQUAL(&new->addr.addr.addr.addr6, &addr->addr.addr6))
518 return new;
519#endif
520 }
521
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000522 insert_error = 1;
523 return NULL;
524 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000525
526 /* Now get a cache entry from the end of the LRU list */
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100527 if (!target_crec)
528 while (1) {
529 if (!(new = cache_tail)) /* no entries left - cache is too small, bail */
530 {
531 insert_error = 1;
532 return NULL;
533 }
534
535 /* Free entry at end of LRU list, use it. */
536 if (!(new->flags & (F_FORWARD | F_REVERSE)))
537 break;
Simon Kelley8d718cb2014-02-03 16:27:37 +0000538
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100539 /* End of LRU list is still in use: if we didn't scan all the hash
540 chains for expired entries do that now. If we already tried that
541 then it's time to start spilling things. */
542
543 /* If free_avail set, we believe that an entry has been freed.
544 Bugs have been known to make this not true, resulting in
545 a tight loop here. If that happens, abandon the
546 insert. Once in this state, all inserts will probably fail. */
547 if (free_avail)
548 {
549 static int warned = 0;
550 if (!warned)
551 {
552 my_syslog(LOG_ERR, _("Internal error in cache."));
553 warned = 1;
554 }
555 insert_error = 1;
556 return NULL;
557 }
558
559 if (freed_all)
560 {
561 struct all_addr free_addr = new->addr.addr;;
562
Simon Kelley8d718cb2014-02-03 16:27:37 +0000563#ifdef HAVE_DNSSEC
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100564 /* For DNSSEC records, addr holds class. */
565 if (new->flags & (F_DS | F_DNSKEY))
566 free_addr.addr.dnssec.class = new->uid;
Simon Kelley8d718cb2014-02-03 16:27:37 +0000567#endif
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100568
569 free_avail = 1; /* Must be free space now. */
570 cache_scan_free(cache_get_name(new), &free_addr, now, new->flags, NULL, NULL);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +0100571 daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]++;
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100572 }
573 else
574 {
575 cache_scan_free(NULL, NULL, now, 0, NULL, NULL);
576 freed_all = 1;
577 }
578 }
579
580 /* Check if we need to and can allocate extra memory for a long name.
581 If that fails, give up now, always succeed for DNSSEC records. */
582 if (name && (strlen(name) > SMALLDNAME-1))
583 {
584 if (big_free)
585 {
586 big_name = big_free;
587 big_free = big_free->next;
588 }
589 else if ((bignames_left == 0 && !(flags & (F_DS | F_DNSKEY))) ||
590 !(big_name = (union bigname *)whine_malloc(sizeof(union bigname))))
591 {
592 insert_error = 1;
593 return NULL;
594 }
595 else if (bignames_left != 0)
596 bignames_left--;
597
598 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000599
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100600 /* If we freed a cache entry for our name which was a CNAME target, use that.
601 and preserve the uid, so that existing CNAMES are not broken. */
602 if (target_crec)
603 {
604 new = target_crec;
605 new->uid = target_uid;
606 }
607
608 /* Got the rest: finally grab entry. */
609 cache_unlink(new);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000610
611 new->flags = flags;
612 if (big_name)
613 {
614 new->name.bname = big_name;
615 new->flags |= F_BIGNAME;
616 }
Simon Kelley5aabfc72007-08-29 11:24:47 +0100617
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000618 if (name)
619 strcpy(cache_get_name(new), name);
620 else
621 *cache_get_name(new) = 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100622
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000623 if (addr)
Simon Kelleyb8eac192014-02-27 14:30:03 +0000624 {
625#ifdef HAVE_DNSSEC
626 if (flags & (F_DS | F_DNSKEY))
627 new->uid = addr->addr.dnssec.class;
628 else
629#endif
630 new->addr.addr = *addr;
631 }
Simon Kelley7b4ad2e2012-04-04 14:05:35 +0100632
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000633 new->ttd = now + (time_t)ttl;
634 new->next = new_chain;
635 new_chain = new;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100636
637 return new;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000638}
639
640/* after end of insertion, commit the new entries */
641void cache_end_insert(void)
642{
643 if (insert_error)
644 return;
645
646 while (new_chain)
647 {
648 struct crec *tmp = new_chain->next;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100649 /* drop CNAMEs which didn't find a target. */
650 if (is_outdated_cname_pointer(new_chain))
651 cache_free(new_chain);
652 else
653 {
654 cache_hash(new_chain);
655 cache_link(new_chain);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +0100656 daemon->metrics[METRIC_DNS_CACHE_INSERTED]++;
Simon Kelleya799ca02018-10-18 19:35:29 +0100657
658 /* If we're a child process, send this cache entry up the pipe to the master.
659 The marshalling process is rather nasty. */
660 if (daemon->pipe_to_parent != -1)
661 {
662 char *name = cache_get_name(new_chain);
663 ssize_t m = strlen(name);
664 unsigned short flags = new_chain->flags;
665#ifdef HAVE_DNSSEC
666 u16 class = new_chain->uid;
667#endif
668
669 read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), 0);
670 read_write(daemon->pipe_to_parent, (unsigned char *)name, m, 0);
671 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->ttd, sizeof(new_chain->ttd), 0);
672 read_write(daemon->pipe_to_parent, (unsigned char *)&flags, sizeof(flags), 0);
673
674 if (flags & (F_IPV4 | F_IPV6))
675 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), 0);
676#ifdef HAVE_DNSSEC
677 else if (flags & F_DNSKEY)
678 {
679 read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0);
680 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.algo, sizeof(new_chain->addr.key.algo), 0);
681 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.keytag, sizeof(new_chain->addr.key.keytag), 0);
682 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.flags, sizeof(new_chain->addr.key.flags), 0);
683 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.key.keylen, sizeof(new_chain->addr.key.keylen), 0);
684 blockdata_write(new_chain->addr.key.keydata, new_chain->addr.key.keylen, daemon->pipe_to_parent);
685 }
686 else if (flags & F_DS)
687 {
688 read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0);
689 /* A negative DS entry is possible and has no data, obviously. */
690 if (!(flags & F_NEG))
691 {
692 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.algo, sizeof(new_chain->addr.ds.algo), 0);
693 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.keytag, sizeof(new_chain->addr.ds.keytag), 0);
694 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.digest, sizeof(new_chain->addr.ds.digest), 0);
695 read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr.ds.keylen, sizeof(new_chain->addr.ds.keylen), 0);
696 blockdata_write(new_chain->addr.ds.keydata, new_chain->addr.ds.keylen, daemon->pipe_to_parent);
697 }
698 }
699#endif
700
701 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100702 }
Simon Kelleya799ca02018-10-18 19:35:29 +0100703
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000704 new_chain = tmp;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000705 }
Simon Kelleya799ca02018-10-18 19:35:29 +0100706
707 /* signal end of cache insert in master process */
708 if (daemon->pipe_to_parent != -1)
709 {
710 ssize_t m = -1;
711 read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), 0);
712 }
713
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000714 new_chain = NULL;
715}
716
Simon Kelleya799ca02018-10-18 19:35:29 +0100717
718/* A marshalled cache entry arrives on fd, read, unmarshall and insert into cache of master process. */
719int cache_recv_insert(time_t now, int fd)
720{
721 ssize_t m;
722 struct all_addr addr;
723 unsigned long ttl;
724 time_t ttd;
725 unsigned short flags;
726 struct crec *crecp = NULL;
727
728 cache_start_insert();
729
730 while(1)
731 {
732
733 if (!read_write(fd, (unsigned char *)&m, sizeof(m), 1))
734 return 0;
735
736 if (m == -1)
737 {
738 cache_end_insert();
739 return 1;
740 }
741
742 if (!read_write(fd, (unsigned char *)daemon->namebuff, m, 1) ||
743 !read_write(fd, (unsigned char *)&ttd, sizeof(ttd), 1) ||
744 !read_write(fd, (unsigned char *)&flags, sizeof(flags), 1))
745 return 0;
746
747 daemon->namebuff[m] = 0;
748
749 ttl = difftime(ttd, now);
750
751 if (flags & (F_IPV4 | F_IPV6))
752 {
753 if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
754 return 0;
755 crecp = really_insert(daemon->namebuff, &addr, now, ttl, flags);
756 }
757 else if (flags & F_CNAME)
758 {
759 struct crec *newc = really_insert(daemon->namebuff, NULL, now, ttl, flags);
760 /* This relies on the fact the the target of a CNAME immediately preceeds
761 it because of the order of extraction in extract_addresses, and
762 the order reversal on the new_chain. */
763 if (newc)
764 {
765 if (!crecp)
766 {
767 newc->addr.cname.target.cache = NULL;
768 /* anything other than zero, to avoid being mistaken for CNAME to interface-name */
769 newc->addr.cname.uid = 1;
770 }
771 else
772 {
773 next_uid(crecp);
774 newc->addr.cname.target.cache = crecp;
775 newc->addr.cname.uid = crecp->uid;
776 }
777 }
778 }
779#ifdef HAVE_DNSSEC
780 else if (flags & (F_DNSKEY | F_DS))
781 {
782 unsigned short class, keylen, keyflags, keytag;
783 unsigned char algo, digest;
784 struct blockdata *keydata;
785
786 if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1))
787 return 0;
788 /* Cache needs to known class for DNSSEC stuff */
789 addr.addr.dnssec.class = class;
790
791 crecp = really_insert(daemon->namebuff, &addr, now, ttl, flags);
792
793 if (flags & F_DNSKEY)
794 {
795 if (!read_write(fd, (unsigned char *)&algo, sizeof(algo), 1) ||
796 !read_write(fd, (unsigned char *)&keytag, sizeof(keytag), 1) ||
797 !read_write(fd, (unsigned char *)&keyflags, sizeof(keyflags), 1) ||
798 !read_write(fd, (unsigned char *)&keylen, sizeof(keylen), 1) ||
799 !(keydata = blockdata_read(fd, keylen)))
800 return 0;
801 }
802 else if (!(flags & F_NEG))
803 {
804 if (!read_write(fd, (unsigned char *)&algo, sizeof(algo), 1) ||
805 !read_write(fd, (unsigned char *)&keytag, sizeof(keytag), 1) ||
806 !read_write(fd, (unsigned char *)&digest, sizeof(digest), 1) ||
807 !read_write(fd, (unsigned char *)&keylen, sizeof(keylen), 1) ||
808 !(keydata = blockdata_read(fd, keylen)))
809 return 0;
810 }
811
812 if (crecp)
813 {
814 if (flags & F_DNSKEY)
815 {
816 crecp->addr.key.algo = algo;
817 crecp->addr.key.keytag = keytag;
818 crecp->addr.key.flags = flags;
819 crecp->addr.key.keylen = keylen;
820 crecp->addr.key.keydata = keydata;
821 }
822 else if (!(flags & F_NEG))
823 {
824 crecp->addr.ds.algo = algo;
825 crecp->addr.ds.keytag = keytag;
826 crecp->addr.ds.digest = digest;
827 crecp->addr.ds.keylen = keylen;
828 crecp->addr.ds.keydata = keydata;
829 }
830 }
831 }
832#endif
833 }
834}
835
Simon Kelleyb6f926f2018-08-21 17:46:52 +0100836int cache_find_non_terminal(char *name, time_t now)
837{
838 struct crec *crecp;
839
840 for (crecp = *hash_bucket(name); crecp; crecp = crecp->hash_next)
841 if (!is_outdated_cname_pointer(crecp) &&
842 !is_expired(now, crecp) &&
843 (crecp->flags & F_FORWARD) &&
844 hostname_isequal(name, cache_get_name(crecp)))
845 return 1;
846
847 return 0;
848}
849
Simon Kelley12fae492014-02-04 22:03:06 +0000850struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned int prot)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000851{
852 struct crec *ans;
Simon Kelley12fae492014-02-04 22:03:06 +0000853 int no_rr = prot & F_NO_RR;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000854
Simon Kelley12fae492014-02-04 22:03:06 +0000855 prot &= ~F_NO_RR;
856
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000857 if (crecp) /* iterating */
858 ans = crecp->next;
859 else
860 {
861 /* first search, look for relevant entries and push to top of list
862 also free anything which has expired */
863 struct crec *next, **up, **insert = NULL, **chainp = &ans;
Simon Kelley28866e92011-02-14 20:19:14 +0000864 unsigned short ins_flags = 0;
Simon Kelley824af852008-02-12 20:43:05 +0000865
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000866 for (up = hash_bucket(name), crecp = *up; crecp; crecp = next)
867 {
868 next = crecp->hash_next;
869
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000870 if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000871 {
872 if ((crecp->flags & F_FORWARD) &&
873 (crecp->flags & prot) &&
874 hostname_isequal(cache_get_name(crecp), name))
875 {
Simon Kelley25439062013-11-25 21:14:51 +0000876 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000877 {
878 *chainp = crecp;
879 chainp = &crecp->next;
880 }
881 else
882 {
883 cache_unlink(crecp);
884 cache_link(crecp);
885 }
886
Simon Kelley824af852008-02-12 20:43:05 +0000887 /* Move all but the first entry up the hash chain
888 this implements round-robin.
889 Make sure that re-ordering doesn't break the hash-chain
890 order invariants.
891 */
Simon Kelley9e038942008-05-30 20:06:34 +0100892 if (insert && (crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000893 {
894 *up = crecp->hash_next;
895 crecp->hash_next = *insert;
896 *insert = crecp;
897 insert = &crecp->hash_next;
898 }
Simon Kelley9e038942008-05-30 20:06:34 +0100899 else
900 {
Simon Kelley12fae492014-02-04 22:03:06 +0000901 if (!insert && !no_rr)
Simon Kelley9e038942008-05-30 20:06:34 +0100902 {
903 insert = up;
904 ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
905 }
906 up = &crecp->hash_next;
907 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000908 }
909 else
910 /* case : not expired, incorrect entry. */
911 up = &crecp->hash_next;
912 }
913 else
914 {
915 /* expired entry, free it */
916 *up = crecp->hash_next;
Simon Kelley25439062013-11-25 21:14:51 +0000917 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000918 {
919 cache_unlink(crecp);
920 cache_free(crecp);
921 }
922 }
923 }
924
925 *chainp = cache_head;
926 }
927
928 if (ans &&
929 (ans->flags & F_FORWARD) &&
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000930 (ans->flags & prot) &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000931 hostname_isequal(cache_get_name(ans), name))
932 return ans;
933
934 return NULL;
935}
936
937struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
Simon Kelley12fae492014-02-04 22:03:06 +0000938 time_t now, unsigned int prot)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000939{
940 struct crec *ans;
941#ifdef HAVE_IPV6
942 int addrlen = (prot == F_IPV6) ? IN6ADDRSZ : INADDRSZ;
943#else
944 int addrlen = INADDRSZ;
945#endif
946
947 if (crecp) /* iterating */
948 ans = crecp->next;
949 else
950 {
951 /* first search, look for relevant entries and push to top of list
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000952 also free anything which has expired. All the reverse entries are at the
953 start of the hash chain, so we can give up when we find the first
954 non-REVERSE one. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000955 int i;
956 struct crec **up, **chainp = &ans;
957
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000958 for (i=0; i<hash_size; i++)
959 for (crecp = hash_table[i], up = &hash_table[i];
960 crecp && (crecp->flags & F_REVERSE);
961 crecp = crecp->hash_next)
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000962 if (!is_expired(now, crecp))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000963 {
Simon Kelley6b010842007-02-12 20:32:07 +0000964 if ((crecp->flags & prot) &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100965 memcmp(&crecp->addr.addr, addr, addrlen) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000966 {
Simon Kelley25439062013-11-25 21:14:51 +0000967 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000968 {
969 *chainp = crecp;
970 chainp = &crecp->next;
971 }
972 else
973 {
974 cache_unlink(crecp);
975 cache_link(crecp);
976 }
977 }
978 up = &crecp->hash_next;
979 }
980 else
981 {
982 *up = crecp->hash_next;
Simon Kelley25439062013-11-25 21:14:51 +0000983 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000984 {
985 cache_unlink(crecp);
986 cache_free(crecp);
987 }
988 }
989
990 *chainp = cache_head;
991 }
992
993 if (ans &&
994 (ans->flags & F_REVERSE) &&
995 (ans->flags & prot) &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100996 memcmp(&ans->addr.addr, addr, addrlen) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000997 return ans;
998
999 return NULL;
1000}
1001
Simon Kelley611ebc52012-07-16 16:23:46 +01001002static void add_hosts_cname(struct crec *target)
1003{
1004 struct crec *crec;
1005 struct cname *a;
1006
1007 for (a = daemon->cnames; a; a = a->next)
Simon Kelleyb637d782016-12-13 16:44:11 +00001008 if (a->alias[1] != '*' &&
1009 hostname_isequal(cache_get_name(target), a->target) &&
Simon Kelley3a610a02018-09-26 16:50:35 +01001010 (crec = whine_malloc(SIZEOF_POINTER_CREC)))
Simon Kelley611ebc52012-07-16 16:23:46 +01001011 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001012 crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001013 crec->ttd = a->ttl;
Simon Kelley611ebc52012-07-16 16:23:46 +01001014 crec->name.namep = a->alias;
Simon Kelleyd56a6042013-10-11 14:39:03 +01001015 crec->addr.cname.target.cache = target;
Simon Kelley45d8a242018-07-17 21:01:14 +01001016 next_uid(target);
Simon Kelley611ebc52012-07-16 16:23:46 +01001017 crec->addr.cname.uid = target->uid;
Simon Kelley45d8a242018-07-17 21:01:14 +01001018 crec->uid = UID_NONE;
Simon Kelley611ebc52012-07-16 16:23:46 +01001019 cache_hash(crec);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001020 make_non_terminals(crec);
1021
Simon Kelley611ebc52012-07-16 16:23:46 +01001022 add_hosts_cname(crec); /* handle chains */
1023 }
1024}
1025
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001026static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
Simon Kelley19c51cf2014-03-18 22:38:30 +00001027 unsigned int index, struct crec **rhash, int hashsz)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001028{
Simon Kelleye759d422012-03-16 13:18:57 +00001029 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 +00001030 int i, nameexists = 0;
Simon Kelley205fafa2012-01-11 21:31:51 +00001031 unsigned int j;
Simon Kelley9009d742008-11-14 20:04:27 +00001032
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001033 /* Remove duplicates in hosts files. */
Simon Kelley9009d742008-11-14 20:04:27 +00001034 if (lookup && (lookup->flags & F_HOSTS))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001035 {
Simon Kelley9009d742008-11-14 20:04:27 +00001036 nameexists = 1;
1037 if (memcmp(&lookup->addr.addr, addr, addrlen) == 0)
1038 {
1039 free(cache);
1040 return;
1041 }
1042 }
1043
1044 /* Ensure there is only one address -> name mapping (first one trumps)
Simon Kelley205fafa2012-01-11 21:31:51 +00001045 We do this by steam here, The entries are kept in hash chains, linked
1046 by ->next (which is unused at this point) held in hash buckets in
Simon Kelley1ab62ae2012-01-12 11:33:16 +00001047 the array rhash, hashed on address. Note that rhash and the values
1048 in ->next are only valid whilst reading hosts files: the buckets are
1049 then freed, and the ->next pointer used for other things.
Simon Kelley205fafa2012-01-11 21:31:51 +00001050
Simon Kelley1ab62ae2012-01-12 11:33:16 +00001051 Only insert each unique address once into this hashing structure.
Simon Kelley205fafa2012-01-11 21:31:51 +00001052
1053 This complexity avoids O(n^2) divergent CPU use whilst reading
Simon Kelley70d18732015-01-31 19:59:29 +00001054 large (10000 entry) hosts files.
1055
1056 Note that we only do this process when bulk-reading hosts files,
1057 for incremental reads, rhash is NULL, and we use cache lookups
1058 instead.
1059 */
Simon Kelley9009d742008-11-14 20:04:27 +00001060
Simon Kelley70d18732015-01-31 19:59:29 +00001061 if (rhash)
Simon Kelley915363f2012-01-11 22:00:48 +00001062 {
Simon Kelley70d18732015-01-31 19:59:29 +00001063 /* hash address */
1064 for (j = 0, i = 0; i < addrlen; i++)
1065 j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
1066
1067 for (lookup = rhash[j]; lookup; lookup = lookup->next)
1068 if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) &&
1069 memcmp(&lookup->addr.addr, addr, addrlen) == 0)
1070 {
1071 cache->flags &= ~F_REVERSE;
1072 break;
1073 }
1074
1075 /* maintain address hash chain, insert new unique address */
1076 if (!lookup)
1077 {
1078 cache->next = rhash[j];
1079 rhash[j] = cache;
1080 }
Simon Kelley915363f2012-01-11 22:00:48 +00001081 }
Simon Kelley70d18732015-01-31 19:59:29 +00001082 else
1083 {
1084 /* incremental read, lookup in cache */
1085 lookup = cache_find_by_addr(NULL, addr, 0, cache->flags & (F_IPV4 | F_IPV6));
1086 if (lookup && lookup->flags & F_HOSTS)
1087 cache->flags &= ~F_REVERSE;
1088 }
1089
Simon Kelley9009d742008-11-14 20:04:27 +00001090 cache->uid = index;
Simon Kelley915363f2012-01-11 22:00:48 +00001091 memcpy(&cache->addr.addr, addr, addrlen);
Simon Kelley9009d742008-11-14 20:04:27 +00001092 cache_hash(cache);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001093 make_non_terminals(cache);
Simon Kelley9009d742008-11-14 20:04:27 +00001094
1095 /* don't need to do alias stuff for second and subsequent addresses. */
1096 if (!nameexists)
Simon Kelley611ebc52012-07-16 16:23:46 +01001097 add_hosts_cname(cache);
Simon Kelley9009d742008-11-14 20:04:27 +00001098}
1099
1100static int eatspace(FILE *f)
1101{
1102 int c, nl = 0;
1103
1104 while (1)
1105 {
1106 if ((c = getc(f)) == '#')
1107 while (c != '\n' && c != EOF)
1108 c = getc(f);
Simon Kelley832af0b2007-01-21 20:01:28 +00001109
Simon Kelley9009d742008-11-14 20:04:27 +00001110 if (c == EOF)
1111 return 1;
1112
1113 if (!isspace(c))
1114 {
1115 ungetc(c, f);
1116 return nl;
1117 }
1118
1119 if (c == '\n')
1120 nl = 1;
1121 }
1122}
1123
1124static int gettok(FILE *f, char *token)
1125{
1126 int c, count = 0;
1127
1128 while (1)
1129 {
1130 if ((c = getc(f)) == EOF)
1131 return (count == 0) ? EOF : 1;
1132
1133 if (isspace(c) || c == '#')
1134 {
1135 ungetc(c, f);
1136 return eatspace(f);
1137 }
1138
1139 if (count < (MAXDNAME - 1))
1140 {
1141 token[count++] = c;
1142 token[count] = 0;
1143 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001144 }
1145}
1146
Simon Kelley70d18732015-01-31 19:59:29 +00001147int read_hostsfile(char *filename, unsigned int index, int cache_size, struct crec **rhash, int hashsz)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001148{
1149 FILE *f = fopen(filename, "r");
Simon Kelley9009d742008-11-14 20:04:27 +00001150 char *token = daemon->namebuff, *domain_suffix = NULL;
Simon Kelley4011c4e2006-10-28 16:26:19 +01001151 int addr_count = 0, name_count = cache_size, lineno = 0;
Simon Kelley205fafa2012-01-11 21:31:51 +00001152 unsigned short flags = 0;
1153 struct all_addr addr;
1154 int atnl, addrlen = 0;
Simon Kelley4011c4e2006-10-28 16:26:19 +01001155
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001156 if (!f)
1157 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001158 my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
André Glüpkereddf3652016-01-12 12:54:17 +00001159 return cache_size;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001160 }
Simon Kelley9009d742008-11-14 20:04:27 +00001161
1162 eatspace(f);
1163
1164 while ((atnl = gettok(f, token)) != EOF)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001165 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001166 lineno++;
Simon Kelley9009d742008-11-14 20:04:27 +00001167
Simon Kelley3d8df262005-08-29 12:19:27 +01001168 if (inet_pton(AF_INET, token, &addr) > 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001169 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001170 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001171 addrlen = INADDRSZ;
Simon Kelley9009d742008-11-14 20:04:27 +00001172 domain_suffix = get_domain(addr.addr.addr4);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001173 }
Simon Kelleye759d422012-03-16 13:18:57 +00001174#ifdef HAVE_IPV6
Simon Kelley3d8df262005-08-29 12:19:27 +01001175 else if (inet_pton(AF_INET6, token, &addr) > 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001176 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001177 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001178 addrlen = IN6ADDRSZ;
Simon Kelley4cb1b322012-02-06 14:30:41 +00001179 domain_suffix = get_domain6(&addr.addr.addr6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001180 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001181#endif
1182 else
Simon Kelleyb8187c82005-11-26 21:46:27 +00001183 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001184 my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
Simon Kelley9009d742008-11-14 20:04:27 +00001185 while (atnl == 0)
1186 atnl = gettok(f, token);
Simon Kelleyb8187c82005-11-26 21:46:27 +00001187 continue;
1188 }
Simon Kelley9009d742008-11-14 20:04:27 +00001189
Simon Kelley9009d742008-11-14 20:04:27 +00001190 addr_count++;
1191
1192 /* rehash every 1000 names. */
Simon Kelley70d18732015-01-31 19:59:29 +00001193 if (rhash && ((name_count - cache_size) > 1000))
Simon Kelley9009d742008-11-14 20:04:27 +00001194 {
1195 rehash(name_count);
1196 cache_size = name_count;
1197 }
1198
1199 while (atnl == 0)
1200 {
1201 struct crec *cache;
Simon Kelley1f15b812009-10-13 17:49:32 +01001202 int fqdn, nomem;
1203 char *canon;
Simon Kelley9009d742008-11-14 20:04:27 +00001204
1205 if ((atnl = gettok(f, token)) == EOF)
1206 break;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001207
Simon Kelley9009d742008-11-14 20:04:27 +00001208 fqdn = !!strchr(token, '.');
1209
Simon Kelley1f15b812009-10-13 17:49:32 +01001210 if ((canon = canonicalise(token, &nomem)))
Simon Kelley9009d742008-11-14 20:04:27 +00001211 {
1212 /* If set, add a version of the name with a default domain appended */
Simon Kelley28866e92011-02-14 20:19:14 +00001213 if (option_bool(OPT_EXPAND) && domain_suffix && !fqdn &&
Simon Kelley3a610a02018-09-26 16:50:35 +01001214 (cache = whine_malloc(SIZEOF_BARE_CREC + strlen(canon) + 2 + strlen(domain_suffix))))
Simon Kelley9009d742008-11-14 20:04:27 +00001215 {
Simon Kelley1f15b812009-10-13 17:49:32 +01001216 strcpy(cache->name.sname, canon);
Simon Kelley9009d742008-11-14 20:04:27 +00001217 strcat(cache->name.sname, ".");
1218 strcat(cache->name.sname, domain_suffix);
Simon Kelleye759d422012-03-16 13:18:57 +00001219 cache->flags = flags;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001220 cache->ttd = daemon->local_ttl;
Simon Kelleye759d422012-03-16 13:18:57 +00001221 add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
Simon Kelley9009d742008-11-14 20:04:27 +00001222 name_count++;
1223 }
Simon Kelley3a610a02018-09-26 16:50:35 +01001224 if ((cache = whine_malloc(SIZEOF_BARE_CREC + strlen(canon) + 1)))
Simon Kelley9009d742008-11-14 20:04:27 +00001225 {
Simon Kelley1f15b812009-10-13 17:49:32 +01001226 strcpy(cache->name.sname, canon);
Simon Kelleye759d422012-03-16 13:18:57 +00001227 cache->flags = flags;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001228 cache->ttd = daemon->local_ttl;
Simon Kelleye759d422012-03-16 13:18:57 +00001229 add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
Simon Kelley9009d742008-11-14 20:04:27 +00001230 name_count++;
1231 }
Simon Kelley1f15b812009-10-13 17:49:32 +01001232 free(canon);
1233
Simon Kelley9009d742008-11-14 20:04:27 +00001234 }
Simon Kelley1f15b812009-10-13 17:49:32 +01001235 else if (!nomem)
Simon Kelley9009d742008-11-14 20:04:27 +00001236 my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
1237 }
1238 }
1239
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001240 fclose(f);
Simon Kelley9009d742008-11-14 20:04:27 +00001241
Simon Kelley70d18732015-01-31 19:59:29 +00001242 if (rhash)
Simon Kelleyf9c86372015-02-03 21:52:48 +00001243 rehash(name_count);
1244
1245 my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
1246
Simon Kelley4011c4e2006-10-28 16:26:19 +01001247 return name_count;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001248}
1249
Simon Kelley7622fc02009-06-04 20:32:05 +01001250void cache_reload(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001251{
1252 struct crec *cache, **up, *tmp;
Simon Kelley1ab62ae2012-01-12 11:33:16 +00001253 int revhashsz, i, total_size = daemon->cachesize;
Simon Kelley7622fc02009-06-04 20:32:05 +01001254 struct hostsfile *ah;
Simon Kelleye759d422012-03-16 13:18:57 +00001255 struct host_record *hr;
1256 struct name_list *nl;
Simon Kelleyd56a6042013-10-11 14:39:03 +01001257 struct cname *a;
1258 struct interface_name *intr;
Simon Kelley0fc2f312014-01-08 10:26:58 +00001259#ifdef HAVE_DNSSEC
Simon Kelleyee415862014-02-11 11:07:22 +00001260 struct ds_config *ds;
Simon Kelley0fc2f312014-01-08 10:26:58 +00001261#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001262
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001263 daemon->metrics[METRIC_DNS_CACHE_INSERTED] = 0;
1264 daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED] = 0;
Simon Kelley59353a62004-11-21 19:34:28 +00001265
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001266 for (i=0; i<hash_size; i++)
1267 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
1268 {
Simon Kelley0fc2f312014-01-08 10:26:58 +00001269#ifdef HAVE_DNSSEC
Simon Kelley82e3f452014-01-31 21:05:48 +00001270 cache_blockdata_free(cache);
Simon Kelley0fc2f312014-01-08 10:26:58 +00001271#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001272 tmp = cache->hash_next;
Simon Kelley25439062013-11-25 21:14:51 +00001273 if (cache->flags & (F_HOSTS | F_CONFIG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001274 {
1275 *up = cache->hash_next;
1276 free(cache);
1277 }
1278 else if (!(cache->flags & F_DHCP))
1279 {
1280 *up = cache->hash_next;
1281 if (cache->flags & F_BIGNAME)
1282 {
1283 cache->name.bname->next = big_free;
1284 big_free = cache->name.bname;
1285 }
1286 cache->flags = 0;
1287 }
1288 else
1289 up = &cache->hash_next;
1290 }
1291
Simon Kelleyd56a6042013-10-11 14:39:03 +01001292 /* Add CNAMEs to interface_names to the cache */
1293 for (a = daemon->cnames; a; a = a->next)
1294 for (intr = daemon->int_names; intr; intr = intr->next)
Simon Kelleyb637d782016-12-13 16:44:11 +00001295 if (a->alias[1] != '*' &&
1296 hostname_isequal(a->target, intr->name) &&
Simon Kelley3a610a02018-09-26 16:50:35 +01001297 ((cache = whine_malloc(SIZEOF_POINTER_CREC))))
Simon Kelleyd56a6042013-10-11 14:39:03 +01001298 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001299 cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001300 cache->ttd = a->ttl;
Simon Kelley532066e2013-11-26 10:14:47 +00001301 cache->name.namep = a->alias;
1302 cache->addr.cname.target.int_name = intr;
Simon Kelley19c51cf2014-03-18 22:38:30 +00001303 cache->addr.cname.uid = SRC_INTERFACE;
Simon Kelley45d8a242018-07-17 21:01:14 +01001304 cache->uid = UID_NONE;
Simon Kelley532066e2013-11-26 10:14:47 +00001305 cache_hash(cache);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001306 make_non_terminals(cache);
Simon Kelley532066e2013-11-26 10:14:47 +00001307 add_hosts_cname(cache); /* handle chains */
Simon Kelleyd56a6042013-10-11 14:39:03 +01001308 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001309
1310#ifdef HAVE_DNSSEC
Simon Kelleyee415862014-02-11 11:07:22 +00001311 for (ds = daemon->ds; ds; ds = ds->next)
Simon Kelley3a610a02018-09-26 16:50:35 +01001312 if ((cache = whine_malloc(SIZEOF_POINTER_CREC)) &&
Simon Kelleyee415862014-02-11 11:07:22 +00001313 (cache->addr.ds.keydata = blockdata_alloc(ds->digest, ds->digestlen)))
Simon Kelley0fc2f312014-01-08 10:26:58 +00001314 {
Simon Kelleyee415862014-02-11 11:07:22 +00001315 cache->flags = F_FORWARD | F_IMMORTAL | F_DS | F_CONFIG | F_NAMEP;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001316 cache->ttd = daemon->local_ttl;
Simon Kelleyee415862014-02-11 11:07:22 +00001317 cache->name.namep = ds->name;
1318 cache->addr.ds.keylen = ds->digestlen;
1319 cache->addr.ds.algo = ds->algo;
1320 cache->addr.ds.keytag = ds->keytag;
1321 cache->addr.ds.digest = ds->digest_type;
1322 cache->uid = ds->class;
Simon Kelley0fc2f312014-01-08 10:26:58 +00001323 cache_hash(cache);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001324 make_non_terminals(cache);
Simon Kelley0fc2f312014-01-08 10:26:58 +00001325 }
1326#endif
Simon Kelleyd56a6042013-10-11 14:39:03 +01001327
Simon Kelleye759d422012-03-16 13:18:57 +00001328 /* borrow the packet buffer for a temporary by-address hash */
1329 memset(daemon->packet, 0, daemon->packet_buff_sz);
1330 revhashsz = daemon->packet_buff_sz / sizeof(struct crec *);
1331 /* we overwrote the buffer... */
1332 daemon->srv_save = NULL;
1333
1334 /* Do host_records in config. */
1335 for (hr = daemon->host_records; hr; hr = hr->next)
1336 for (nl = hr->names; nl; nl = nl->next)
1337 {
1338 if (hr->addr.s_addr != 0 &&
Simon Kelley3a610a02018-09-26 16:50:35 +01001339 (cache = whine_malloc(SIZEOF_POINTER_CREC)))
Simon Kelleye759d422012-03-16 13:18:57 +00001340 {
1341 cache->name.namep = nl->name;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001342 cache->ttd = hr->ttl;
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001343 cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG;
Simon Kelley19c51cf2014-03-18 22:38:30 +00001344 add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
Simon Kelleye759d422012-03-16 13:18:57 +00001345 }
1346#ifdef HAVE_IPV6
1347 if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) &&
Simon Kelley3a610a02018-09-26 16:50:35 +01001348 (cache = whine_malloc(SIZEOF_POINTER_CREC)))
Simon Kelleye759d422012-03-16 13:18:57 +00001349 {
1350 cache->name.namep = nl->name;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001351 cache->ttd = hr->ttl;
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001352 cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG;
Simon Kelley19c51cf2014-03-18 22:38:30 +00001353 add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
Simon Kelleye759d422012-03-16 13:18:57 +00001354 }
1355#endif
1356 }
1357
Simon Kelley28866e92011-02-14 20:19:14 +00001358 if (option_bool(OPT_NO_HOSTS) && !daemon->addn_hosts)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001359 {
Simon Kelley5aabfc72007-08-29 11:24:47 +01001360 if (daemon->cachesize > 0)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001361 my_syslog(LOG_INFO, _("cleared cache"));
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001362 }
Simon Kelleycaeea192015-02-14 20:08:56 +00001363 else
1364 {
1365 if (!option_bool(OPT_NO_HOSTS))
1366 total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
1367
1368 daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
1369 for (ah = daemon->addn_hosts; ah; ah = ah->next)
1370 if (!(ah->flags & AH_INACTIVE))
1371 total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
1372 }
1373
Simon Kelley70d18732015-01-31 19:59:29 +00001374#ifdef HAVE_INOTIFY
1375 set_dynamic_inotify(AH_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
1376#endif
1377
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001378}
1379
Simon Kelley7622fc02009-06-04 20:32:05 +01001380#ifdef HAVE_DHCP
Simon Kelley7de060b2011-08-26 17:24:52 +01001381struct in_addr a_record_from_hosts(char *name, time_t now)
1382{
1383 struct crec *crecp = NULL;
1384 struct in_addr ret;
1385
1386 while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
1387 if (crecp->flags & F_HOSTS)
1388 return *(struct in_addr *)&crecp->addr;
1389
1390 my_syslog(MS_DHCP | LOG_WARNING, _("No IPv4 address found for %s"), name);
1391
1392 ret.s_addr = 0;
1393 return ret;
1394}
1395
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001396void cache_unhash_dhcp(void)
1397{
Simon Kelley6b010842007-02-12 20:32:07 +00001398 struct crec *cache, **up;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001399 int i;
1400
1401 for (i=0; i<hash_size; i++)
1402 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next)
1403 if (cache->flags & F_DHCP)
Simon Kelley6b010842007-02-12 20:32:07 +00001404 {
1405 *up = cache->hash_next;
1406 cache->next = dhcp_spare;
1407 dhcp_spare = cache;
1408 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001409 else
1410 up = &cache->hash_next;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001411}
1412
Simon Kelley611ebc52012-07-16 16:23:46 +01001413static void add_dhcp_cname(struct crec *target, time_t ttd)
1414{
1415 struct crec *aliasc;
1416 struct cname *a;
1417
1418 for (a = daemon->cnames; a; a = a->next)
Simon Kelleyb637d782016-12-13 16:44:11 +00001419 if (a->alias[1] != '*' &&
1420 hostname_isequal(cache_get_name(target), a->target))
Simon Kelley611ebc52012-07-16 16:23:46 +01001421 {
1422 if ((aliasc = dhcp_spare))
1423 dhcp_spare = dhcp_spare->next;
1424 else /* need new one */
Simon Kelley3a610a02018-09-26 16:50:35 +01001425 aliasc = whine_malloc(SIZEOF_POINTER_CREC);
Simon Kelley611ebc52012-07-16 16:23:46 +01001426
1427 if (aliasc)
1428 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001429 aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME | F_CONFIG;
Simon Kelley611ebc52012-07-16 16:23:46 +01001430 if (ttd == 0)
1431 aliasc->flags |= F_IMMORTAL;
1432 else
1433 aliasc->ttd = ttd;
1434 aliasc->name.namep = a->alias;
Simon Kelleyd56a6042013-10-11 14:39:03 +01001435 aliasc->addr.cname.target.cache = target;
Simon Kelley45d8a242018-07-17 21:01:14 +01001436 next_uid(target);
Simon Kelley611ebc52012-07-16 16:23:46 +01001437 aliasc->addr.cname.uid = target->uid;
Simon Kelley45d8a242018-07-17 21:01:14 +01001438 aliasc->uid = UID_NONE;
Simon Kelley611ebc52012-07-16 16:23:46 +01001439 cache_hash(aliasc);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001440 make_non_terminals(aliasc);
Simon Kelley611ebc52012-07-16 16:23:46 +01001441 add_dhcp_cname(aliasc, ttd);
1442 }
1443 }
1444}
1445
Simon Kelley4cb1b322012-02-06 14:30:41 +00001446void cache_add_dhcp_entry(char *host_name, int prot,
1447 struct all_addr *host_address, time_t ttd)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001448{
Simon Kelley12d71ed2012-08-30 15:16:41 +01001449 struct crec *crec = NULL, *fail_crec = NULL;
Simon Kelley4cb1b322012-02-06 14:30:41 +00001450 unsigned short flags = F_IPV4;
Simon Kelley824af852008-02-12 20:43:05 +00001451 int in_hosts = 0;
Simon Kelley4cb1b322012-02-06 14:30:41 +00001452 size_t addrlen = sizeof(struct in_addr);
1453
1454#ifdef HAVE_IPV6
1455 if (prot == AF_INET6)
1456 {
1457 flags = F_IPV6;
1458 addrlen = sizeof(struct in6_addr);
1459 }
1460#endif
Simon Kelley9009d742008-11-14 20:04:27 +00001461
Simon Kelley12d71ed2012-08-30 15:16:41 +01001462 inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN);
1463
Simon Kelley4cb1b322012-02-06 14:30:41 +00001464 while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001465 {
Simon Kelley824af852008-02-12 20:43:05 +00001466 /* check all addresses associated with name */
Simon Kelley25439062013-11-25 21:14:51 +00001467 if (crec->flags & (F_HOSTS | F_CONFIG))
Simon Kelley1ab84e22004-01-29 16:48:35 +00001468 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001469 if (crec->flags & F_CNAME)
Simon Kelley28866e92011-02-14 20:19:14 +00001470 my_syslog(MS_DHCP | LOG_WARNING,
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001471 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
Simon Kelley4cb1b322012-02-06 14:30:41 +00001472 host_name, daemon->addrbuff);
Simon Kelley12d71ed2012-08-30 15:16:41 +01001473 else if (memcmp(&crec->addr.addr, host_address, addrlen) == 0)
1474 in_hosts = 1;
1475 else
1476 fail_crec = crec;
Simon Kelley1ab84e22004-01-29 16:48:35 +00001477 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001478 else if (!(crec->flags & F_DHCP))
Simon Kelley824af852008-02-12 20:43:05 +00001479 {
Simon Kelleyeb1fe152018-07-18 20:59:52 +01001480 cache_scan_free(host_name, NULL, 0, crec->flags & (flags | F_CNAME | F_FORWARD), NULL, NULL);
Simon Kelley824af852008-02-12 20:43:05 +00001481 /* scan_free deletes all addresses associated with name */
1482 break;
1483 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001484 }
Simon Kelley824af852008-02-12 20:43:05 +00001485
Simon Kelley12d71ed2012-08-30 15:16:41 +01001486 /* if in hosts, don't need DHCP record */
1487 if (in_hosts)
Simon Kelley824af852008-02-12 20:43:05 +00001488 return;
Simon Kelley12d71ed2012-08-30 15:16:41 +01001489
1490 /* Name in hosts, address doesn't match */
1491 if (fail_crec)
1492 {
1493 inet_ntop(prot, &fail_crec->addr.addr, daemon->namebuff, MAXDNAME);
1494 my_syslog(MS_DHCP | LOG_WARNING,
1495 _("not giving name %s to the DHCP lease of %s because "
1496 "the name exists in %s with address %s"),
1497 host_name, daemon->addrbuff,
1498 record_source(fail_crec->uid), daemon->namebuff);
1499 return;
1500 }
1501
1502 if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, flags)))
1503 {
1504 if (crec->flags & F_NEG)
1505 {
1506 flags |= F_REVERSE;
Simon Kelleyeb1fe152018-07-18 20:59:52 +01001507 cache_scan_free(NULL, (struct all_addr *)host_address, 0, flags, NULL, NULL);
Simon Kelley12d71ed2012-08-30 15:16:41 +01001508 }
1509 }
1510 else
1511 flags |= F_REVERSE;
1512
1513 if ((crec = dhcp_spare))
Simon Kelley6b010842007-02-12 20:32:07 +00001514 dhcp_spare = dhcp_spare->next;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001515 else /* need new one */
Simon Kelley3a610a02018-09-26 16:50:35 +01001516 crec = whine_malloc(SIZEOF_POINTER_CREC);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001517
1518 if (crec) /* malloc may fail */
1519 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001520 crec->flags = flags | F_NAMEP | F_DHCP | F_FORWARD;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001521 if (ttd == 0)
1522 crec->flags |= F_IMMORTAL;
1523 else
1524 crec->ttd = ttd;
Simon Kelley4cb1b322012-02-06 14:30:41 +00001525 crec->addr.addr = *host_address;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001526 crec->name.namep = host_name;
Simon Kelley45d8a242018-07-17 21:01:14 +01001527 crec->uid = UID_NONE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001528 cache_hash(crec);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001529 make_non_terminals(crec);
Simon Kelley9009d742008-11-14 20:04:27 +00001530
Simon Kelley611ebc52012-07-16 16:23:46 +01001531 add_dhcp_cname(crec, ttd);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001532 }
1533}
Simon Kelley7622fc02009-06-04 20:32:05 +01001534#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001535
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001536/* Called when we put a local or DHCP name into the cache.
1537 Creates empty cache entries for subnames (ie,
1538 for three.two.one, for two.one and one), without
1539 F_IPV4 or F_IPV6 or F_CNAME set. These convert
1540 NXDOMAIN answers to NoData ones. */
1541static void make_non_terminals(struct crec *source)
1542{
1543 char *name = cache_get_name(source);
Simon Kelleyea6cc332018-09-18 23:21:17 +01001544 struct crec *crecp, *tmp, **up;
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001545 int type = F_HOSTS | F_CONFIG;
1546#ifdef HAVE_DHCP
1547 if (source->flags & F_DHCP)
1548 type = F_DHCP;
1549#endif
1550
1551 /* First delete any empty entries for our new real name. Note that
1552 we only delete empty entries deriving from DHCP for a new DHCP-derived
1553 entry and vice-versa for HOSTS and CONFIG. This ensures that
1554 non-terminals from DHCP go when we reload DHCP and
1555 for HOSTS/CONFIG when we re-read. */
1556 for (up = hash_bucket(name), crecp = *up; crecp; crecp = tmp)
1557 {
1558 tmp = crecp->hash_next;
1559
1560 if (!is_outdated_cname_pointer(crecp) &&
1561 (crecp->flags & F_FORWARD) &&
1562 (crecp->flags & type) &&
Simon Kelleycbfbd172018-08-21 18:25:18 +01001563 !(crecp->flags & (F_IPV4 | F_IPV6 | F_CNAME | F_DNSKEY | F_DS)) &&
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001564 hostname_isequal(name, cache_get_name(crecp)))
1565 {
1566 *up = crecp->hash_next;
1567#ifdef HAVE_DHCP
1568 if (type & F_DHCP)
1569 {
1570 crecp->next = dhcp_spare;
1571 dhcp_spare = crecp;
1572 }
1573 else
1574#endif
1575 free(crecp);
1576 break;
1577 }
1578 else
1579 up = &crecp->hash_next;
1580 }
1581
1582 while ((name = strchr(name, '.')))
1583 {
1584 name++;
1585
1586 /* Look for one existing, don't need another */
1587 for (crecp = *hash_bucket(name); crecp; crecp = crecp->hash_next)
1588 if (!is_outdated_cname_pointer(crecp) &&
1589 (crecp->flags & F_FORWARD) &&
1590 (crecp->flags & type) &&
1591 hostname_isequal(name, cache_get_name(crecp)))
1592 break;
1593
1594 if (crecp)
1595 {
1596 /* If the new name expires later, transfer that time to
1597 empty non-terminal entry. */
1598 if (!(crecp->flags & F_IMMORTAL))
1599 {
1600 if (source->flags & F_IMMORTAL)
1601 crecp->flags |= F_IMMORTAL;
1602 else if (difftime(crecp->ttd, source->ttd) < 0)
1603 crecp->ttd = source->ttd;
1604 }
1605 continue;
1606 }
1607
1608#ifdef HAVE_DHCP
1609 if ((source->flags & F_DHCP) && dhcp_spare)
1610 {
1611 crecp = dhcp_spare;
1612 dhcp_spare = dhcp_spare->next;
1613 }
1614 else
1615#endif
Simon Kelley3a610a02018-09-26 16:50:35 +01001616 crecp = whine_malloc(SIZEOF_POINTER_CREC);
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001617
Simon Kelleyea6cc332018-09-18 23:21:17 +01001618 if (crecp)
1619 {
Simon Kelley48b090c2018-09-26 12:53:59 +01001620 crecp->flags = (source->flags | F_NAMEP) & ~(F_IPV4 | F_IPV6 | F_CNAME | F_DNSKEY | F_DS | F_REVERSE);
1621 crecp->ttd = source->ttd;
Simon Kelleyea6cc332018-09-18 23:21:17 +01001622 crecp->name.namep = name;
1623
1624 cache_hash(crecp);
1625 }
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001626 }
1627}
1628
Kevin Darbyshire-Bryant7ac9ae12016-09-09 20:52:08 +01001629#ifndef NO_ID
Simon Kelleyfec216d2014-03-27 20:54:34 +00001630int cache_make_stat(struct txt_record *t)
1631{
1632 static char *buff = NULL;
1633 static int bufflen = 60;
1634 int len;
1635 struct server *serv, *serv1;
1636 char *p;
1637
1638 if (!buff && !(buff = whine_malloc(60)))
1639 return 0;
1640
1641 p = buff;
1642
1643 switch (t->stat)
1644 {
1645 case TXT_STAT_CACHESIZE:
1646 sprintf(buff+1, "%d", daemon->cachesize);
1647 break;
1648
1649 case TXT_STAT_INSERTS:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001650 sprintf(buff+1, "%d", daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001651 break;
1652
1653 case TXT_STAT_EVICTIONS:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001654 sprintf(buff+1, "%d", daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001655 break;
1656
1657 case TXT_STAT_MISSES:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001658 sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001659 break;
1660
1661 case TXT_STAT_HITS:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001662 sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001663 break;
1664
1665#ifdef HAVE_AUTH
1666 case TXT_STAT_AUTH:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001667 sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001668 break;
1669#endif
1670
1671 case TXT_STAT_SERVERS:
1672 /* sum counts from different records for same server */
1673 for (serv = daemon->servers; serv; serv = serv->next)
1674 serv->flags &= ~SERV_COUNTED;
1675
1676 for (serv = daemon->servers; serv; serv = serv->next)
1677 if (!(serv->flags &
1678 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
1679 {
1680 char *new, *lenp;
1681 int port, newlen, bytes_avail, bytes_needed;
1682 unsigned int queries = 0, failed_queries = 0;
1683 for (serv1 = serv; serv1; serv1 = serv1->next)
1684 if (!(serv1->flags &
1685 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
1686 sockaddr_isequal(&serv->addr, &serv1->addr))
1687 {
1688 serv1->flags |= SERV_COUNTED;
1689 queries += serv1->queries;
1690 failed_queries += serv1->failed_queries;
1691 }
1692 port = prettyprint_addr(&serv->addr, daemon->addrbuff);
1693 lenp = p++; /* length */
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 if (bytes_needed >= bytes_avail)
1697 {
1698 /* expand buffer if necessary */
1699 newlen = bytes_needed + 1 + bufflen - bytes_avail;
1700 if (!(new = whine_malloc(newlen)))
1701 return 0;
1702 memcpy(new, buff, bufflen);
1703 free(buff);
1704 p = new + (p - buff);
1705 lenp = p - 1;
1706 buff = new;
1707 bufflen = newlen;
Simon Kelley04b0ac02015-04-06 17:19:13 +01001708 bytes_avail = bufflen - (p - buff );
Simon Kelleyfec216d2014-03-27 20:54:34 +00001709 bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
1710 }
1711 *lenp = bytes_needed;
1712 p += bytes_needed;
1713 }
1714 t->txt = (unsigned char *)buff;
1715 t->len = p - buff;
1716 return 1;
1717 }
1718
1719 len = strlen(buff+1);
1720 t->txt = (unsigned char *)buff;
1721 t->len = len + 1;
1722 *buff = len;
1723 return 1;
1724}
Kevin Darbyshire-Bryant7ac9ae12016-09-09 20:52:08 +01001725#endif
Simon Kelley9009d742008-11-14 20:04:27 +00001726
Simon Kelley394ff492015-03-29 22:17:14 +01001727/* There can be names in the cache containing control chars, don't
1728 mess up logging or open security holes. */
1729static char *sanitise(char *name)
1730{
1731 unsigned char *r;
Simon Kelley794fccc2015-03-29 22:35:44 +01001732 if (name)
1733 for (r = (unsigned char *)name; *r; r++)
1734 if (!isprint((int)*r))
1735 return "<name unprintable>";
Simon Kelley394ff492015-03-29 22:17:14 +01001736
1737 return name;
1738}
1739
1740
Simon Kelley5aabfc72007-08-29 11:24:47 +01001741void dump_cache(time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001742{
Simon Kelley824af852008-02-12 20:43:05 +00001743 struct server *serv, *serv1;
1744
1745 my_syslog(LOG_INFO, _("time %lu"), (unsigned long)now);
1746 my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001747 daemon->cachesize, daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED], daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
Simon Kelley824af852008-02-12 20:43:05 +00001748 my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001749 daemon->metrics[METRIC_DNS_QUERIES_FORWARDED], daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
Simon Kelleyb485ed92013-10-18 22:00:39 +01001750#ifdef HAVE_AUTH
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001751 my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
Simon Kelleyb485ed92013-10-18 22:00:39 +01001752#endif
Simon Kelleyc2207682014-01-08 18:04:20 +00001753#ifdef HAVE_DNSSEC
1754 blockdata_report();
1755#endif
Simon Kelley824af852008-02-12 20:43:05 +00001756
Simon Kelley824af852008-02-12 20:43:05 +00001757 /* sum counts from different records for same server */
1758 for (serv = daemon->servers; serv; serv = serv->next)
1759 serv->flags &= ~SERV_COUNTED;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001760
Simon Kelley824af852008-02-12 20:43:05 +00001761 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley28866e92011-02-14 20:19:14 +00001762 if (!(serv->flags &
1763 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley824af852008-02-12 20:43:05 +00001764 {
1765 int port;
1766 unsigned int queries = 0, failed_queries = 0;
1767 for (serv1 = serv; serv1; serv1 = serv1->next)
Simon Kelley28866e92011-02-14 20:19:14 +00001768 if (!(serv1->flags &
1769 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
1770 sockaddr_isequal(&serv->addr, &serv1->addr))
Simon Kelley824af852008-02-12 20:43:05 +00001771 {
1772 serv1->flags |= SERV_COUNTED;
1773 queries += serv1->queries;
1774 failed_queries += serv1->failed_queries;
1775 }
Simon Kelleyc72daea2012-01-05 21:33:27 +00001776 port = prettyprint_addr(&serv->addr, daemon->addrbuff);
1777 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 +00001778 }
1779
Simon Kelley28866e92011-02-14 20:19:14 +00001780 if (option_bool(OPT_DEBUG) || option_bool(OPT_LOG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001781 {
1782 struct crec *cache ;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001783 int i;
Simon Kelleye7829ae2014-01-22 22:21:51 +00001784 my_syslog(LOG_INFO, "Host Address Flags Expires");
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001785
1786 for (i=0; i<hash_size; i++)
1787 for (cache = hash_table[i]; cache; cache = cache->hash_next)
1788 {
Simon Kelleyb6f926f2018-08-21 17:46:52 +01001789 char *t = " ";
Simon Kelley0fc2f312014-01-08 10:26:58 +00001790 char *a = daemon->addrbuff, *p = daemon->namebuff, *n = cache_get_name(cache);
1791 *a = 0;
Simon Kelley2d33bda2014-01-24 22:37:25 +00001792 if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
Simon Kelley0fc2f312014-01-08 10:26:58 +00001793 n = "<Root>";
Simon Kelley394ff492015-03-29 22:17:14 +01001794 p += sprintf(p, "%-30.30s ", sanitise(n));
Simon Kelley0fc2f312014-01-08 10:26:58 +00001795 if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
Simon Kelley394ff492015-03-29 22:17:14 +01001796 a = sanitise(cache_get_cname_target(cache));
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001797#ifdef HAVE_DNSSEC
Simon Kelleycdbee9a2012-04-04 21:55:59 +01001798 else if (cache->flags & F_DS)
1799 {
Simon Kelley93be5b12015-12-15 12:04:40 +00001800 if (!(cache->flags & F_NEG))
Simon Kelleyb8eac192014-02-27 14:30:03 +00001801 sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
1802 cache->addr.ds.algo, cache->addr.ds.digest);
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001803 }
1804 else if (cache->flags & F_DNSKEY)
Simon Kelleyb8eac192014-02-27 14:30:03 +00001805 sprintf(a, "%5u %3u %3u", cache->addr.key.keytag,
1806 cache->addr.key.algo, cache->addr.key.flags);
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001807#endif
Simon Kelley0fc2f312014-01-08 10:26:58 +00001808 else if (!(cache->flags & F_NEG) || !(cache->flags & F_FORWARD))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001809 {
Simon Kelleyc72daea2012-01-05 21:33:27 +00001810 a = daemon->addrbuff;
Simon Kelleyf2621c72007-04-29 19:47:21 +01001811 if (cache->flags & F_IPV4)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001812 inet_ntop(AF_INET, &cache->addr.addr, a, ADDRSTRLEN);
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001813#ifdef HAVE_IPV6
Simon Kelleyf2621c72007-04-29 19:47:21 +01001814 else if (cache->flags & F_IPV6)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001815 inet_ntop(AF_INET6, &cache->addr.addr, a, ADDRSTRLEN);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001816#endif
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001817 }
1818
Simon Kelleye7829ae2014-01-22 22:21:51 +00001819 if (cache->flags & F_IPV4)
1820 t = "4";
1821 else if (cache->flags & F_IPV6)
1822 t = "6";
1823 else if (cache->flags & F_CNAME)
1824 t = "C";
1825#ifdef HAVE_DNSSEC
Simon Kelleye7829ae2014-01-22 22:21:51 +00001826 else if (cache->flags & F_DS)
1827 t = "S";
1828 else if (cache->flags & F_DNSKEY)
1829 t = "K";
1830#endif
Simon Kelley32678042014-12-17 20:38:20 +00001831 p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s ", a, t,
Simon Kelleyf2621c72007-04-29 19:47:21 +01001832 cache->flags & F_FORWARD ? "F" : " ",
1833 cache->flags & F_REVERSE ? "R" : " ",
1834 cache->flags & F_IMMORTAL ? "I" : " ",
1835 cache->flags & F_DHCP ? "D" : " ",
1836 cache->flags & F_NEG ? "N" : " ",
1837 cache->flags & F_NXDOMAIN ? "X" : " ",
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001838 cache->flags & F_HOSTS ? "H" : " ",
1839 cache->flags & F_DNSSECOK ? "V" : " ");
Simon Kelley44a2a312004-03-10 20:04:35 +00001840#ifdef HAVE_BROKEN_RTC
Simon Kelleyf2621c72007-04-29 19:47:21 +01001841 p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
Simon Kelley44a2a312004-03-10 20:04:35 +00001842#else
Simon Kelleyf2621c72007-04-29 19:47:21 +01001843 p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd)));
1844 /* ctime includes trailing \n - eat it */
1845 *(p-1) = 0;
Simon Kelley44a2a312004-03-10 20:04:35 +00001846#endif
Rosen Penevcbd29e52017-06-27 22:29:51 +01001847 my_syslog(LOG_INFO, "%s", daemon->namebuff);
Simon Kelleyf2621c72007-04-29 19:47:21 +01001848 }
1849 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001850}
1851
Simon Kelley19c51cf2014-03-18 22:38:30 +00001852char *record_source(unsigned int index)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001853{
Simon Kelley7622fc02009-06-04 20:32:05 +01001854 struct hostsfile *ah;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001855
Simon Kelley19c51cf2014-03-18 22:38:30 +00001856 if (index == SRC_CONFIG)
1857 return "config";
1858 else if (index == SRC_HOSTS)
Simon Kelley7622fc02009-06-04 20:32:05 +01001859 return HOSTSFILE;
1860
1861 for (ah = daemon->addn_hosts; ah; ah = ah->next)
1862 if (ah->index == index)
1863 return ah->fname;
Simon Kelley70d18732015-01-31 19:59:29 +00001864
1865#ifdef HAVE_INOTIFY
1866 for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
1867 if (ah->index == index)
1868 return ah->fname;
1869#endif
1870
Simon Kelley7622fc02009-06-04 20:32:05 +01001871 return "<unknown>";
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001872}
Simon Kelleyc1bb8502004-08-11 18:40:17 +01001873
Simon Kelley610e7822014-02-06 14:45:17 +00001874char *querystr(char *desc, unsigned short type)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001875{
1876 unsigned int i;
Simon Kelley610e7822014-02-06 14:45:17 +00001877 int len = 10; /* strlen("type=xxxxx") */
1878 const char *types = NULL;
1879 static char *buff = NULL;
1880 static int bufflen = 0;
1881
Simon Kelley1a6bca82008-07-11 11:11:42 +01001882 for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
1883 if (typestr[i].type == type)
Simon Kelley610e7822014-02-06 14:45:17 +00001884 {
1885 types = typestr[i].name;
1886 len = strlen(types);
1887 break;
1888 }
1889
Simon Kelleyb758b672018-08-23 21:41:23 +01001890 if (desc)
1891 {
1892 len += 2; /* braces */
1893 len += strlen(desc);
1894 }
1895 len++; /* terminator */
1896
Simon Kelley610e7822014-02-06 14:45:17 +00001897 if (!buff || bufflen < len)
1898 {
1899 if (buff)
1900 free(buff);
1901 else if (len < 20)
1902 len = 20;
1903
1904 buff = whine_malloc(len);
1905 bufflen = len;
1906 }
1907
1908 if (buff)
1909 {
Simon Kelleyb758b672018-08-23 21:41:23 +01001910 if (desc)
1911 {
1912 if (types)
1913 sprintf(buff, "%s[%s]", desc, types);
1914 else
1915 sprintf(buff, "%s[type=%d]", desc, type);
1916 }
Simon Kelley610e7822014-02-06 14:45:17 +00001917 else
Simon Kelleyb758b672018-08-23 21:41:23 +01001918 {
1919 if (types)
1920 sprintf(buff, "<%s>", types);
1921 else
1922 sprintf(buff, "type=%d", type);
1923 }
Simon Kelley610e7822014-02-06 14:45:17 +00001924 }
Simon Kelleyb758b672018-08-23 21:41:23 +01001925
Simon Kelley610e7822014-02-06 14:45:17 +00001926 return buff ? buff : "";
Simon Kelley1a6bca82008-07-11 11:11:42 +01001927}
1928
Simon Kelley28866e92011-02-14 20:19:14 +00001929void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001930{
Simon Kelleyc72daea2012-01-05 21:33:27 +00001931 char *source, *dest = daemon->addrbuff;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001932 char *verb = "is";
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001933
Simon Kelley28866e92011-02-14 20:19:14 +00001934 if (!option_bool(OPT_LOG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001935 return;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001936
Simon Kelley394ff492015-03-29 22:17:14 +01001937 name = sanitise(name);
1938
Simon Kelley5aabfc72007-08-29 11:24:47 +01001939 if (addr)
1940 {
Simon Kelley0fc2f312014-01-08 10:26:58 +00001941 if (flags & F_KEYTAG)
Simon Kelley15379ea2015-12-21 18:31:55 +00001942 sprintf(daemon->addrbuff, arg, addr->addr.log.keytag, addr->addr.log.algo, addr->addr.log.digest);
Simon Kelley07ed5852018-05-04 21:52:22 +01001943 else if (flags & F_RCODE)
1944 {
1945 unsigned int rcode = addr->addr.rcode.rcode;
1946
1947 if (rcode == SERVFAIL)
1948 dest = "SERVFAIL";
1949 else if (rcode == REFUSED)
1950 dest = "REFUSED";
1951 else if (rcode == NOTIMP)
1952 dest = "not implemented";
1953 else
1954 sprintf(daemon->addrbuff, "%u", rcode);
1955 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001956 else
1957 {
Simon Kelley5aabfc72007-08-29 11:24:47 +01001958#ifdef HAVE_IPV6
Simon Kelley0fc2f312014-01-08 10:26:58 +00001959 inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
1960 addr, daemon->addrbuff, ADDRSTRLEN);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001961#else
Simon Kelley0fc2f312014-01-08 10:26:58 +00001962 strncpy(daemon->addrbuff, inet_ntoa(addr->addr.addr4), ADDRSTRLEN);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001963#endif
Simon Kelley0fc2f312014-01-08 10:26:58 +00001964 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001965 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001966 else
1967 dest = arg;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001968
1969 if (flags & F_REVERSE)
1970 {
1971 dest = name;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001972 name = daemon->addrbuff;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001973 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001974
1975 if (flags & F_NEG)
1976 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001977 if (flags & F_NXDOMAIN)
Simon Kelley40b695c2014-02-03 17:07:51 +00001978 dest = "NXDOMAIN";
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001979 else
Simon Kelley5aabfc72007-08-29 11:24:47 +01001980 {
1981 if (flags & F_IPV4)
1982 dest = "NODATA-IPv4";
Simon Kelley824af852008-02-12 20:43:05 +00001983 else if (flags & F_IPV6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001984 dest = "NODATA-IPv6";
Simon Kelley824af852008-02-12 20:43:05 +00001985 else
1986 dest = "NODATA";
Simon Kelley5aabfc72007-08-29 11:24:47 +01001987 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001988 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001989 else if (flags & F_CNAME)
Simon Kelley28866e92011-02-14 20:19:14 +00001990 dest = "<CNAME>";
1991 else if (flags & F_RRNAME)
1992 dest = arg;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001993
Simon Kelley1f15b812009-10-13 17:49:32 +01001994 if (flags & F_CONFIG)
1995 source = "config";
1996 else if (flags & F_DHCP)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001997 source = "DHCP";
1998 else if (flags & F_HOSTS)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001999 source = arg;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002000 else if (flags & F_UPSTREAM)
2001 source = "reply";
Simon Kelley0fc2f312014-01-08 10:26:58 +00002002 else if (flags & F_SECSTAT)
2003 source = "validation";
Simon Kelley4f7b3042012-11-28 21:27:02 +00002004 else if (flags & F_AUTH)
2005 source = "auth";
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002006 else if (flags & F_SERVER)
2007 {
2008 source = "forwarded";
2009 verb = "to";
2010 }
2011 else if (flags & F_QUERY)
2012 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01002013 source = arg;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002014 verb = "from";
2015 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00002016 else if (flags & F_DNSSEC)
2017 {
2018 source = arg;
2019 verb = "to";
2020 }
Wang Jian49752b92014-03-28 20:52:47 +00002021 else if (flags & F_IPSET)
2022 {
2023 source = "ipset add";
2024 dest = name;
2025 name = arg;
2026 verb = daemon->addrbuff;
2027 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002028 else
2029 source = "cached";
2030
Simon Kelley3d8df262005-08-29 12:19:27 +01002031 if (strlen(name) == 0)
2032 name = ".";
2033
Simon Kelley25cf5e32015-01-09 15:53:03 +00002034 if (option_bool(OPT_EXTRALOG))
2035 {
Simon Kelley9f79ee42015-01-12 20:18:18 +00002036 int port = prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2);
Simon Kelley25cf5e32015-01-09 15:53:03 +00002037 if (flags & F_NOEXTRA)
Simon Kelley9f79ee42015-01-12 20:18:18 +00002038 my_syslog(LOG_INFO, "* %s/%u %s %s %s %s", daemon->addrbuff2, port, source, name, verb, dest);
Simon Kelley25cf5e32015-01-09 15:53:03 +00002039 else
Simon Kelley9f79ee42015-01-12 20:18:18 +00002040 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 +00002041 }
2042 else
2043 my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002044}
2045
Simon Kelley98c098b2014-01-08 17:31:16 +00002046