blob: 9e0923d3fe702f5277793ec22fd80239ac6de066 [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 Kelley16972692006-10-16 20:04:18 +010028/* type->string mapping: this is also used by the name-hash function as a mixing table. */
29static const struct {
30 unsigned int type;
31 const char * const name;
32} typestr[] = {
33 { 1, "A" },
34 { 2, "NS" },
35 { 5, "CNAME" },
36 { 6, "SOA" },
37 { 10, "NULL" },
38 { 11, "WKS" },
39 { 12, "PTR" },
40 { 13, "HINFO" },
41 { 15, "MX" },
42 { 16, "TXT" },
43 { 22, "NSAP" },
44 { 23, "NSAP_PTR" },
45 { 24, "SIG" },
46 { 25, "KEY" },
47 { 28, "AAAA" },
Simon Kelleyaa6f8322017-10-27 22:52:26 +010048 { 29, "LOC" },
Simon Kelley16972692006-10-16 20:04:18 +010049 { 33, "SRV" },
Simon Kelley1a6bca82008-07-11 11:11:42 +010050 { 35, "NAPTR" },
Simon Kelley16972692006-10-16 20:04:18 +010051 { 36, "KX" },
52 { 37, "CERT" },
53 { 38, "A6" },
54 { 39, "DNAME" },
55 { 41, "OPT" },
Simon Kelley0fc2f312014-01-08 10:26:58 +000056 { 43, "DS" },
57 { 46, "RRSIG" },
Simon Kelley610e7822014-02-06 14:45:17 +000058 { 47, "NSEC" },
Simon Kelley832af0b2007-01-21 20:01:28 +000059 { 48, "DNSKEY" },
Simon Kelley610e7822014-02-06 14:45:17 +000060 { 50, "NSEC3" },
Simon Kelleyaa6f8322017-10-27 22:52:26 +010061 { 51, "NSEC3PARAM" },
62 { 52, "TLSA" },
63 { 53, "SMIMEA" },
64 { 55, "HIP" },
Simon Kelley832af0b2007-01-21 20:01:28 +000065 { 249, "TKEY" },
Simon Kelley16972692006-10-16 20:04:18 +010066 { 250, "TSIG" },
67 { 251, "IXFR" },
68 { 252, "AXFR" },
69 { 253, "MAILB" },
70 { 254, "MAILA" },
71 { 255, "ANY" }
72};
73
Simon Kelley9e4abcb2004-01-22 19:47:41 +000074static void cache_free(struct crec *crecp);
75static void cache_unlink(struct crec *crecp);
76static void cache_link(struct crec *crecp);
Simon Kelley4011c4e2006-10-28 16:26:19 +010077static void rehash(int size);
78static void cache_hash(struct crec *crecp);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000079
Simon Kelley45d8a242018-07-17 21:01:14 +010080void next_uid(struct crec *crecp)
Simon Kelley3f7483e2014-03-16 22:56:58 +000081{
Andyd5082152014-03-17 19:50:29 +000082 static unsigned int uid = 0;
Simon Kelley3f7483e2014-03-16 22:56:58 +000083
Simon Kelley45d8a242018-07-17 21:01:14 +010084 if (crecp->uid == UID_NONE)
85 {
86 uid++;
Andyd5082152014-03-17 19:50:29 +000087
Simon Kelley45d8a242018-07-17 21:01:14 +010088 /* uid == 0 used to indicate CNAME to interface name. */
89 if (uid == UID_NONE)
90 uid++;
91
92 crecp->uid = uid;
93 }
Simon Kelley3f7483e2014-03-16 22:56:58 +000094}
95
Simon Kelley5aabfc72007-08-29 11:24:47 +010096void cache_init(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +000097{
98 struct crec *crecp;
99 int i;
Simon Kelleyd56a6042013-10-11 14:39:03 +0100100
Simon Kelley5aabfc72007-08-29 11:24:47 +0100101 bignames_left = daemon->cachesize/10;
102
103 if (daemon->cachesize > 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000104 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100105 crecp = safe_malloc(daemon->cachesize*sizeof(struct crec));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000106
Simon Kelley5aabfc72007-08-29 11:24:47 +0100107 for (i=0; i < daemon->cachesize; i++, crecp++)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000108 {
109 cache_link(crecp);
110 crecp->flags = 0;
Simon Kelley45d8a242018-07-17 21:01:14 +0100111 crecp->uid = UID_NONE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000112 }
113 }
114
Simon Kelley4011c4e2006-10-28 16:26:19 +0100115 /* create initial hash table*/
Simon Kelley5aabfc72007-08-29 11:24:47 +0100116 rehash(daemon->cachesize);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000117}
118
Simon Kelley4011c4e2006-10-28 16:26:19 +0100119/* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
120 but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
121 will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
122 expand the table. */
123static void rehash(int size)
124{
125 struct crec **new, **old, *p, *tmp;
126 int i, new_size, old_size;
127
128 /* hash_size is a power of two. */
129 for (new_size = 64; new_size < size/10; new_size = new_size << 1);
130
131 /* must succeed in getting first instance, failure later is non-fatal */
132 if (!hash_table)
133 new = safe_malloc(new_size * sizeof(struct crec *));
Simon Kelley5aabfc72007-08-29 11:24:47 +0100134 else if (new_size <= hash_size || !(new = whine_malloc(new_size * sizeof(struct crec *))))
Simon Kelley4011c4e2006-10-28 16:26:19 +0100135 return;
136
137 for(i = 0; i < new_size; i++)
138 new[i] = NULL;
139
140 old = hash_table;
141 old_size = hash_size;
142 hash_table = new;
143 hash_size = new_size;
144
145 if (old)
146 {
147 for (i = 0; i < old_size; i++)
148 for (p = old[i]; p ; p = tmp)
149 {
150 tmp = p->hash_next;
151 cache_hash(p);
152 }
153 free(old);
154 }
155}
156
Simon Kelley3d8df262005-08-29 12:19:27 +0100157static struct crec **hash_bucket(char *name)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000158{
Simon Kelley4011c4e2006-10-28 16:26:19 +0100159 unsigned int c, val = 017465; /* Barker code - minimum self-correlation in cyclic shift */
Simon Kelley16972692006-10-16 20:04:18 +0100160 const unsigned char *mix_tab = (const unsigned char*)typestr;
161
Simon Kelley3d8df262005-08-29 12:19:27 +0100162 while((c = (unsigned char) *name++))
Simon Kelley16972692006-10-16 20:04:18 +0100163 {
164 /* don't use tolower and friends here - they may be messed up by LOCALE */
165 if (c >= 'A' && c <= 'Z')
166 c += 'a' - 'A';
Simon Kelley4011c4e2006-10-28 16:26:19 +0100167 val = ((val << 7) | (val >> (32 - 7))) + (mix_tab[(val + c) & 0x3F] ^ c);
Simon Kelley16972692006-10-16 20:04:18 +0100168 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000169
170 /* hash_size is a power of two */
Simon Kelley16972692006-10-16 20:04:18 +0100171 return hash_table + ((val ^ (val >> 16)) & (hash_size - 1));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000172}
173
174static void cache_hash(struct crec *crecp)
175{
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000176 /* maintain an invariant that all entries with F_REVERSE set
177 are at the start of the hash-chain and all non-reverse
178 immortal entries are at the end of the hash-chain.
179 This allows reverse searches and garbage collection to be optimised */
180
181 struct crec **up = hash_bucket(cache_get_name(crecp));
182
183 if (!(crecp->flags & F_REVERSE))
184 {
185 while (*up && ((*up)->flags & F_REVERSE))
186 up = &((*up)->hash_next);
187
188 if (crecp->flags & F_IMMORTAL)
Simon Kelley6b010842007-02-12 20:32:07 +0000189 while (*up && !((*up)->flags & F_IMMORTAL))
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000190 up = &((*up)->hash_next);
191 }
192 crecp->hash_next = *up;
193 *up = crecp;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000194}
Simon Kelley82e3f452014-01-31 21:05:48 +0000195
196#ifdef HAVE_DNSSEC
197static void cache_blockdata_free(struct crec *crecp)
198{
199 if (crecp->flags & F_DNSKEY)
Simon Kelley93be5b12015-12-15 12:04:40 +0000200 blockdata_free(crecp->addr.key.keydata);
Simon Kelleye3f14552014-03-01 17:58:28 +0000201 else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG))
Simon Kelley82e3f452014-01-31 21:05:48 +0000202 blockdata_free(crecp->addr.ds.keydata);
203}
204#endif
205
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000206static void cache_free(struct crec *crecp)
207{
208 crecp->flags &= ~F_FORWARD;
209 crecp->flags &= ~F_REVERSE;
Simon Kelley45d8a242018-07-17 21:01:14 +0100210 crecp->uid = UID_NONE; /* invalidate CNAMES pointing to this. */
Simon Kelleyd56a6042013-10-11 14:39:03 +0100211
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000212 if (cache_tail)
213 cache_tail->next = crecp;
214 else
215 cache_head = crecp;
216 crecp->prev = cache_tail;
217 crecp->next = NULL;
218 cache_tail = crecp;
219
220 /* retrieve big name for further use. */
221 if (crecp->flags & F_BIGNAME)
222 {
223 crecp->name.bname->next = big_free;
224 big_free = crecp->name.bname;
225 crecp->flags &= ~F_BIGNAME;
226 }
Simon Kelley072e81b2014-01-31 12:42:54 +0000227
Simon Kelley7b4ad2e2012-04-04 14:05:35 +0100228#ifdef HAVE_DNSSEC
Simon Kelley82e3f452014-01-31 21:05:48 +0000229 cache_blockdata_free(crecp);
Simon Kelley7b4ad2e2012-04-04 14:05:35 +0100230#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000231}
232
233/* insert a new cache entry at the head of the list (youngest entry) */
234static void cache_link(struct crec *crecp)
235{
236 if (cache_head) /* check needed for init code */
237 cache_head->prev = crecp;
238 crecp->next = cache_head;
239 crecp->prev = NULL;
240 cache_head = crecp;
241 if (!cache_tail)
242 cache_tail = crecp;
243}
244
245/* remove an arbitrary cache entry for promotion */
246static void cache_unlink (struct crec *crecp)
247{
248 if (crecp->prev)
249 crecp->prev->next = crecp->next;
250 else
251 cache_head = crecp->next;
252
253 if (crecp->next)
254 crecp->next->prev = crecp->prev;
255 else
256 cache_tail = crecp->prev;
257}
258
259char *cache_get_name(struct crec *crecp)
260{
261 if (crecp->flags & F_BIGNAME)
262 return crecp->name.bname->name;
Simon Kelley28866e92011-02-14 20:19:14 +0000263 else if (crecp->flags & F_NAMEP)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000264 return crecp->name.namep;
265
266 return crecp->name.sname;
267}
268
Simon Kelleyd56a6042013-10-11 14:39:03 +0100269char *cache_get_cname_target(struct crec *crecp)
270{
Simon Kelley19c51cf2014-03-18 22:38:30 +0000271 if (crecp->addr.cname.uid != SRC_INTERFACE)
Simon Kelleyd56a6042013-10-11 14:39:03 +0100272 return cache_get_name(crecp->addr.cname.target.cache);
273
274 return crecp->addr.cname.target.int_name->name;
275}
276
277
278
Simon Kelleyb75e9362012-12-07 11:50:41 +0000279struct crec *cache_enumerate(int init)
280{
281 static int bucket;
282 static struct crec *cache;
283
284 if (init)
285 {
286 bucket = 0;
287 cache = NULL;
288 }
289 else if (cache && cache->hash_next)
290 cache = cache->hash_next;
291 else
292 {
293 cache = NULL;
294 while (bucket < hash_size)
295 if ((cache = hash_table[bucket++]))
296 break;
297 }
298
299 return cache;
300}
301
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100302static int is_outdated_cname_pointer(struct crec *crecp)
303{
Andy3e21a1a2014-03-22 19:10:07 +0000304 if (!(crecp->flags & F_CNAME) || crecp->addr.cname.uid == SRC_INTERFACE)
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100305 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100306
Simon Kelleycdbee9a2012-04-04 21:55:59 +0100307 /* NB. record may be reused as DS or DNSKEY, where uid is
308 overloaded for something completely different */
Simon Kelleyd56a6042013-10-11 14:39:03 +0100309 if (crecp->addr.cname.target.cache &&
310 (crecp->addr.cname.target.cache->flags & (F_IPV4 | F_IPV6 | F_CNAME)) &&
311 crecp->addr.cname.uid == crecp->addr.cname.target.cache->uid)
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100312 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100313
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100314 return 1;
315}
316
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000317static int is_expired(time_t now, struct crec *crecp)
318{
319 if (crecp->flags & F_IMMORTAL)
320 return 0;
321
322 if (difftime(now, crecp->ttd) < 0)
323 return 0;
Simon Kelley4011c4e2006-10-28 16:26:19 +0100324
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000325 return 1;
326}
327
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100328static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags,
329 struct crec **target_crec, unsigned int *target_uid)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000330{
331 /* Scan and remove old entries.
332 If (flags & F_FORWARD) then remove any forward entries for name and any expired
333 entries but only in the same hash bucket as name.
334 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
335 entries in the whole cache.
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000336 If (flags == 0) remove any expired entries in the whole cache.
337
Simon Kelleycbc65242014-12-21 21:21:53 +0000338 In the flags & F_FORWARD case, the return code is valid, and returns a non-NULL pointer
339 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 +0000340
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000341 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100342 so that when we hit an entry which isn't reverse and is immortal, we're done.
343
344 If we free a crec which is a CNAME target, return the entry and uid in target_crec and target_uid.
345 This entry will get re-used with the same name, to preserve CNAMEs. */
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000346
347 struct crec *crecp, **up;
348
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000349 if (flags & F_FORWARD)
350 {
Simon Kelley6b010842007-02-12 20:32:07 +0000351 for (up = hash_bucket(name), crecp = *up; crecp; crecp = crecp->hash_next)
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000352 {
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000353 if ((crecp->flags & F_FORWARD) && hostname_isequal(cache_get_name(crecp), name))
354 {
Simon Kelleye7829ae2014-01-22 22:21:51 +0000355 /* Don't delete DNSSEC in favour of a CNAME, they can co-exist */
356 if ((flags & crecp->flags & (F_IPV4 | F_IPV6)) ||
Simon Kelley6429e422014-01-23 12:09:36 +0000357 (((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))))
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000358 {
359 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
Simon Kelleycbc65242014-12-21 21:21:53 +0000360 return crecp;
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000361 *up = crecp->hash_next;
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100362 /* If this record is for the name we're inserting and is the target
363 of a CNAME record. Make the new record for the same name, in the same
364 crec, with the same uid to avoid breaking the existing CNAME. */
365 if (crecp->uid != UID_NONE)
366 {
367 if (target_crec)
368 *target_crec = crecp;
369 if (target_uid)
370 *target_uid = crecp->uid;
371 }
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000372 cache_unlink(crecp);
373 cache_free(crecp);
374 continue;
375 }
376
377#ifdef HAVE_DNSSEC
Simon Kelley93be5b12015-12-15 12:04:40 +0000378 /* Deletion has to be class-sensitive for DS and DNSKEY */
379 if ((flags & crecp->flags & (F_DNSKEY | F_DS)) && crecp->uid == addr->addr.dnssec.class)
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000380 {
Simon Kelley824202e2014-01-23 20:59:46 +0000381 if (crecp->flags & F_CONFIG)
Simon Kelleycbc65242014-12-21 21:21:53 +0000382 return crecp;
Simon Kelley824202e2014-01-23 20:59:46 +0000383 *up = crecp->hash_next;
384 cache_unlink(crecp);
385 cache_free(crecp);
386 continue;
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000387 }
388#endif
389 }
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100390
391 if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp))
392 {
393 *up = crecp->hash_next;
394 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
395 {
396 cache_unlink(crecp);
397 cache_free(crecp);
398 }
399 continue;
400 }
401
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000402 up = &crecp->hash_next;
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000403 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000404 }
405 else
406 {
407 int i;
408#ifdef HAVE_IPV6
409 int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ;
410#else
411 int addrlen = INADDRSZ;
412#endif
413 for (i = 0; i < hash_size; i++)
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000414 for (crecp = hash_table[i], up = &hash_table[i];
415 crecp && ((crecp->flags & F_REVERSE) || !(crecp->flags & F_IMMORTAL));
416 crecp = crecp->hash_next)
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000417 if (is_expired(now, crecp))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000418 {
419 *up = crecp->hash_next;
Simon Kelley25439062013-11-25 21:14:51 +0000420 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000421 {
422 cache_unlink(crecp);
423 cache_free(crecp);
424 }
425 }
Simon Kelley25439062013-11-25 21:14:51 +0000426 else if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) &&
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000427 (flags & crecp->flags & F_REVERSE) &&
428 (flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
429 memcmp(&crecp->addr.addr, addr, addrlen) == 0)
430 {
431 *up = crecp->hash_next;
432 cache_unlink(crecp);
433 cache_free(crecp);
434 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000435 else
436 up = &crecp->hash_next;
437 }
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000438
Simon Kelleycbc65242014-12-21 21:21:53 +0000439 return NULL;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000440}
441
442/* Note: The normal calling sequence is
443 cache_start_insert
444 cache_insert * n
445 cache_end_insert
446
447 but an abort can cause the cache_end_insert to be missed
448 in which can the next cache_start_insert cleans things up. */
449
450void cache_start_insert(void)
451{
452 /* Free any entries which didn't get committed during the last
453 insert due to error.
454 */
455 while (new_chain)
456 {
457 struct crec *tmp = new_chain->next;
458 cache_free(new_chain);
459 new_chain = tmp;
460 }
461 new_chain = NULL;
462 insert_error = 0;
463}
464
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100465struct crec *cache_insert(char *name, struct all_addr *addr,
466 time_t now, unsigned long ttl, unsigned short flags)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000467{
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100468 struct crec *new, *target_crec = NULL;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000469 union bigname *big_name = NULL;
470 int freed_all = flags & F_REVERSE;
Simon Kelley9e038942008-05-30 20:06:34 +0100471 int free_avail = 0;
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100472 unsigned int target_uid;
473
Simon Kelleya0ab18f2014-02-13 16:38:23 +0000474 /* Don't log DNSSEC records here, done elsewhere */
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000475 if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
Simon Kelleya0ab18f2014-02-13 16:38:23 +0000476 {
477 log_query(flags | F_UPSTREAM, name, addr, NULL);
RinSatsuki28de3872015-01-10 15:22:21 +0000478 /* Don't mess with TTL for DNSSEC records. */
Simon Kelleya0ab18f2014-02-13 16:38:23 +0000479 if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
480 ttl = daemon->max_cache_ttl;
RinSatsuki28de3872015-01-10 15:22:21 +0000481 if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl)
482 ttl = daemon->min_cache_ttl;
Simon Kelleya0ab18f2014-02-13 16:38:23 +0000483 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000484
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000485 /* if previous insertion failed give up now. */
486 if (insert_error)
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100487 return NULL;
Simon Kelley8d718cb2014-02-03 16:27:37 +0000488
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000489 /* First remove any expired entries and entries for the name/address we
Simon Kelleycbc65242014-12-21 21:21:53 +0000490 are currently inserting. */
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100491 if ((new = cache_scan_free(name, addr, now, flags, &target_crec, &target_uid)))
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000492 {
Simon Kelleycbc65242014-12-21 21:21:53 +0000493 /* We're trying to insert a record over one from
494 /etc/hosts or DHCP, or other config. If the
495 existing record is for an A or AAAA and
496 the record we're trying to insert is the same,
497 just drop the insert, but don't error the whole process. */
Edwin Török41a8d9e2015-11-14 17:45:48 +0000498 if ((flags & (F_IPV4 | F_IPV6)) && (flags & F_FORWARD) && addr)
Simon Kelleycbc65242014-12-21 21:21:53 +0000499 {
500 if ((flags & F_IPV4) && (new->flags & F_IPV4) &&
501 new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr)
502 return new;
503#ifdef HAVE_IPV6
504 else if ((flags & F_IPV6) && (new->flags & F_IPV6) &&
505 IN6_ARE_ADDR_EQUAL(&new->addr.addr.addr.addr6, &addr->addr.addr6))
506 return new;
507#endif
508 }
509
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000510 insert_error = 1;
511 return NULL;
512 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000513
514 /* Now get a cache entry from the end of the LRU list */
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100515 if (!target_crec)
516 while (1) {
517 if (!(new = cache_tail)) /* no entries left - cache is too small, bail */
518 {
519 insert_error = 1;
520 return NULL;
521 }
522
523 /* Free entry at end of LRU list, use it. */
524 if (!(new->flags & (F_FORWARD | F_REVERSE)))
525 break;
Simon Kelley8d718cb2014-02-03 16:27:37 +0000526
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100527 /* End of LRU list is still in use: if we didn't scan all the hash
528 chains for expired entries do that now. If we already tried that
529 then it's time to start spilling things. */
530
531 /* If free_avail set, we believe that an entry has been freed.
532 Bugs have been known to make this not true, resulting in
533 a tight loop here. If that happens, abandon the
534 insert. Once in this state, all inserts will probably fail. */
535 if (free_avail)
536 {
537 static int warned = 0;
538 if (!warned)
539 {
540 my_syslog(LOG_ERR, _("Internal error in cache."));
541 warned = 1;
542 }
543 insert_error = 1;
544 return NULL;
545 }
546
547 if (freed_all)
548 {
549 struct all_addr free_addr = new->addr.addr;;
550
Simon Kelley8d718cb2014-02-03 16:27:37 +0000551#ifdef HAVE_DNSSEC
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100552 /* For DNSSEC records, addr holds class. */
553 if (new->flags & (F_DS | F_DNSKEY))
554 free_addr.addr.dnssec.class = new->uid;
Simon Kelley8d718cb2014-02-03 16:27:37 +0000555#endif
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100556
557 free_avail = 1; /* Must be free space now. */
558 cache_scan_free(cache_get_name(new), &free_addr, now, new->flags, NULL, NULL);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +0100559 daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]++;
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100560 }
561 else
562 {
563 cache_scan_free(NULL, NULL, now, 0, NULL, NULL);
564 freed_all = 1;
565 }
566 }
567
568 /* Check if we need to and can allocate extra memory for a long name.
569 If that fails, give up now, always succeed for DNSSEC records. */
570 if (name && (strlen(name) > SMALLDNAME-1))
571 {
572 if (big_free)
573 {
574 big_name = big_free;
575 big_free = big_free->next;
576 }
577 else if ((bignames_left == 0 && !(flags & (F_DS | F_DNSKEY))) ||
578 !(big_name = (union bigname *)whine_malloc(sizeof(union bigname))))
579 {
580 insert_error = 1;
581 return NULL;
582 }
583 else if (bignames_left != 0)
584 bignames_left--;
585
586 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000587
Simon Kelleyeb1fe152018-07-18 20:59:52 +0100588 /* If we freed a cache entry for our name which was a CNAME target, use that.
589 and preserve the uid, so that existing CNAMES are not broken. */
590 if (target_crec)
591 {
592 new = target_crec;
593 new->uid = target_uid;
594 }
595
596 /* Got the rest: finally grab entry. */
597 cache_unlink(new);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000598
599 new->flags = flags;
600 if (big_name)
601 {
602 new->name.bname = big_name;
603 new->flags |= F_BIGNAME;
604 }
Simon Kelley5aabfc72007-08-29 11:24:47 +0100605
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000606 if (name)
607 strcpy(cache_get_name(new), name);
608 else
609 *cache_get_name(new) = 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100610
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000611 if (addr)
Simon Kelleyb8eac192014-02-27 14:30:03 +0000612 {
613#ifdef HAVE_DNSSEC
614 if (flags & (F_DS | F_DNSKEY))
615 new->uid = addr->addr.dnssec.class;
616 else
617#endif
618 new->addr.addr = *addr;
619 }
Simon Kelley7b4ad2e2012-04-04 14:05:35 +0100620
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000621 new->ttd = now + (time_t)ttl;
622 new->next = new_chain;
623 new_chain = new;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100624
625 return new;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000626}
627
628/* after end of insertion, commit the new entries */
629void cache_end_insert(void)
630{
631 if (insert_error)
632 return;
633
634 while (new_chain)
635 {
636 struct crec *tmp = new_chain->next;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100637 /* drop CNAMEs which didn't find a target. */
638 if (is_outdated_cname_pointer(new_chain))
639 cache_free(new_chain);
640 else
641 {
642 cache_hash(new_chain);
643 cache_link(new_chain);
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +0100644 daemon->metrics[METRIC_DNS_CACHE_INSERTED]++;
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100645 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000646 new_chain = tmp;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000647 }
648 new_chain = NULL;
649}
650
Simon Kelley12fae492014-02-04 22:03:06 +0000651struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned int prot)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000652{
653 struct crec *ans;
Simon Kelley12fae492014-02-04 22:03:06 +0000654 int no_rr = prot & F_NO_RR;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000655
Simon Kelley12fae492014-02-04 22:03:06 +0000656 prot &= ~F_NO_RR;
657
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000658 if (crecp) /* iterating */
659 ans = crecp->next;
660 else
661 {
662 /* first search, look for relevant entries and push to top of list
663 also free anything which has expired */
664 struct crec *next, **up, **insert = NULL, **chainp = &ans;
Simon Kelley28866e92011-02-14 20:19:14 +0000665 unsigned short ins_flags = 0;
Simon Kelley824af852008-02-12 20:43:05 +0000666
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000667 for (up = hash_bucket(name), crecp = *up; crecp; crecp = next)
668 {
669 next = crecp->hash_next;
670
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000671 if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000672 {
673 if ((crecp->flags & F_FORWARD) &&
674 (crecp->flags & prot) &&
675 hostname_isequal(cache_get_name(crecp), name))
676 {
Simon Kelley25439062013-11-25 21:14:51 +0000677 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000678 {
679 *chainp = crecp;
680 chainp = &crecp->next;
681 }
682 else
683 {
684 cache_unlink(crecp);
685 cache_link(crecp);
686 }
687
Simon Kelley824af852008-02-12 20:43:05 +0000688 /* Move all but the first entry up the hash chain
689 this implements round-robin.
690 Make sure that re-ordering doesn't break the hash-chain
691 order invariants.
692 */
Simon Kelley9e038942008-05-30 20:06:34 +0100693 if (insert && (crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000694 {
695 *up = crecp->hash_next;
696 crecp->hash_next = *insert;
697 *insert = crecp;
698 insert = &crecp->hash_next;
699 }
Simon Kelley9e038942008-05-30 20:06:34 +0100700 else
701 {
Simon Kelley12fae492014-02-04 22:03:06 +0000702 if (!insert && !no_rr)
Simon Kelley9e038942008-05-30 20:06:34 +0100703 {
704 insert = up;
705 ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
706 }
707 up = &crecp->hash_next;
708 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000709 }
710 else
711 /* case : not expired, incorrect entry. */
712 up = &crecp->hash_next;
713 }
714 else
715 {
716 /* expired entry, free it */
717 *up = crecp->hash_next;
Simon Kelley25439062013-11-25 21:14:51 +0000718 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000719 {
720 cache_unlink(crecp);
721 cache_free(crecp);
722 }
723 }
724 }
725
726 *chainp = cache_head;
727 }
728
729 if (ans &&
730 (ans->flags & F_FORWARD) &&
Simon Kelley51ea3ca2014-01-22 19:31:38 +0000731 (ans->flags & prot) &&
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000732 hostname_isequal(cache_get_name(ans), name))
733 return ans;
734
735 return NULL;
736}
737
738struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
Simon Kelley12fae492014-02-04 22:03:06 +0000739 time_t now, unsigned int prot)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000740{
741 struct crec *ans;
742#ifdef HAVE_IPV6
743 int addrlen = (prot == F_IPV6) ? IN6ADDRSZ : INADDRSZ;
744#else
745 int addrlen = INADDRSZ;
746#endif
747
748 if (crecp) /* iterating */
749 ans = crecp->next;
750 else
751 {
752 /* first search, look for relevant entries and push to top of list
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000753 also free anything which has expired. All the reverse entries are at the
754 start of the hash chain, so we can give up when we find the first
755 non-REVERSE one. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000756 int i;
757 struct crec **up, **chainp = &ans;
758
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000759 for (i=0; i<hash_size; i++)
760 for (crecp = hash_table[i], up = &hash_table[i];
761 crecp && (crecp->flags & F_REVERSE);
762 crecp = crecp->hash_next)
Simon Kelleyf6b7dc42005-01-23 12:06:08 +0000763 if (!is_expired(now, crecp))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000764 {
Simon Kelley6b010842007-02-12 20:32:07 +0000765 if ((crecp->flags & prot) &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100766 memcmp(&crecp->addr.addr, addr, addrlen) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000767 {
Simon Kelley25439062013-11-25 21:14:51 +0000768 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000769 {
770 *chainp = crecp;
771 chainp = &crecp->next;
772 }
773 else
774 {
775 cache_unlink(crecp);
776 cache_link(crecp);
777 }
778 }
779 up = &crecp->hash_next;
780 }
781 else
782 {
783 *up = crecp->hash_next;
Simon Kelley25439062013-11-25 21:14:51 +0000784 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000785 {
786 cache_unlink(crecp);
787 cache_free(crecp);
788 }
789 }
790
791 *chainp = cache_head;
792 }
793
794 if (ans &&
795 (ans->flags & F_REVERSE) &&
796 (ans->flags & prot) &&
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100797 memcmp(&ans->addr.addr, addr, addrlen) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000798 return ans;
799
800 return NULL;
801}
802
Simon Kelley611ebc52012-07-16 16:23:46 +0100803static void add_hosts_cname(struct crec *target)
804{
805 struct crec *crec;
806 struct cname *a;
807
808 for (a = daemon->cnames; a; a = a->next)
Simon Kelleyb637d782016-12-13 16:44:11 +0000809 if (a->alias[1] != '*' &&
810 hostname_isequal(cache_get_name(target), a->target) &&
Simon Kelley611ebc52012-07-16 16:23:46 +0100811 (crec = whine_malloc(sizeof(struct crec))))
812 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +0000813 crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
Simon Kelleydf3d54f2016-02-24 21:03:38 +0000814 crec->ttd = a->ttl;
Simon Kelley611ebc52012-07-16 16:23:46 +0100815 crec->name.namep = a->alias;
Simon Kelleyd56a6042013-10-11 14:39:03 +0100816 crec->addr.cname.target.cache = target;
Simon Kelley45d8a242018-07-17 21:01:14 +0100817 next_uid(target);
Simon Kelley611ebc52012-07-16 16:23:46 +0100818 crec->addr.cname.uid = target->uid;
Simon Kelley45d8a242018-07-17 21:01:14 +0100819 crec->uid = UID_NONE;
Simon Kelley611ebc52012-07-16 16:23:46 +0100820 cache_hash(crec);
821 add_hosts_cname(crec); /* handle chains */
822 }
823}
824
Simon Kelleyfd9fa482004-10-21 20:24:00 +0100825static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
Simon Kelley19c51cf2014-03-18 22:38:30 +0000826 unsigned int index, struct crec **rhash, int hashsz)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000827{
Simon Kelleye759d422012-03-16 13:18:57 +0000828 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 +0000829 int i, nameexists = 0;
Simon Kelley205fafa2012-01-11 21:31:51 +0000830 unsigned int j;
Simon Kelley9009d742008-11-14 20:04:27 +0000831
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000832 /* Remove duplicates in hosts files. */
Simon Kelley9009d742008-11-14 20:04:27 +0000833 if (lookup && (lookup->flags & F_HOSTS))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000834 {
Simon Kelley9009d742008-11-14 20:04:27 +0000835 nameexists = 1;
836 if (memcmp(&lookup->addr.addr, addr, addrlen) == 0)
837 {
838 free(cache);
839 return;
840 }
841 }
842
843 /* Ensure there is only one address -> name mapping (first one trumps)
Simon Kelley205fafa2012-01-11 21:31:51 +0000844 We do this by steam here, The entries are kept in hash chains, linked
845 by ->next (which is unused at this point) held in hash buckets in
Simon Kelley1ab62ae2012-01-12 11:33:16 +0000846 the array rhash, hashed on address. Note that rhash and the values
847 in ->next are only valid whilst reading hosts files: the buckets are
848 then freed, and the ->next pointer used for other things.
Simon Kelley205fafa2012-01-11 21:31:51 +0000849
Simon Kelley1ab62ae2012-01-12 11:33:16 +0000850 Only insert each unique address once into this hashing structure.
Simon Kelley205fafa2012-01-11 21:31:51 +0000851
852 This complexity avoids O(n^2) divergent CPU use whilst reading
Simon Kelley70d18732015-01-31 19:59:29 +0000853 large (10000 entry) hosts files.
854
855 Note that we only do this process when bulk-reading hosts files,
856 for incremental reads, rhash is NULL, and we use cache lookups
857 instead.
858 */
Simon Kelley9009d742008-11-14 20:04:27 +0000859
Simon Kelley70d18732015-01-31 19:59:29 +0000860 if (rhash)
Simon Kelley915363f2012-01-11 22:00:48 +0000861 {
Simon Kelley70d18732015-01-31 19:59:29 +0000862 /* hash address */
863 for (j = 0, i = 0; i < addrlen; i++)
864 j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
865
866 for (lookup = rhash[j]; lookup; lookup = lookup->next)
867 if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) &&
868 memcmp(&lookup->addr.addr, addr, addrlen) == 0)
869 {
870 cache->flags &= ~F_REVERSE;
871 break;
872 }
873
874 /* maintain address hash chain, insert new unique address */
875 if (!lookup)
876 {
877 cache->next = rhash[j];
878 rhash[j] = cache;
879 }
Simon Kelley915363f2012-01-11 22:00:48 +0000880 }
Simon Kelley70d18732015-01-31 19:59:29 +0000881 else
882 {
883 /* incremental read, lookup in cache */
884 lookup = cache_find_by_addr(NULL, addr, 0, cache->flags & (F_IPV4 | F_IPV6));
885 if (lookup && lookup->flags & F_HOSTS)
886 cache->flags &= ~F_REVERSE;
887 }
888
Simon Kelley9009d742008-11-14 20:04:27 +0000889 cache->uid = index;
Simon Kelley915363f2012-01-11 22:00:48 +0000890 memcpy(&cache->addr.addr, addr, addrlen);
Simon Kelley9009d742008-11-14 20:04:27 +0000891 cache_hash(cache);
892
893 /* don't need to do alias stuff for second and subsequent addresses. */
894 if (!nameexists)
Simon Kelley611ebc52012-07-16 16:23:46 +0100895 add_hosts_cname(cache);
Simon Kelley9009d742008-11-14 20:04:27 +0000896}
897
898static int eatspace(FILE *f)
899{
900 int c, nl = 0;
901
902 while (1)
903 {
904 if ((c = getc(f)) == '#')
905 while (c != '\n' && c != EOF)
906 c = getc(f);
Simon Kelley832af0b2007-01-21 20:01:28 +0000907
Simon Kelley9009d742008-11-14 20:04:27 +0000908 if (c == EOF)
909 return 1;
910
911 if (!isspace(c))
912 {
913 ungetc(c, f);
914 return nl;
915 }
916
917 if (c == '\n')
918 nl = 1;
919 }
920}
921
922static int gettok(FILE *f, char *token)
923{
924 int c, count = 0;
925
926 while (1)
927 {
928 if ((c = getc(f)) == EOF)
929 return (count == 0) ? EOF : 1;
930
931 if (isspace(c) || c == '#')
932 {
933 ungetc(c, f);
934 return eatspace(f);
935 }
936
937 if (count < (MAXDNAME - 1))
938 {
939 token[count++] = c;
940 token[count] = 0;
941 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000942 }
943}
944
Simon Kelley70d18732015-01-31 19:59:29 +0000945int read_hostsfile(char *filename, unsigned int index, int cache_size, struct crec **rhash, int hashsz)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000946{
947 FILE *f = fopen(filename, "r");
Simon Kelley9009d742008-11-14 20:04:27 +0000948 char *token = daemon->namebuff, *domain_suffix = NULL;
Simon Kelley4011c4e2006-10-28 16:26:19 +0100949 int addr_count = 0, name_count = cache_size, lineno = 0;
Simon Kelley205fafa2012-01-11 21:31:51 +0000950 unsigned short flags = 0;
951 struct all_addr addr;
952 int atnl, addrlen = 0;
Simon Kelley4011c4e2006-10-28 16:26:19 +0100953
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000954 if (!f)
955 {
Simon Kelleyf2621c72007-04-29 19:47:21 +0100956 my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
André Glüpkereddf3652016-01-12 12:54:17 +0000957 return cache_size;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000958 }
Simon Kelley9009d742008-11-14 20:04:27 +0000959
960 eatspace(f);
961
962 while ((atnl = gettok(f, token)) != EOF)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000963 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000964 lineno++;
Simon Kelley9009d742008-11-14 20:04:27 +0000965
Simon Kelley3d8df262005-08-29 12:19:27 +0100966 if (inet_pton(AF_INET, token, &addr) > 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000967 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +0000968 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000969 addrlen = INADDRSZ;
Simon Kelley9009d742008-11-14 20:04:27 +0000970 domain_suffix = get_domain(addr.addr.addr4);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000971 }
Simon Kelleye759d422012-03-16 13:18:57 +0000972#ifdef HAVE_IPV6
Simon Kelley3d8df262005-08-29 12:19:27 +0100973 else if (inet_pton(AF_INET6, token, &addr) > 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000974 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +0000975 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000976 addrlen = IN6ADDRSZ;
Simon Kelley4cb1b322012-02-06 14:30:41 +0000977 domain_suffix = get_domain6(&addr.addr.addr6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000978 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000979#endif
980 else
Simon Kelleyb8187c82005-11-26 21:46:27 +0000981 {
Simon Kelleyf2621c72007-04-29 19:47:21 +0100982 my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
Simon Kelley9009d742008-11-14 20:04:27 +0000983 while (atnl == 0)
984 atnl = gettok(f, token);
Simon Kelleyb8187c82005-11-26 21:46:27 +0000985 continue;
986 }
Simon Kelley9009d742008-11-14 20:04:27 +0000987
Simon Kelley9009d742008-11-14 20:04:27 +0000988 addr_count++;
989
990 /* rehash every 1000 names. */
Simon Kelley70d18732015-01-31 19:59:29 +0000991 if (rhash && ((name_count - cache_size) > 1000))
Simon Kelley9009d742008-11-14 20:04:27 +0000992 {
993 rehash(name_count);
994 cache_size = name_count;
995 }
996
997 while (atnl == 0)
998 {
999 struct crec *cache;
Simon Kelley1f15b812009-10-13 17:49:32 +01001000 int fqdn, nomem;
1001 char *canon;
Simon Kelley9009d742008-11-14 20:04:27 +00001002
1003 if ((atnl = gettok(f, token)) == EOF)
1004 break;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001005
Simon Kelley9009d742008-11-14 20:04:27 +00001006 fqdn = !!strchr(token, '.');
1007
Simon Kelley1f15b812009-10-13 17:49:32 +01001008 if ((canon = canonicalise(token, &nomem)))
Simon Kelley9009d742008-11-14 20:04:27 +00001009 {
1010 /* If set, add a version of the name with a default domain appended */
Simon Kelley28866e92011-02-14 20:19:14 +00001011 if (option_bool(OPT_EXPAND) && domain_suffix && !fqdn &&
Simon Kelley9009d742008-11-14 20:04:27 +00001012 (cache = whine_malloc(sizeof(struct crec) +
Simon Kelley1f15b812009-10-13 17:49:32 +01001013 strlen(canon)+2+strlen(domain_suffix)-SMALLDNAME)))
Simon Kelley9009d742008-11-14 20:04:27 +00001014 {
Simon Kelley1f15b812009-10-13 17:49:32 +01001015 strcpy(cache->name.sname, canon);
Simon Kelley9009d742008-11-14 20:04:27 +00001016 strcat(cache->name.sname, ".");
1017 strcat(cache->name.sname, domain_suffix);
Simon Kelleye759d422012-03-16 13:18:57 +00001018 cache->flags = flags;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001019 cache->ttd = daemon->local_ttl;
Simon Kelleye759d422012-03-16 13:18:57 +00001020 add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
Simon Kelley9009d742008-11-14 20:04:27 +00001021 name_count++;
1022 }
Simon Kelley1f15b812009-10-13 17:49:32 +01001023 if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon)+1-SMALLDNAME)))
Simon Kelley9009d742008-11-14 20:04:27 +00001024 {
Simon Kelley1f15b812009-10-13 17:49:32 +01001025 strcpy(cache->name.sname, canon);
Simon Kelleye759d422012-03-16 13:18:57 +00001026 cache->flags = flags;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001027 cache->ttd = daemon->local_ttl;
Simon Kelleye759d422012-03-16 13:18:57 +00001028 add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
Simon Kelley9009d742008-11-14 20:04:27 +00001029 name_count++;
1030 }
Simon Kelley1f15b812009-10-13 17:49:32 +01001031 free(canon);
1032
Simon Kelley9009d742008-11-14 20:04:27 +00001033 }
Simon Kelley1f15b812009-10-13 17:49:32 +01001034 else if (!nomem)
Simon Kelley9009d742008-11-14 20:04:27 +00001035 my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
1036 }
1037 }
1038
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001039 fclose(f);
Simon Kelley9009d742008-11-14 20:04:27 +00001040
Simon Kelley70d18732015-01-31 19:59:29 +00001041 if (rhash)
Simon Kelleyf9c86372015-02-03 21:52:48 +00001042 rehash(name_count);
1043
1044 my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
1045
Simon Kelley4011c4e2006-10-28 16:26:19 +01001046 return name_count;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001047}
1048
Simon Kelley7622fc02009-06-04 20:32:05 +01001049void cache_reload(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001050{
1051 struct crec *cache, **up, *tmp;
Simon Kelley1ab62ae2012-01-12 11:33:16 +00001052 int revhashsz, i, total_size = daemon->cachesize;
Simon Kelley7622fc02009-06-04 20:32:05 +01001053 struct hostsfile *ah;
Simon Kelleye759d422012-03-16 13:18:57 +00001054 struct host_record *hr;
1055 struct name_list *nl;
Simon Kelleyd56a6042013-10-11 14:39:03 +01001056 struct cname *a;
1057 struct interface_name *intr;
Simon Kelley0fc2f312014-01-08 10:26:58 +00001058#ifdef HAVE_DNSSEC
Simon Kelleyee415862014-02-11 11:07:22 +00001059 struct ds_config *ds;
Simon Kelley0fc2f312014-01-08 10:26:58 +00001060#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001061
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001062 daemon->metrics[METRIC_DNS_CACHE_INSERTED] = 0;
1063 daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED] = 0;
Simon Kelley59353a62004-11-21 19:34:28 +00001064
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001065 for (i=0; i<hash_size; i++)
1066 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
1067 {
Simon Kelley0fc2f312014-01-08 10:26:58 +00001068#ifdef HAVE_DNSSEC
Simon Kelley82e3f452014-01-31 21:05:48 +00001069 cache_blockdata_free(cache);
Simon Kelley0fc2f312014-01-08 10:26:58 +00001070#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001071 tmp = cache->hash_next;
Simon Kelley25439062013-11-25 21:14:51 +00001072 if (cache->flags & (F_HOSTS | F_CONFIG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001073 {
1074 *up = cache->hash_next;
1075 free(cache);
1076 }
1077 else if (!(cache->flags & F_DHCP))
1078 {
1079 *up = cache->hash_next;
1080 if (cache->flags & F_BIGNAME)
1081 {
1082 cache->name.bname->next = big_free;
1083 big_free = cache->name.bname;
1084 }
1085 cache->flags = 0;
1086 }
1087 else
1088 up = &cache->hash_next;
1089 }
1090
Simon Kelleyd56a6042013-10-11 14:39:03 +01001091 /* Add CNAMEs to interface_names to the cache */
1092 for (a = daemon->cnames; a; a = a->next)
1093 for (intr = daemon->int_names; intr; intr = intr->next)
Simon Kelleyb637d782016-12-13 16:44:11 +00001094 if (a->alias[1] != '*' &&
1095 hostname_isequal(a->target, intr->name) &&
Simon Kelley532066e2013-11-26 10:14:47 +00001096 ((cache = whine_malloc(sizeof(struct crec)))))
Simon Kelleyd56a6042013-10-11 14:39:03 +01001097 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001098 cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001099 cache->ttd = a->ttl;
Simon Kelley532066e2013-11-26 10:14:47 +00001100 cache->name.namep = a->alias;
1101 cache->addr.cname.target.int_name = intr;
Simon Kelley19c51cf2014-03-18 22:38:30 +00001102 cache->addr.cname.uid = SRC_INTERFACE;
Simon Kelley45d8a242018-07-17 21:01:14 +01001103 cache->uid = UID_NONE;
Simon Kelley532066e2013-11-26 10:14:47 +00001104 cache_hash(cache);
1105 add_hosts_cname(cache); /* handle chains */
Simon Kelleyd56a6042013-10-11 14:39:03 +01001106 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001107
1108#ifdef HAVE_DNSSEC
Simon Kelleyee415862014-02-11 11:07:22 +00001109 for (ds = daemon->ds; ds; ds = ds->next)
Simon Kelley0fc2f312014-01-08 10:26:58 +00001110 if ((cache = whine_malloc(sizeof(struct crec))) &&
Simon Kelleyee415862014-02-11 11:07:22 +00001111 (cache->addr.ds.keydata = blockdata_alloc(ds->digest, ds->digestlen)))
Simon Kelley0fc2f312014-01-08 10:26:58 +00001112 {
Simon Kelleyee415862014-02-11 11:07:22 +00001113 cache->flags = F_FORWARD | F_IMMORTAL | F_DS | F_CONFIG | F_NAMEP;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001114 cache->ttd = daemon->local_ttl;
Simon Kelleyee415862014-02-11 11:07:22 +00001115 cache->name.namep = ds->name;
1116 cache->addr.ds.keylen = ds->digestlen;
1117 cache->addr.ds.algo = ds->algo;
1118 cache->addr.ds.keytag = ds->keytag;
1119 cache->addr.ds.digest = ds->digest_type;
1120 cache->uid = ds->class;
Simon Kelley0fc2f312014-01-08 10:26:58 +00001121 cache_hash(cache);
1122 }
1123#endif
Simon Kelleyd56a6042013-10-11 14:39:03 +01001124
Simon Kelleye759d422012-03-16 13:18:57 +00001125 /* borrow the packet buffer for a temporary by-address hash */
1126 memset(daemon->packet, 0, daemon->packet_buff_sz);
1127 revhashsz = daemon->packet_buff_sz / sizeof(struct crec *);
1128 /* we overwrote the buffer... */
1129 daemon->srv_save = NULL;
1130
1131 /* Do host_records in config. */
1132 for (hr = daemon->host_records; hr; hr = hr->next)
1133 for (nl = hr->names; nl; nl = nl->next)
1134 {
1135 if (hr->addr.s_addr != 0 &&
1136 (cache = whine_malloc(sizeof(struct crec))))
1137 {
1138 cache->name.namep = nl->name;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001139 cache->ttd = hr->ttl;
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001140 cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG;
Simon Kelley19c51cf2014-03-18 22:38:30 +00001141 add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
Simon Kelleye759d422012-03-16 13:18:57 +00001142 }
1143#ifdef HAVE_IPV6
1144 if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) &&
1145 (cache = whine_malloc(sizeof(struct crec))))
1146 {
1147 cache->name.namep = nl->name;
Simon Kelleydf3d54f2016-02-24 21:03:38 +00001148 cache->ttd = hr->ttl;
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001149 cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG;
Simon Kelley19c51cf2014-03-18 22:38:30 +00001150 add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
Simon Kelleye759d422012-03-16 13:18:57 +00001151 }
1152#endif
1153 }
1154
Simon Kelley28866e92011-02-14 20:19:14 +00001155 if (option_bool(OPT_NO_HOSTS) && !daemon->addn_hosts)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001156 {
Simon Kelley5aabfc72007-08-29 11:24:47 +01001157 if (daemon->cachesize > 0)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001158 my_syslog(LOG_INFO, _("cleared cache"));
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001159 }
Simon Kelleycaeea192015-02-14 20:08:56 +00001160 else
1161 {
1162 if (!option_bool(OPT_NO_HOSTS))
1163 total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
1164
1165 daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
1166 for (ah = daemon->addn_hosts; ah; ah = ah->next)
1167 if (!(ah->flags & AH_INACTIVE))
1168 total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
1169 }
1170
Simon Kelley70d18732015-01-31 19:59:29 +00001171#ifdef HAVE_INOTIFY
1172 set_dynamic_inotify(AH_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
1173#endif
1174
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001175}
1176
Simon Kelley7622fc02009-06-04 20:32:05 +01001177#ifdef HAVE_DHCP
Simon Kelley7de060b2011-08-26 17:24:52 +01001178struct in_addr a_record_from_hosts(char *name, time_t now)
1179{
1180 struct crec *crecp = NULL;
1181 struct in_addr ret;
1182
1183 while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
1184 if (crecp->flags & F_HOSTS)
1185 return *(struct in_addr *)&crecp->addr;
1186
1187 my_syslog(MS_DHCP | LOG_WARNING, _("No IPv4 address found for %s"), name);
1188
1189 ret.s_addr = 0;
1190 return ret;
1191}
1192
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001193void cache_unhash_dhcp(void)
1194{
Simon Kelley6b010842007-02-12 20:32:07 +00001195 struct crec *cache, **up;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001196 int i;
1197
1198 for (i=0; i<hash_size; i++)
1199 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next)
1200 if (cache->flags & F_DHCP)
Simon Kelley6b010842007-02-12 20:32:07 +00001201 {
1202 *up = cache->hash_next;
1203 cache->next = dhcp_spare;
1204 dhcp_spare = cache;
1205 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001206 else
1207 up = &cache->hash_next;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001208}
1209
Simon Kelley611ebc52012-07-16 16:23:46 +01001210static void add_dhcp_cname(struct crec *target, time_t ttd)
1211{
1212 struct crec *aliasc;
1213 struct cname *a;
1214
1215 for (a = daemon->cnames; a; a = a->next)
Simon Kelleyb637d782016-12-13 16:44:11 +00001216 if (a->alias[1] != '*' &&
1217 hostname_isequal(cache_get_name(target), a->target))
Simon Kelley611ebc52012-07-16 16:23:46 +01001218 {
1219 if ((aliasc = dhcp_spare))
1220 dhcp_spare = dhcp_spare->next;
1221 else /* need new one */
1222 aliasc = whine_malloc(sizeof(struct crec));
1223
1224 if (aliasc)
1225 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001226 aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME | F_CONFIG;
Simon Kelley611ebc52012-07-16 16:23:46 +01001227 if (ttd == 0)
1228 aliasc->flags |= F_IMMORTAL;
1229 else
1230 aliasc->ttd = ttd;
1231 aliasc->name.namep = a->alias;
Simon Kelleyd56a6042013-10-11 14:39:03 +01001232 aliasc->addr.cname.target.cache = target;
Simon Kelley45d8a242018-07-17 21:01:14 +01001233 next_uid(target);
Simon Kelley611ebc52012-07-16 16:23:46 +01001234 aliasc->addr.cname.uid = target->uid;
Simon Kelley45d8a242018-07-17 21:01:14 +01001235 aliasc->uid = UID_NONE;
Simon Kelley611ebc52012-07-16 16:23:46 +01001236 cache_hash(aliasc);
1237 add_dhcp_cname(aliasc, ttd);
1238 }
1239 }
1240}
1241
Simon Kelley4cb1b322012-02-06 14:30:41 +00001242void cache_add_dhcp_entry(char *host_name, int prot,
1243 struct all_addr *host_address, time_t ttd)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001244{
Simon Kelley12d71ed2012-08-30 15:16:41 +01001245 struct crec *crec = NULL, *fail_crec = NULL;
Simon Kelley4cb1b322012-02-06 14:30:41 +00001246 unsigned short flags = F_IPV4;
Simon Kelley824af852008-02-12 20:43:05 +00001247 int in_hosts = 0;
Simon Kelley4cb1b322012-02-06 14:30:41 +00001248 size_t addrlen = sizeof(struct in_addr);
1249
1250#ifdef HAVE_IPV6
1251 if (prot == AF_INET6)
1252 {
1253 flags = F_IPV6;
1254 addrlen = sizeof(struct in6_addr);
1255 }
1256#endif
Simon Kelley9009d742008-11-14 20:04:27 +00001257
Simon Kelley12d71ed2012-08-30 15:16:41 +01001258 inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN);
1259
Simon Kelley4cb1b322012-02-06 14:30:41 +00001260 while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001261 {
Simon Kelley824af852008-02-12 20:43:05 +00001262 /* check all addresses associated with name */
Simon Kelley25439062013-11-25 21:14:51 +00001263 if (crec->flags & (F_HOSTS | F_CONFIG))
Simon Kelley1ab84e22004-01-29 16:48:35 +00001264 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001265 if (crec->flags & F_CNAME)
Simon Kelley28866e92011-02-14 20:19:14 +00001266 my_syslog(MS_DHCP | LOG_WARNING,
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001267 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
Simon Kelley4cb1b322012-02-06 14:30:41 +00001268 host_name, daemon->addrbuff);
Simon Kelley12d71ed2012-08-30 15:16:41 +01001269 else if (memcmp(&crec->addr.addr, host_address, addrlen) == 0)
1270 in_hosts = 1;
1271 else
1272 fail_crec = crec;
Simon Kelley1ab84e22004-01-29 16:48:35 +00001273 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001274 else if (!(crec->flags & F_DHCP))
Simon Kelley824af852008-02-12 20:43:05 +00001275 {
Simon Kelleyeb1fe152018-07-18 20:59:52 +01001276 cache_scan_free(host_name, NULL, 0, crec->flags & (flags | F_CNAME | F_FORWARD), NULL, NULL);
Simon Kelley824af852008-02-12 20:43:05 +00001277 /* scan_free deletes all addresses associated with name */
1278 break;
1279 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001280 }
Simon Kelley824af852008-02-12 20:43:05 +00001281
Simon Kelley12d71ed2012-08-30 15:16:41 +01001282 /* if in hosts, don't need DHCP record */
1283 if (in_hosts)
Simon Kelley824af852008-02-12 20:43:05 +00001284 return;
Simon Kelley12d71ed2012-08-30 15:16:41 +01001285
1286 /* Name in hosts, address doesn't match */
1287 if (fail_crec)
1288 {
1289 inet_ntop(prot, &fail_crec->addr.addr, daemon->namebuff, MAXDNAME);
1290 my_syslog(MS_DHCP | LOG_WARNING,
1291 _("not giving name %s to the DHCP lease of %s because "
1292 "the name exists in %s with address %s"),
1293 host_name, daemon->addrbuff,
1294 record_source(fail_crec->uid), daemon->namebuff);
1295 return;
1296 }
1297
1298 if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, flags)))
1299 {
1300 if (crec->flags & F_NEG)
1301 {
1302 flags |= F_REVERSE;
Simon Kelleyeb1fe152018-07-18 20:59:52 +01001303 cache_scan_free(NULL, (struct all_addr *)host_address, 0, flags, NULL, NULL);
Simon Kelley12d71ed2012-08-30 15:16:41 +01001304 }
1305 }
1306 else
1307 flags |= F_REVERSE;
1308
1309 if ((crec = dhcp_spare))
Simon Kelley6b010842007-02-12 20:32:07 +00001310 dhcp_spare = dhcp_spare->next;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001311 else /* need new one */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001312 crec = whine_malloc(sizeof(struct crec));
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001313
1314 if (crec) /* malloc may fail */
1315 {
Simon Kelleybce6e1b2014-01-23 22:02:19 +00001316 crec->flags = flags | F_NAMEP | F_DHCP | F_FORWARD;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001317 if (ttd == 0)
1318 crec->flags |= F_IMMORTAL;
1319 else
1320 crec->ttd = ttd;
Simon Kelley4cb1b322012-02-06 14:30:41 +00001321 crec->addr.addr = *host_address;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001322 crec->name.namep = host_name;
Simon Kelley45d8a242018-07-17 21:01:14 +01001323 crec->uid = UID_NONE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001324 cache_hash(crec);
Simon Kelley9009d742008-11-14 20:04:27 +00001325
Simon Kelley611ebc52012-07-16 16:23:46 +01001326 add_dhcp_cname(crec, ttd);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001327 }
1328}
Simon Kelley7622fc02009-06-04 20:32:05 +01001329#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001330
Kevin Darbyshire-Bryant7ac9ae12016-09-09 20:52:08 +01001331#ifndef NO_ID
Simon Kelleyfec216d2014-03-27 20:54:34 +00001332int cache_make_stat(struct txt_record *t)
1333{
1334 static char *buff = NULL;
1335 static int bufflen = 60;
1336 int len;
1337 struct server *serv, *serv1;
1338 char *p;
1339
1340 if (!buff && !(buff = whine_malloc(60)))
1341 return 0;
1342
1343 p = buff;
1344
1345 switch (t->stat)
1346 {
1347 case TXT_STAT_CACHESIZE:
1348 sprintf(buff+1, "%d", daemon->cachesize);
1349 break;
1350
1351 case TXT_STAT_INSERTS:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001352 sprintf(buff+1, "%d", daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001353 break;
1354
1355 case TXT_STAT_EVICTIONS:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001356 sprintf(buff+1, "%d", daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001357 break;
1358
1359 case TXT_STAT_MISSES:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001360 sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001361 break;
1362
1363 case TXT_STAT_HITS:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001364 sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001365 break;
1366
1367#ifdef HAVE_AUTH
1368 case TXT_STAT_AUTH:
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001369 sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
Simon Kelleyfec216d2014-03-27 20:54:34 +00001370 break;
1371#endif
1372
1373 case TXT_STAT_SERVERS:
1374 /* sum counts from different records for same server */
1375 for (serv = daemon->servers; serv; serv = serv->next)
1376 serv->flags &= ~SERV_COUNTED;
1377
1378 for (serv = daemon->servers; serv; serv = serv->next)
1379 if (!(serv->flags &
1380 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
1381 {
1382 char *new, *lenp;
1383 int port, newlen, bytes_avail, bytes_needed;
1384 unsigned int queries = 0, failed_queries = 0;
1385 for (serv1 = serv; serv1; serv1 = serv1->next)
1386 if (!(serv1->flags &
1387 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
1388 sockaddr_isequal(&serv->addr, &serv1->addr))
1389 {
1390 serv1->flags |= SERV_COUNTED;
1391 queries += serv1->queries;
1392 failed_queries += serv1->failed_queries;
1393 }
1394 port = prettyprint_addr(&serv->addr, daemon->addrbuff);
1395 lenp = p++; /* length */
Simon Kelley04b0ac02015-04-06 17:19:13 +01001396 bytes_avail = bufflen - (p - buff );
Simon Kelleyfec216d2014-03-27 20:54:34 +00001397 bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
1398 if (bytes_needed >= bytes_avail)
1399 {
1400 /* expand buffer if necessary */
1401 newlen = bytes_needed + 1 + bufflen - bytes_avail;
1402 if (!(new = whine_malloc(newlen)))
1403 return 0;
1404 memcpy(new, buff, bufflen);
1405 free(buff);
1406 p = new + (p - buff);
1407 lenp = p - 1;
1408 buff = new;
1409 bufflen = newlen;
Simon Kelley04b0ac02015-04-06 17:19:13 +01001410 bytes_avail = bufflen - (p - buff );
Simon Kelleyfec216d2014-03-27 20:54:34 +00001411 bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
1412 }
1413 *lenp = bytes_needed;
1414 p += bytes_needed;
1415 }
1416 t->txt = (unsigned char *)buff;
1417 t->len = p - buff;
1418 return 1;
1419 }
1420
1421 len = strlen(buff+1);
1422 t->txt = (unsigned char *)buff;
1423 t->len = len + 1;
1424 *buff = len;
1425 return 1;
1426}
Kevin Darbyshire-Bryant7ac9ae12016-09-09 20:52:08 +01001427#endif
Simon Kelley9009d742008-11-14 20:04:27 +00001428
Simon Kelley394ff492015-03-29 22:17:14 +01001429/* There can be names in the cache containing control chars, don't
1430 mess up logging or open security holes. */
1431static char *sanitise(char *name)
1432{
1433 unsigned char *r;
Simon Kelley794fccc2015-03-29 22:35:44 +01001434 if (name)
1435 for (r = (unsigned char *)name; *r; r++)
1436 if (!isprint((int)*r))
1437 return "<name unprintable>";
Simon Kelley394ff492015-03-29 22:17:14 +01001438
1439 return name;
1440}
1441
1442
Simon Kelley5aabfc72007-08-29 11:24:47 +01001443void dump_cache(time_t now)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001444{
Simon Kelley824af852008-02-12 20:43:05 +00001445 struct server *serv, *serv1;
Simon Kelleye7829ae2014-01-22 22:21:51 +00001446 char *t = "";
Simon Kelley824af852008-02-12 20:43:05 +00001447
1448 my_syslog(LOG_INFO, _("time %lu"), (unsigned long)now);
1449 my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001450 daemon->cachesize, daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED], daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
Simon Kelley824af852008-02-12 20:43:05 +00001451 my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001452 daemon->metrics[METRIC_DNS_QUERIES_FORWARDED], daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
Simon Kelleyb485ed92013-10-18 22:00:39 +01001453#ifdef HAVE_AUTH
Julian Kornbergeraba8bbb2018-07-21 21:55:08 +01001454 my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
Simon Kelleyb485ed92013-10-18 22:00:39 +01001455#endif
Simon Kelleyc2207682014-01-08 18:04:20 +00001456#ifdef HAVE_DNSSEC
1457 blockdata_report();
1458#endif
Simon Kelley824af852008-02-12 20:43:05 +00001459
Simon Kelley824af852008-02-12 20:43:05 +00001460 /* sum counts from different records for same server */
1461 for (serv = daemon->servers; serv; serv = serv->next)
1462 serv->flags &= ~SERV_COUNTED;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001463
Simon Kelley824af852008-02-12 20:43:05 +00001464 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley28866e92011-02-14 20:19:14 +00001465 if (!(serv->flags &
1466 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley824af852008-02-12 20:43:05 +00001467 {
1468 int port;
1469 unsigned int queries = 0, failed_queries = 0;
1470 for (serv1 = serv; serv1; serv1 = serv1->next)
Simon Kelley28866e92011-02-14 20:19:14 +00001471 if (!(serv1->flags &
1472 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
1473 sockaddr_isequal(&serv->addr, &serv1->addr))
Simon Kelley824af852008-02-12 20:43:05 +00001474 {
1475 serv1->flags |= SERV_COUNTED;
1476 queries += serv1->queries;
1477 failed_queries += serv1->failed_queries;
1478 }
Simon Kelleyc72daea2012-01-05 21:33:27 +00001479 port = prettyprint_addr(&serv->addr, daemon->addrbuff);
1480 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 +00001481 }
1482
Simon Kelley28866e92011-02-14 20:19:14 +00001483 if (option_bool(OPT_DEBUG) || option_bool(OPT_LOG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001484 {
1485 struct crec *cache ;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001486 int i;
Simon Kelleye7829ae2014-01-22 22:21:51 +00001487 my_syslog(LOG_INFO, "Host Address Flags Expires");
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001488
1489 for (i=0; i<hash_size; i++)
1490 for (cache = hash_table[i]; cache; cache = cache->hash_next)
1491 {
Simon Kelley0fc2f312014-01-08 10:26:58 +00001492 char *a = daemon->addrbuff, *p = daemon->namebuff, *n = cache_get_name(cache);
1493 *a = 0;
Simon Kelley2d33bda2014-01-24 22:37:25 +00001494 if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
Simon Kelley0fc2f312014-01-08 10:26:58 +00001495 n = "<Root>";
Simon Kelley394ff492015-03-29 22:17:14 +01001496 p += sprintf(p, "%-30.30s ", sanitise(n));
Simon Kelley0fc2f312014-01-08 10:26:58 +00001497 if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
Simon Kelley394ff492015-03-29 22:17:14 +01001498 a = sanitise(cache_get_cname_target(cache));
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001499#ifdef HAVE_DNSSEC
Simon Kelleycdbee9a2012-04-04 21:55:59 +01001500 else if (cache->flags & F_DS)
1501 {
Simon Kelley93be5b12015-12-15 12:04:40 +00001502 if (!(cache->flags & F_NEG))
Simon Kelleyb8eac192014-02-27 14:30:03 +00001503 sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
1504 cache->addr.ds.algo, cache->addr.ds.digest);
Simon Kelley51ea3ca2014-01-22 19:31:38 +00001505 }
1506 else if (cache->flags & F_DNSKEY)
Simon Kelleyb8eac192014-02-27 14:30:03 +00001507 sprintf(a, "%5u %3u %3u", cache->addr.key.keytag,
1508 cache->addr.key.algo, cache->addr.key.flags);
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001509#endif
Simon Kelley0fc2f312014-01-08 10:26:58 +00001510 else if (!(cache->flags & F_NEG) || !(cache->flags & F_FORWARD))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001511 {
Simon Kelleyc72daea2012-01-05 21:33:27 +00001512 a = daemon->addrbuff;
Simon Kelleyf2621c72007-04-29 19:47:21 +01001513 if (cache->flags & F_IPV4)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001514 inet_ntop(AF_INET, &cache->addr.addr, a, ADDRSTRLEN);
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001515#ifdef HAVE_IPV6
Simon Kelleyf2621c72007-04-29 19:47:21 +01001516 else if (cache->flags & F_IPV6)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001517 inet_ntop(AF_INET6, &cache->addr.addr, a, ADDRSTRLEN);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001518#endif
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001519 }
1520
Simon Kelleye7829ae2014-01-22 22:21:51 +00001521 if (cache->flags & F_IPV4)
1522 t = "4";
1523 else if (cache->flags & F_IPV6)
1524 t = "6";
1525 else if (cache->flags & F_CNAME)
1526 t = "C";
1527#ifdef HAVE_DNSSEC
Simon Kelleye7829ae2014-01-22 22:21:51 +00001528 else if (cache->flags & F_DS)
1529 t = "S";
1530 else if (cache->flags & F_DNSKEY)
1531 t = "K";
1532#endif
Simon Kelley32678042014-12-17 20:38:20 +00001533 p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s ", a, t,
Simon Kelleyf2621c72007-04-29 19:47:21 +01001534 cache->flags & F_FORWARD ? "F" : " ",
1535 cache->flags & F_REVERSE ? "R" : " ",
1536 cache->flags & F_IMMORTAL ? "I" : " ",
1537 cache->flags & F_DHCP ? "D" : " ",
1538 cache->flags & F_NEG ? "N" : " ",
1539 cache->flags & F_NXDOMAIN ? "X" : " ",
Simon Kelley7b4ad2e2012-04-04 14:05:35 +01001540 cache->flags & F_HOSTS ? "H" : " ",
1541 cache->flags & F_DNSSECOK ? "V" : " ");
Simon Kelley44a2a312004-03-10 20:04:35 +00001542#ifdef HAVE_BROKEN_RTC
Simon Kelleyf2621c72007-04-29 19:47:21 +01001543 p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
Simon Kelley44a2a312004-03-10 20:04:35 +00001544#else
Simon Kelleyf2621c72007-04-29 19:47:21 +01001545 p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd)));
1546 /* ctime includes trailing \n - eat it */
1547 *(p-1) = 0;
Simon Kelley44a2a312004-03-10 20:04:35 +00001548#endif
Rosen Penevcbd29e52017-06-27 22:29:51 +01001549 my_syslog(LOG_INFO, "%s", daemon->namebuff);
Simon Kelleyf2621c72007-04-29 19:47:21 +01001550 }
1551 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001552}
1553
Simon Kelley19c51cf2014-03-18 22:38:30 +00001554char *record_source(unsigned int index)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001555{
Simon Kelley7622fc02009-06-04 20:32:05 +01001556 struct hostsfile *ah;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001557
Simon Kelley19c51cf2014-03-18 22:38:30 +00001558 if (index == SRC_CONFIG)
1559 return "config";
1560 else if (index == SRC_HOSTS)
Simon Kelley7622fc02009-06-04 20:32:05 +01001561 return HOSTSFILE;
1562
1563 for (ah = daemon->addn_hosts; ah; ah = ah->next)
1564 if (ah->index == index)
1565 return ah->fname;
Simon Kelley70d18732015-01-31 19:59:29 +00001566
1567#ifdef HAVE_INOTIFY
1568 for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
1569 if (ah->index == index)
1570 return ah->fname;
1571#endif
1572
Simon Kelley7622fc02009-06-04 20:32:05 +01001573 return "<unknown>";
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001574}
Simon Kelleyc1bb8502004-08-11 18:40:17 +01001575
Simon Kelley610e7822014-02-06 14:45:17 +00001576char *querystr(char *desc, unsigned short type)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001577{
1578 unsigned int i;
Simon Kelley610e7822014-02-06 14:45:17 +00001579 int len = 10; /* strlen("type=xxxxx") */
1580 const char *types = NULL;
1581 static char *buff = NULL;
1582 static int bufflen = 0;
1583
Simon Kelley1a6bca82008-07-11 11:11:42 +01001584 for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
1585 if (typestr[i].type == type)
Simon Kelley610e7822014-02-06 14:45:17 +00001586 {
1587 types = typestr[i].name;
1588 len = strlen(types);
1589 break;
1590 }
1591
1592 len += 3; /* braces, terminator */
1593 len += strlen(desc);
1594
1595 if (!buff || bufflen < len)
1596 {
1597 if (buff)
1598 free(buff);
1599 else if (len < 20)
1600 len = 20;
1601
1602 buff = whine_malloc(len);
1603 bufflen = len;
1604 }
1605
1606 if (buff)
1607 {
1608 if (types)
1609 sprintf(buff, "%s[%s]", desc, types);
1610 else
1611 sprintf(buff, "%s[type=%d]", desc, type);
1612 }
1613
1614 return buff ? buff : "";
Simon Kelley1a6bca82008-07-11 11:11:42 +01001615}
1616
Simon Kelley28866e92011-02-14 20:19:14 +00001617void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001618{
Simon Kelleyc72daea2012-01-05 21:33:27 +00001619 char *source, *dest = daemon->addrbuff;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001620 char *verb = "is";
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001621
Simon Kelley28866e92011-02-14 20:19:14 +00001622 if (!option_bool(OPT_LOG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001623 return;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001624
Simon Kelley394ff492015-03-29 22:17:14 +01001625 name = sanitise(name);
1626
Simon Kelley5aabfc72007-08-29 11:24:47 +01001627 if (addr)
1628 {
Simon Kelley0fc2f312014-01-08 10:26:58 +00001629 if (flags & F_KEYTAG)
Simon Kelley15379ea2015-12-21 18:31:55 +00001630 sprintf(daemon->addrbuff, arg, addr->addr.log.keytag, addr->addr.log.algo, addr->addr.log.digest);
Simon Kelley07ed5852018-05-04 21:52:22 +01001631 else if (flags & F_RCODE)
1632 {
1633 unsigned int rcode = addr->addr.rcode.rcode;
1634
1635 if (rcode == SERVFAIL)
1636 dest = "SERVFAIL";
1637 else if (rcode == REFUSED)
1638 dest = "REFUSED";
1639 else if (rcode == NOTIMP)
1640 dest = "not implemented";
1641 else
1642 sprintf(daemon->addrbuff, "%u", rcode);
1643 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001644 else
1645 {
Simon Kelley5aabfc72007-08-29 11:24:47 +01001646#ifdef HAVE_IPV6
Simon Kelley0fc2f312014-01-08 10:26:58 +00001647 inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
1648 addr, daemon->addrbuff, ADDRSTRLEN);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001649#else
Simon Kelley0fc2f312014-01-08 10:26:58 +00001650 strncpy(daemon->addrbuff, inet_ntoa(addr->addr.addr4), ADDRSTRLEN);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001651#endif
Simon Kelley0fc2f312014-01-08 10:26:58 +00001652 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001653 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001654 else
1655 dest = arg;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001656
1657 if (flags & F_REVERSE)
1658 {
1659 dest = name;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001660 name = daemon->addrbuff;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001661 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001662
1663 if (flags & F_NEG)
1664 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001665 if (flags & F_NXDOMAIN)
Simon Kelley40b695c2014-02-03 17:07:51 +00001666 dest = "NXDOMAIN";
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001667 else
Simon Kelley5aabfc72007-08-29 11:24:47 +01001668 {
1669 if (flags & F_IPV4)
1670 dest = "NODATA-IPv4";
Simon Kelley824af852008-02-12 20:43:05 +00001671 else if (flags & F_IPV6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001672 dest = "NODATA-IPv6";
Simon Kelley824af852008-02-12 20:43:05 +00001673 else
1674 dest = "NODATA";
Simon Kelley5aabfc72007-08-29 11:24:47 +01001675 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001676 }
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001677 else if (flags & F_CNAME)
Simon Kelley28866e92011-02-14 20:19:14 +00001678 dest = "<CNAME>";
1679 else if (flags & F_RRNAME)
1680 dest = arg;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001681
Simon Kelley1f15b812009-10-13 17:49:32 +01001682 if (flags & F_CONFIG)
1683 source = "config";
1684 else if (flags & F_DHCP)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001685 source = "DHCP";
1686 else if (flags & F_HOSTS)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001687 source = arg;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001688 else if (flags & F_UPSTREAM)
1689 source = "reply";
Simon Kelley0fc2f312014-01-08 10:26:58 +00001690 else if (flags & F_SECSTAT)
1691 source = "validation";
Simon Kelley4f7b3042012-11-28 21:27:02 +00001692 else if (flags & F_AUTH)
1693 source = "auth";
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001694 else if (flags & F_SERVER)
1695 {
1696 source = "forwarded";
1697 verb = "to";
1698 }
1699 else if (flags & F_QUERY)
1700 {
Simon Kelley1a6bca82008-07-11 11:11:42 +01001701 source = arg;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001702 verb = "from";
1703 }
Simon Kelley0fc2f312014-01-08 10:26:58 +00001704 else if (flags & F_DNSSEC)
1705 {
1706 source = arg;
1707 verb = "to";
1708 }
Wang Jian49752b92014-03-28 20:52:47 +00001709 else if (flags & F_IPSET)
1710 {
1711 source = "ipset add";
1712 dest = name;
1713 name = arg;
1714 verb = daemon->addrbuff;
1715 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001716 else
1717 source = "cached";
1718
Simon Kelley3d8df262005-08-29 12:19:27 +01001719 if (strlen(name) == 0)
1720 name = ".";
1721
Simon Kelley25cf5e32015-01-09 15:53:03 +00001722 if (option_bool(OPT_EXTRALOG))
1723 {
Simon Kelley9f79ee42015-01-12 20:18:18 +00001724 int port = prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001725 if (flags & F_NOEXTRA)
Simon Kelley9f79ee42015-01-12 20:18:18 +00001726 my_syslog(LOG_INFO, "* %s/%u %s %s %s %s", daemon->addrbuff2, port, source, name, verb, dest);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001727 else
Simon Kelley9f79ee42015-01-12 20:18:18 +00001728 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 +00001729 }
1730 else
1731 my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001732}
1733
Simon Kelley98c098b2014-01-08 17:31:16 +00001734