]> git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/cache.c
Extra logging for inotify code.
[people/ms/dnsmasq.git] / src / cache.c
1 /* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
2
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
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
8 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.
12
13 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/>.
15 */
16
17 #include "dnsmasq.h"
18
19 static struct crec *cache_head = NULL, *cache_tail = NULL, **hash_table = NULL;
20 #ifdef HAVE_DHCP
21 static struct crec *dhcp_spare = NULL;
22 #endif
23 static struct crec *new_chain = NULL;
24 static int cache_inserted = 0, cache_live_freed = 0, insert_error;
25 static union bigname *big_free = NULL;
26 static int bignames_left, hash_size;
27
28 /* type->string mapping: this is also used by the name-hash function as a mixing table. */
29 static 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" },
48 { 33, "SRV" },
49 { 35, "NAPTR" },
50 { 36, "KX" },
51 { 37, "CERT" },
52 { 38, "A6" },
53 { 39, "DNAME" },
54 { 41, "OPT" },
55 { 43, "DS" },
56 { 46, "RRSIG" },
57 { 47, "NSEC" },
58 { 48, "DNSKEY" },
59 { 50, "NSEC3" },
60 { 249, "TKEY" },
61 { 250, "TSIG" },
62 { 251, "IXFR" },
63 { 252, "AXFR" },
64 { 253, "MAILB" },
65 { 254, "MAILA" },
66 { 255, "ANY" }
67 };
68
69 static void cache_free(struct crec *crecp);
70 static void cache_unlink(struct crec *crecp);
71 static void cache_link(struct crec *crecp);
72 static void rehash(int size);
73 static void cache_hash(struct crec *crecp);
74
75 static unsigned int next_uid(void)
76 {
77 static unsigned int uid = 0;
78
79 uid++;
80
81 /* uid == 0 used to indicate CNAME to interface name. */
82 if (uid == SRC_INTERFACE)
83 uid++;
84
85 return uid;
86 }
87
88 void cache_init(void)
89 {
90 struct crec *crecp;
91 int i;
92
93 bignames_left = daemon->cachesize/10;
94
95 if (daemon->cachesize > 0)
96 {
97 crecp = safe_malloc(daemon->cachesize*sizeof(struct crec));
98
99 for (i=0; i < daemon->cachesize; i++, crecp++)
100 {
101 cache_link(crecp);
102 crecp->flags = 0;
103 crecp->uid = next_uid();
104 }
105 }
106
107 /* create initial hash table*/
108 rehash(daemon->cachesize);
109 }
110
111 /* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
112 but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
113 will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
114 expand the table. */
115 static void rehash(int size)
116 {
117 struct crec **new, **old, *p, *tmp;
118 int i, new_size, old_size;
119
120 /* hash_size is a power of two. */
121 for (new_size = 64; new_size < size/10; new_size = new_size << 1);
122
123 /* must succeed in getting first instance, failure later is non-fatal */
124 if (!hash_table)
125 new = safe_malloc(new_size * sizeof(struct crec *));
126 else if (new_size <= hash_size || !(new = whine_malloc(new_size * sizeof(struct crec *))))
127 return;
128
129 for(i = 0; i < new_size; i++)
130 new[i] = NULL;
131
132 old = hash_table;
133 old_size = hash_size;
134 hash_table = new;
135 hash_size = new_size;
136
137 if (old)
138 {
139 for (i = 0; i < old_size; i++)
140 for (p = old[i]; p ; p = tmp)
141 {
142 tmp = p->hash_next;
143 cache_hash(p);
144 }
145 free(old);
146 }
147 }
148
149 static struct crec **hash_bucket(char *name)
150 {
151 unsigned int c, val = 017465; /* Barker code - minimum self-correlation in cyclic shift */
152 const unsigned char *mix_tab = (const unsigned char*)typestr;
153
154 while((c = (unsigned char) *name++))
155 {
156 /* don't use tolower and friends here - they may be messed up by LOCALE */
157 if (c >= 'A' && c <= 'Z')
158 c += 'a' - 'A';
159 val = ((val << 7) | (val >> (32 - 7))) + (mix_tab[(val + c) & 0x3F] ^ c);
160 }
161
162 /* hash_size is a power of two */
163 return hash_table + ((val ^ (val >> 16)) & (hash_size - 1));
164 }
165
166 static void cache_hash(struct crec *crecp)
167 {
168 /* maintain an invariant that all entries with F_REVERSE set
169 are at the start of the hash-chain and all non-reverse
170 immortal entries are at the end of the hash-chain.
171 This allows reverse searches and garbage collection to be optimised */
172
173 struct crec **up = hash_bucket(cache_get_name(crecp));
174
175 if (!(crecp->flags & F_REVERSE))
176 {
177 while (*up && ((*up)->flags & F_REVERSE))
178 up = &((*up)->hash_next);
179
180 if (crecp->flags & F_IMMORTAL)
181 while (*up && !((*up)->flags & F_IMMORTAL))
182 up = &((*up)->hash_next);
183 }
184 crecp->hash_next = *up;
185 *up = crecp;
186 }
187
188 #ifdef HAVE_DNSSEC
189 static void cache_blockdata_free(struct crec *crecp)
190 {
191 if (crecp->flags & F_DNSKEY)
192 {
193 if (crecp->flags & F_DS)
194 blockdata_free(crecp->addr.sig.keydata);
195 else
196 blockdata_free(crecp->addr.key.keydata);
197 }
198 else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG))
199 blockdata_free(crecp->addr.ds.keydata);
200 }
201 #endif
202
203 static void cache_free(struct crec *crecp)
204 {
205 crecp->flags &= ~F_FORWARD;
206 crecp->flags &= ~F_REVERSE;
207 crecp->uid = next_uid(); /* invalidate CNAMES pointing to this. */
208
209 if (cache_tail)
210 cache_tail->next = crecp;
211 else
212 cache_head = crecp;
213 crecp->prev = cache_tail;
214 crecp->next = NULL;
215 cache_tail = crecp;
216
217 /* retrieve big name for further use. */
218 if (crecp->flags & F_BIGNAME)
219 {
220 crecp->name.bname->next = big_free;
221 big_free = crecp->name.bname;
222 crecp->flags &= ~F_BIGNAME;
223 }
224
225 #ifdef HAVE_DNSSEC
226 cache_blockdata_free(crecp);
227 #endif
228 }
229
230 /* insert a new cache entry at the head of the list (youngest entry) */
231 static void cache_link(struct crec *crecp)
232 {
233 if (cache_head) /* check needed for init code */
234 cache_head->prev = crecp;
235 crecp->next = cache_head;
236 crecp->prev = NULL;
237 cache_head = crecp;
238 if (!cache_tail)
239 cache_tail = crecp;
240 }
241
242 /* remove an arbitrary cache entry for promotion */
243 static void cache_unlink (struct crec *crecp)
244 {
245 if (crecp->prev)
246 crecp->prev->next = crecp->next;
247 else
248 cache_head = crecp->next;
249
250 if (crecp->next)
251 crecp->next->prev = crecp->prev;
252 else
253 cache_tail = crecp->prev;
254 }
255
256 char *cache_get_name(struct crec *crecp)
257 {
258 if (crecp->flags & F_BIGNAME)
259 return crecp->name.bname->name;
260 else if (crecp->flags & F_NAMEP)
261 return crecp->name.namep;
262
263 return crecp->name.sname;
264 }
265
266 char *cache_get_cname_target(struct crec *crecp)
267 {
268 if (crecp->addr.cname.uid != SRC_INTERFACE)
269 return cache_get_name(crecp->addr.cname.target.cache);
270
271 return crecp->addr.cname.target.int_name->name;
272 }
273
274
275
276 struct crec *cache_enumerate(int init)
277 {
278 static int bucket;
279 static struct crec *cache;
280
281 if (init)
282 {
283 bucket = 0;
284 cache = NULL;
285 }
286 else if (cache && cache->hash_next)
287 cache = cache->hash_next;
288 else
289 {
290 cache = NULL;
291 while (bucket < hash_size)
292 if ((cache = hash_table[bucket++]))
293 break;
294 }
295
296 return cache;
297 }
298
299 static int is_outdated_cname_pointer(struct crec *crecp)
300 {
301 if (!(crecp->flags & F_CNAME) || crecp->addr.cname.uid == SRC_INTERFACE)
302 return 0;
303
304 /* NB. record may be reused as DS or DNSKEY, where uid is
305 overloaded for something completely different */
306 if (crecp->addr.cname.target.cache &&
307 (crecp->addr.cname.target.cache->flags & (F_IPV4 | F_IPV6 | F_CNAME)) &&
308 crecp->addr.cname.uid == crecp->addr.cname.target.cache->uid)
309 return 0;
310
311 return 1;
312 }
313
314 static int is_expired(time_t now, struct crec *crecp)
315 {
316 if (crecp->flags & F_IMMORTAL)
317 return 0;
318
319 if (difftime(now, crecp->ttd) < 0)
320 return 0;
321
322 return 1;
323 }
324
325 static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags)
326 {
327 /* Scan and remove old entries.
328 If (flags & F_FORWARD) then remove any forward entries for name and any expired
329 entries but only in the same hash bucket as name.
330 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
331 entries in the whole cache.
332 If (flags == 0) remove any expired entries in the whole cache.
333
334 In the flags & F_FORWARD case, the return code is valid, and returns a non-NULL pointer
335 to a cache entry if the name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
336
337 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
338 so that when we hit an entry which isn't reverse and is immortal, we're done. */
339
340 struct crec *crecp, **up;
341
342 if (flags & F_FORWARD)
343 {
344 for (up = hash_bucket(name), crecp = *up; crecp; crecp = crecp->hash_next)
345 {
346 if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp))
347 {
348 *up = crecp->hash_next;
349 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
350 {
351 cache_unlink(crecp);
352 cache_free(crecp);
353 }
354 continue;
355 }
356
357 if ((crecp->flags & F_FORWARD) && hostname_isequal(cache_get_name(crecp), name))
358 {
359 /* Don't delete DNSSEC in favour of a CNAME, they can co-exist */
360 if ((flags & crecp->flags & (F_IPV4 | F_IPV6)) ||
361 (((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))))
362 {
363 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
364 return crecp;
365 *up = crecp->hash_next;
366 cache_unlink(crecp);
367 cache_free(crecp);
368 continue;
369 }
370
371 #ifdef HAVE_DNSSEC
372 /* Deletion has to be class-sensitive for DS, DNSKEY, RRSIG, also
373 type-covered sensitive for RRSIG */
374 if ((flags & (F_DNSKEY | F_DS)) &&
375 (flags & (F_DNSKEY | F_DS)) == (crecp->flags & (F_DNSKEY | F_DS)) &&
376 crecp->uid == addr->addr.dnssec.class &&
377 (!((flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY)) ||
378 crecp->addr.sig.type_covered == addr->addr.dnssec.type))
379 {
380 if (crecp->flags & F_CONFIG)
381 return crecp;
382 *up = crecp->hash_next;
383 cache_unlink(crecp);
384 cache_free(crecp);
385 continue;
386 }
387 #endif
388 }
389 up = &crecp->hash_next;
390 }
391 }
392 else
393 {
394 int i;
395 #ifdef HAVE_IPV6
396 int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ;
397 #else
398 int addrlen = INADDRSZ;
399 #endif
400 for (i = 0; i < hash_size; i++)
401 for (crecp = hash_table[i], up = &hash_table[i];
402 crecp && ((crecp->flags & F_REVERSE) || !(crecp->flags & F_IMMORTAL));
403 crecp = crecp->hash_next)
404 if (is_expired(now, crecp))
405 {
406 *up = crecp->hash_next;
407 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
408 {
409 cache_unlink(crecp);
410 cache_free(crecp);
411 }
412 }
413 else if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) &&
414 (flags & crecp->flags & F_REVERSE) &&
415 (flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
416 memcmp(&crecp->addr.addr, addr, addrlen) == 0)
417 {
418 *up = crecp->hash_next;
419 cache_unlink(crecp);
420 cache_free(crecp);
421 }
422 else
423 up = &crecp->hash_next;
424 }
425
426 return NULL;
427 }
428
429 /* Note: The normal calling sequence is
430 cache_start_insert
431 cache_insert * n
432 cache_end_insert
433
434 but an abort can cause the cache_end_insert to be missed
435 in which can the next cache_start_insert cleans things up. */
436
437 void cache_start_insert(void)
438 {
439 /* Free any entries which didn't get committed during the last
440 insert due to error.
441 */
442 while (new_chain)
443 {
444 struct crec *tmp = new_chain->next;
445 cache_free(new_chain);
446 new_chain = tmp;
447 }
448 new_chain = NULL;
449 insert_error = 0;
450 }
451
452 struct crec *cache_insert(char *name, struct all_addr *addr,
453 time_t now, unsigned long ttl, unsigned short flags)
454 {
455 struct crec *new;
456 union bigname *big_name = NULL;
457 int freed_all = flags & F_REVERSE;
458 int free_avail = 0;
459
460 /* Don't log DNSSEC records here, done elsewhere */
461 if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
462 {
463 log_query(flags | F_UPSTREAM, name, addr, NULL);
464 /* Don't mess with TTL for DNSSEC records. */
465 if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
466 ttl = daemon->max_cache_ttl;
467 if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl)
468 ttl = daemon->min_cache_ttl;
469 }
470
471 /* if previous insertion failed give up now. */
472 if (insert_error)
473 return NULL;
474
475 /* First remove any expired entries and entries for the name/address we
476 are currently inserting. */
477 if ((new = cache_scan_free(name, addr, now, flags)))
478 {
479 /* We're trying to insert a record over one from
480 /etc/hosts or DHCP, or other config. If the
481 existing record is for an A or AAAA and
482 the record we're trying to insert is the same,
483 just drop the insert, but don't error the whole process. */
484 if ((flags & (F_IPV4 | F_IPV6)) && (flags & F_FORWARD))
485 {
486 if ((flags & F_IPV4) && (new->flags & F_IPV4) &&
487 new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr)
488 return new;
489 #ifdef HAVE_IPV6
490 else if ((flags & F_IPV6) && (new->flags & F_IPV6) &&
491 IN6_ARE_ADDR_EQUAL(&new->addr.addr.addr.addr6, &addr->addr.addr6))
492 return new;
493 #endif
494 }
495
496 insert_error = 1;
497 return NULL;
498 }
499
500 /* Now get a cache entry from the end of the LRU list */
501 while (1) {
502 if (!(new = cache_tail)) /* no entries left - cache is too small, bail */
503 {
504 insert_error = 1;
505 return NULL;
506 }
507
508 /* End of LRU list is still in use: if we didn't scan all the hash
509 chains for expired entries do that now. If we already tried that
510 then it's time to start spilling things. */
511
512 if (new->flags & (F_FORWARD | F_REVERSE))
513 {
514 /* If free_avail set, we believe that an entry has been freed.
515 Bugs have been known to make this not true, resulting in
516 a tight loop here. If that happens, abandon the
517 insert. Once in this state, all inserts will probably fail. */
518 if (free_avail)
519 {
520 static int warned = 0;
521 if (!warned)
522 {
523 my_syslog(LOG_ERR, _("Internal error in cache."));
524 warned = 1;
525 }
526 insert_error = 1;
527 return NULL;
528 }
529
530 if (freed_all)
531 {
532 struct all_addr free_addr = new->addr.addr;;
533
534 #ifdef HAVE_DNSSEC
535 /* For DNSSEC records, addr holds class and type_covered for RRSIG */
536 if (new->flags & (F_DS | F_DNSKEY))
537 {
538 free_addr.addr.dnssec.class = new->uid;
539 if ((new->flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY))
540 free_addr.addr.dnssec.type = new->addr.sig.type_covered;
541 }
542 #endif
543
544 free_avail = 1; /* Must be free space now. */
545 cache_scan_free(cache_get_name(new), &free_addr, now, new->flags);
546 cache_live_freed++;
547 }
548 else
549 {
550 cache_scan_free(NULL, NULL, now, 0);
551 freed_all = 1;
552 }
553 continue;
554 }
555
556 /* Check if we need to and can allocate extra memory for a long name.
557 If that fails, give up now, always succeed for DNSSEC records. */
558 if (name && (strlen(name) > SMALLDNAME-1))
559 {
560 if (big_free)
561 {
562 big_name = big_free;
563 big_free = big_free->next;
564 }
565 else if ((bignames_left == 0 && !(flags & (F_DS | F_DNSKEY))) ||
566 !(big_name = (union bigname *)whine_malloc(sizeof(union bigname))))
567 {
568 insert_error = 1;
569 return NULL;
570 }
571 else if (bignames_left != 0)
572 bignames_left--;
573
574 }
575
576 /* Got the rest: finally grab entry. */
577 cache_unlink(new);
578 break;
579 }
580
581 new->flags = flags;
582 if (big_name)
583 {
584 new->name.bname = big_name;
585 new->flags |= F_BIGNAME;
586 }
587
588 if (name)
589 strcpy(cache_get_name(new), name);
590 else
591 *cache_get_name(new) = 0;
592
593 if (addr)
594 {
595 #ifdef HAVE_DNSSEC
596 if (flags & (F_DS | F_DNSKEY))
597 new->uid = addr->addr.dnssec.class;
598 else
599 #endif
600 new->addr.addr = *addr;
601 }
602
603 new->ttd = now + (time_t)ttl;
604 new->next = new_chain;
605 new_chain = new;
606
607 return new;
608 }
609
610 /* after end of insertion, commit the new entries */
611 void cache_end_insert(void)
612 {
613 if (insert_error)
614 return;
615
616 while (new_chain)
617 {
618 struct crec *tmp = new_chain->next;
619 /* drop CNAMEs which didn't find a target. */
620 if (is_outdated_cname_pointer(new_chain))
621 cache_free(new_chain);
622 else
623 {
624 cache_hash(new_chain);
625 cache_link(new_chain);
626 cache_inserted++;
627 }
628 new_chain = tmp;
629 }
630 new_chain = NULL;
631 }
632
633 struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned int prot)
634 {
635 struct crec *ans;
636 int no_rr = prot & F_NO_RR;
637
638 prot &= ~F_NO_RR;
639
640 if (crecp) /* iterating */
641 ans = crecp->next;
642 else
643 {
644 /* first search, look for relevant entries and push to top of list
645 also free anything which has expired */
646 struct crec *next, **up, **insert = NULL, **chainp = &ans;
647 unsigned short ins_flags = 0;
648
649 for (up = hash_bucket(name), crecp = *up; crecp; crecp = next)
650 {
651 next = crecp->hash_next;
652
653 if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp))
654 {
655 if ((crecp->flags & F_FORWARD) &&
656 #ifdef HAVE_DNSSEC
657 (((crecp->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) || (prot & F_NSIGMATCH)) &&
658 #endif
659 (crecp->flags & prot) &&
660 hostname_isequal(cache_get_name(crecp), name))
661 {
662 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
663 {
664 *chainp = crecp;
665 chainp = &crecp->next;
666 }
667 else
668 {
669 cache_unlink(crecp);
670 cache_link(crecp);
671 }
672
673 /* Move all but the first entry up the hash chain
674 this implements round-robin.
675 Make sure that re-ordering doesn't break the hash-chain
676 order invariants.
677 */
678 if (insert && (crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags)
679 {
680 *up = crecp->hash_next;
681 crecp->hash_next = *insert;
682 *insert = crecp;
683 insert = &crecp->hash_next;
684 }
685 else
686 {
687 if (!insert && !no_rr)
688 {
689 insert = up;
690 ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
691 }
692 up = &crecp->hash_next;
693 }
694 }
695 else
696 /* case : not expired, incorrect entry. */
697 up = &crecp->hash_next;
698 }
699 else
700 {
701 /* expired entry, free it */
702 *up = crecp->hash_next;
703 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
704 {
705 cache_unlink(crecp);
706 cache_free(crecp);
707 }
708 }
709 }
710
711 *chainp = cache_head;
712 }
713
714 if (ans &&
715 (ans->flags & F_FORWARD) &&
716 #ifdef HAVE_DNSSEC
717 (((ans->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) || (prot & F_NSIGMATCH)) &&
718 #endif
719 (ans->flags & prot) &&
720 hostname_isequal(cache_get_name(ans), name))
721 return ans;
722
723 return NULL;
724 }
725
726 struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
727 time_t now, unsigned int prot)
728 {
729 struct crec *ans;
730 #ifdef HAVE_IPV6
731 int addrlen = (prot == F_IPV6) ? IN6ADDRSZ : INADDRSZ;
732 #else
733 int addrlen = INADDRSZ;
734 #endif
735
736 if (crecp) /* iterating */
737 ans = crecp->next;
738 else
739 {
740 /* first search, look for relevant entries and push to top of list
741 also free anything which has expired. All the reverse entries are at the
742 start of the hash chain, so we can give up when we find the first
743 non-REVERSE one. */
744 int i;
745 struct crec **up, **chainp = &ans;
746
747 for (i=0; i<hash_size; i++)
748 for (crecp = hash_table[i], up = &hash_table[i];
749 crecp && (crecp->flags & F_REVERSE);
750 crecp = crecp->hash_next)
751 if (!is_expired(now, crecp))
752 {
753 if ((crecp->flags & prot) &&
754 memcmp(&crecp->addr.addr, addr, addrlen) == 0)
755 {
756 if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
757 {
758 *chainp = crecp;
759 chainp = &crecp->next;
760 }
761 else
762 {
763 cache_unlink(crecp);
764 cache_link(crecp);
765 }
766 }
767 up = &crecp->hash_next;
768 }
769 else
770 {
771 *up = crecp->hash_next;
772 if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
773 {
774 cache_unlink(crecp);
775 cache_free(crecp);
776 }
777 }
778
779 *chainp = cache_head;
780 }
781
782 if (ans &&
783 (ans->flags & F_REVERSE) &&
784 (ans->flags & prot) &&
785 memcmp(&ans->addr.addr, addr, addrlen) == 0)
786 return ans;
787
788 return NULL;
789 }
790
791 static void add_hosts_cname(struct crec *target)
792 {
793 struct crec *crec;
794 struct cname *a;
795
796 for (a = daemon->cnames; a; a = a->next)
797 if (hostname_isequal(cache_get_name(target), a->target) &&
798 (crec = whine_malloc(sizeof(struct crec))))
799 {
800 crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
801 crec->name.namep = a->alias;
802 crec->addr.cname.target.cache = target;
803 crec->addr.cname.uid = target->uid;
804 crec->uid = next_uid();
805 cache_hash(crec);
806 add_hosts_cname(crec); /* handle chains */
807 }
808 }
809
810 static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
811 unsigned int index, struct crec **rhash, int hashsz)
812 {
813 struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6));
814 int i, nameexists = 0;
815 unsigned int j;
816
817 /* Remove duplicates in hosts files. */
818 if (lookup && (lookup->flags & F_HOSTS))
819 {
820 nameexists = 1;
821 if (memcmp(&lookup->addr.addr, addr, addrlen) == 0)
822 {
823 free(cache);
824 return;
825 }
826 }
827
828 /* Ensure there is only one address -> name mapping (first one trumps)
829 We do this by steam here, The entries are kept in hash chains, linked
830 by ->next (which is unused at this point) held in hash buckets in
831 the array rhash, hashed on address. Note that rhash and the values
832 in ->next are only valid whilst reading hosts files: the buckets are
833 then freed, and the ->next pointer used for other things.
834
835 Only insert each unique address once into this hashing structure.
836
837 This complexity avoids O(n^2) divergent CPU use whilst reading
838 large (10000 entry) hosts files.
839
840 Note that we only do this process when bulk-reading hosts files,
841 for incremental reads, rhash is NULL, and we use cache lookups
842 instead.
843 */
844
845 if (rhash)
846 {
847 /* hash address */
848 for (j = 0, i = 0; i < addrlen; i++)
849 j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
850
851 for (lookup = rhash[j]; lookup; lookup = lookup->next)
852 if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) &&
853 memcmp(&lookup->addr.addr, addr, addrlen) == 0)
854 {
855 cache->flags &= ~F_REVERSE;
856 break;
857 }
858
859 /* maintain address hash chain, insert new unique address */
860 if (!lookup)
861 {
862 cache->next = rhash[j];
863 rhash[j] = cache;
864 }
865 }
866 else
867 {
868 /* incremental read, lookup in cache */
869 lookup = cache_find_by_addr(NULL, addr, 0, cache->flags & (F_IPV4 | F_IPV6));
870 if (lookup && lookup->flags & F_HOSTS)
871 cache->flags &= ~F_REVERSE;
872 }
873
874 cache->uid = index;
875 memcpy(&cache->addr.addr, addr, addrlen);
876 cache_hash(cache);
877
878 /* don't need to do alias stuff for second and subsequent addresses. */
879 if (!nameexists)
880 add_hosts_cname(cache);
881 }
882
883 static int eatspace(FILE *f)
884 {
885 int c, nl = 0;
886
887 while (1)
888 {
889 if ((c = getc(f)) == '#')
890 while (c != '\n' && c != EOF)
891 c = getc(f);
892
893 if (c == EOF)
894 return 1;
895
896 if (!isspace(c))
897 {
898 ungetc(c, f);
899 return nl;
900 }
901
902 if (c == '\n')
903 nl = 1;
904 }
905 }
906
907 static int gettok(FILE *f, char *token)
908 {
909 int c, count = 0;
910
911 while (1)
912 {
913 if ((c = getc(f)) == EOF)
914 return (count == 0) ? EOF : 1;
915
916 if (isspace(c) || c == '#')
917 {
918 ungetc(c, f);
919 return eatspace(f);
920 }
921
922 if (count < (MAXDNAME - 1))
923 {
924 token[count++] = c;
925 token[count] = 0;
926 }
927 }
928 }
929
930 int read_hostsfile(char *filename, unsigned int index, int cache_size, struct crec **rhash, int hashsz)
931 {
932 FILE *f = fopen(filename, "r");
933 char *token = daemon->namebuff, *domain_suffix = NULL;
934 int addr_count = 0, name_count = cache_size, lineno = 0;
935 unsigned short flags = 0;
936 struct all_addr addr;
937 int atnl, addrlen = 0;
938
939 if (!f)
940 {
941 my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
942 return 0;
943 }
944
945 eatspace(f);
946
947 while ((atnl = gettok(f, token)) != EOF)
948 {
949 lineno++;
950
951 if (inet_pton(AF_INET, token, &addr) > 0)
952 {
953 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
954 addrlen = INADDRSZ;
955 domain_suffix = get_domain(addr.addr.addr4);
956 }
957 #ifdef HAVE_IPV6
958 else if (inet_pton(AF_INET6, token, &addr) > 0)
959 {
960 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
961 addrlen = IN6ADDRSZ;
962 domain_suffix = get_domain6(&addr.addr.addr6);
963 }
964 #endif
965 else
966 {
967 my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
968 while (atnl == 0)
969 atnl = gettok(f, token);
970 continue;
971 }
972
973 addr_count++;
974
975 /* rehash every 1000 names. */
976 if (rhash && ((name_count - cache_size) > 1000))
977 {
978 rehash(name_count);
979 cache_size = name_count;
980 }
981
982 while (atnl == 0)
983 {
984 struct crec *cache;
985 int fqdn, nomem;
986 char *canon;
987
988 if ((atnl = gettok(f, token)) == EOF)
989 break;
990
991 fqdn = !!strchr(token, '.');
992
993 if ((canon = canonicalise(token, &nomem)))
994 {
995 /* If set, add a version of the name with a default domain appended */
996 if (option_bool(OPT_EXPAND) && domain_suffix && !fqdn &&
997 (cache = whine_malloc(sizeof(struct crec) +
998 strlen(canon)+2+strlen(domain_suffix)-SMALLDNAME)))
999 {
1000 strcpy(cache->name.sname, canon);
1001 strcat(cache->name.sname, ".");
1002 strcat(cache->name.sname, domain_suffix);
1003 cache->flags = flags;
1004 add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
1005 name_count++;
1006 }
1007 if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon)+1-SMALLDNAME)))
1008 {
1009 strcpy(cache->name.sname, canon);
1010 cache->flags = flags;
1011 add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
1012 name_count++;
1013 }
1014 free(canon);
1015
1016 }
1017 else if (!nomem)
1018 my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
1019 }
1020 }
1021
1022 fclose(f);
1023
1024 if (rhash)
1025 rehash(name_count);
1026
1027 my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
1028
1029 return name_count;
1030 }
1031
1032 void cache_reload(void)
1033 {
1034 struct crec *cache, **up, *tmp;
1035 int revhashsz, i, total_size = daemon->cachesize;
1036 struct hostsfile *ah;
1037 struct host_record *hr;
1038 struct name_list *nl;
1039 struct cname *a;
1040 struct interface_name *intr;
1041 #ifdef HAVE_DNSSEC
1042 struct ds_config *ds;
1043 #endif
1044
1045 cache_inserted = cache_live_freed = 0;
1046
1047 for (i=0; i<hash_size; i++)
1048 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
1049 {
1050 #ifdef HAVE_DNSSEC
1051 cache_blockdata_free(cache);
1052 #endif
1053 tmp = cache->hash_next;
1054 if (cache->flags & (F_HOSTS | F_CONFIG))
1055 {
1056 *up = cache->hash_next;
1057 free(cache);
1058 }
1059 else if (!(cache->flags & F_DHCP))
1060 {
1061 *up = cache->hash_next;
1062 if (cache->flags & F_BIGNAME)
1063 {
1064 cache->name.bname->next = big_free;
1065 big_free = cache->name.bname;
1066 }
1067 cache->flags = 0;
1068 }
1069 else
1070 up = &cache->hash_next;
1071 }
1072
1073 /* Add CNAMEs to interface_names to the cache */
1074 for (a = daemon->cnames; a; a = a->next)
1075 for (intr = daemon->int_names; intr; intr = intr->next)
1076 if (hostname_isequal(a->target, intr->name) &&
1077 ((cache = whine_malloc(sizeof(struct crec)))))
1078 {
1079 cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
1080 cache->name.namep = a->alias;
1081 cache->addr.cname.target.int_name = intr;
1082 cache->addr.cname.uid = SRC_INTERFACE;
1083 cache->uid = next_uid();
1084 cache_hash(cache);
1085 add_hosts_cname(cache); /* handle chains */
1086 }
1087
1088 #ifdef HAVE_DNSSEC
1089 for (ds = daemon->ds; ds; ds = ds->next)
1090 if ((cache = whine_malloc(sizeof(struct crec))) &&
1091 (cache->addr.ds.keydata = blockdata_alloc(ds->digest, ds->digestlen)))
1092 {
1093 cache->flags = F_FORWARD | F_IMMORTAL | F_DS | F_CONFIG | F_NAMEP;
1094 cache->name.namep = ds->name;
1095 cache->addr.ds.keylen = ds->digestlen;
1096 cache->addr.ds.algo = ds->algo;
1097 cache->addr.ds.keytag = ds->keytag;
1098 cache->addr.ds.digest = ds->digest_type;
1099 cache->uid = ds->class;
1100 cache_hash(cache);
1101 }
1102 #endif
1103
1104 /* borrow the packet buffer for a temporary by-address hash */
1105 memset(daemon->packet, 0, daemon->packet_buff_sz);
1106 revhashsz = daemon->packet_buff_sz / sizeof(struct crec *);
1107 /* we overwrote the buffer... */
1108 daemon->srv_save = NULL;
1109
1110 /* Do host_records in config. */
1111 for (hr = daemon->host_records; hr; hr = hr->next)
1112 for (nl = hr->names; nl; nl = nl->next)
1113 {
1114 if (hr->addr.s_addr != 0 &&
1115 (cache = whine_malloc(sizeof(struct crec))))
1116 {
1117 cache->name.namep = nl->name;
1118 cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG;
1119 add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
1120 }
1121 #ifdef HAVE_IPV6
1122 if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) &&
1123 (cache = whine_malloc(sizeof(struct crec))))
1124 {
1125 cache->name.namep = nl->name;
1126 cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG;
1127 add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
1128 }
1129 #endif
1130 }
1131
1132 if (option_bool(OPT_NO_HOSTS) && !daemon->addn_hosts)
1133 {
1134 if (daemon->cachesize > 0)
1135 my_syslog(LOG_INFO, _("cleared cache"));
1136 return;
1137 }
1138
1139 if (!option_bool(OPT_NO_HOSTS))
1140 total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
1141
1142 daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
1143 for (ah = daemon->addn_hosts; ah; ah = ah->next)
1144 if (!(ah->flags & AH_INACTIVE))
1145 total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
1146
1147 #ifdef HAVE_INOTIFY
1148 set_dynamic_inotify(AH_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
1149 #endif
1150
1151 }
1152
1153 #ifdef HAVE_DHCP
1154 struct in_addr a_record_from_hosts(char *name, time_t now)
1155 {
1156 struct crec *crecp = NULL;
1157 struct in_addr ret;
1158
1159 while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
1160 if (crecp->flags & F_HOSTS)
1161 return *(struct in_addr *)&crecp->addr;
1162
1163 my_syslog(MS_DHCP | LOG_WARNING, _("No IPv4 address found for %s"), name);
1164
1165 ret.s_addr = 0;
1166 return ret;
1167 }
1168
1169 void cache_unhash_dhcp(void)
1170 {
1171 struct crec *cache, **up;
1172 int i;
1173
1174 for (i=0; i<hash_size; i++)
1175 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next)
1176 if (cache->flags & F_DHCP)
1177 {
1178 *up = cache->hash_next;
1179 cache->next = dhcp_spare;
1180 dhcp_spare = cache;
1181 }
1182 else
1183 up = &cache->hash_next;
1184 }
1185
1186 static void add_dhcp_cname(struct crec *target, time_t ttd)
1187 {
1188 struct crec *aliasc;
1189 struct cname *a;
1190
1191 for (a = daemon->cnames; a; a = a->next)
1192 if (hostname_isequal(cache_get_name(target), a->target))
1193 {
1194 if ((aliasc = dhcp_spare))
1195 dhcp_spare = dhcp_spare->next;
1196 else /* need new one */
1197 aliasc = whine_malloc(sizeof(struct crec));
1198
1199 if (aliasc)
1200 {
1201 aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME | F_CONFIG;
1202 if (ttd == 0)
1203 aliasc->flags |= F_IMMORTAL;
1204 else
1205 aliasc->ttd = ttd;
1206 aliasc->name.namep = a->alias;
1207 aliasc->addr.cname.target.cache = target;
1208 aliasc->addr.cname.uid = target->uid;
1209 aliasc->uid = next_uid();
1210 cache_hash(aliasc);
1211 add_dhcp_cname(aliasc, ttd);
1212 }
1213 }
1214 }
1215
1216 void cache_add_dhcp_entry(char *host_name, int prot,
1217 struct all_addr *host_address, time_t ttd)
1218 {
1219 struct crec *crec = NULL, *fail_crec = NULL;
1220 unsigned short flags = F_IPV4;
1221 int in_hosts = 0;
1222 size_t addrlen = sizeof(struct in_addr);
1223
1224 #ifdef HAVE_IPV6
1225 if (prot == AF_INET6)
1226 {
1227 flags = F_IPV6;
1228 addrlen = sizeof(struct in6_addr);
1229 }
1230 #endif
1231
1232 inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN);
1233
1234 while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
1235 {
1236 /* check all addresses associated with name */
1237 if (crec->flags & (F_HOSTS | F_CONFIG))
1238 {
1239 if (crec->flags & F_CNAME)
1240 my_syslog(MS_DHCP | LOG_WARNING,
1241 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
1242 host_name, daemon->addrbuff);
1243 else if (memcmp(&crec->addr.addr, host_address, addrlen) == 0)
1244 in_hosts = 1;
1245 else
1246 fail_crec = crec;
1247 }
1248 else if (!(crec->flags & F_DHCP))
1249 {
1250 cache_scan_free(host_name, NULL, 0, crec->flags & (flags | F_CNAME | F_FORWARD));
1251 /* scan_free deletes all addresses associated with name */
1252 break;
1253 }
1254 }
1255
1256 /* if in hosts, don't need DHCP record */
1257 if (in_hosts)
1258 return;
1259
1260 /* Name in hosts, address doesn't match */
1261 if (fail_crec)
1262 {
1263 inet_ntop(prot, &fail_crec->addr.addr, daemon->namebuff, MAXDNAME);
1264 my_syslog(MS_DHCP | LOG_WARNING,
1265 _("not giving name %s to the DHCP lease of %s because "
1266 "the name exists in %s with address %s"),
1267 host_name, daemon->addrbuff,
1268 record_source(fail_crec->uid), daemon->namebuff);
1269 return;
1270 }
1271
1272 if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, flags)))
1273 {
1274 if (crec->flags & F_NEG)
1275 {
1276 flags |= F_REVERSE;
1277 cache_scan_free(NULL, (struct all_addr *)host_address, 0, flags);
1278 }
1279 }
1280 else
1281 flags |= F_REVERSE;
1282
1283 if ((crec = dhcp_spare))
1284 dhcp_spare = dhcp_spare->next;
1285 else /* need new one */
1286 crec = whine_malloc(sizeof(struct crec));
1287
1288 if (crec) /* malloc may fail */
1289 {
1290 crec->flags = flags | F_NAMEP | F_DHCP | F_FORWARD;
1291 if (ttd == 0)
1292 crec->flags |= F_IMMORTAL;
1293 else
1294 crec->ttd = ttd;
1295 crec->addr.addr = *host_address;
1296 crec->name.namep = host_name;
1297 crec->uid = next_uid();
1298 cache_hash(crec);
1299
1300 add_dhcp_cname(crec, ttd);
1301 }
1302 }
1303 #endif
1304
1305 int cache_make_stat(struct txt_record *t)
1306 {
1307 static char *buff = NULL;
1308 static int bufflen = 60;
1309 int len;
1310 struct server *serv, *serv1;
1311 char *p;
1312
1313 if (!buff && !(buff = whine_malloc(60)))
1314 return 0;
1315
1316 p = buff;
1317
1318 switch (t->stat)
1319 {
1320 case TXT_STAT_CACHESIZE:
1321 sprintf(buff+1, "%d", daemon->cachesize);
1322 break;
1323
1324 case TXT_STAT_INSERTS:
1325 sprintf(buff+1, "%d", cache_inserted);
1326 break;
1327
1328 case TXT_STAT_EVICTIONS:
1329 sprintf(buff+1, "%d", cache_live_freed);
1330 break;
1331
1332 case TXT_STAT_MISSES:
1333 sprintf(buff+1, "%u", daemon->queries_forwarded);
1334 break;
1335
1336 case TXT_STAT_HITS:
1337 sprintf(buff+1, "%u", daemon->local_answer);
1338 break;
1339
1340 #ifdef HAVE_AUTH
1341 case TXT_STAT_AUTH:
1342 sprintf(buff+1, "%u", daemon->auth_answer);
1343 break;
1344 #endif
1345
1346 case TXT_STAT_SERVERS:
1347 /* sum counts from different records for same server */
1348 for (serv = daemon->servers; serv; serv = serv->next)
1349 serv->flags &= ~SERV_COUNTED;
1350
1351 for (serv = daemon->servers; serv; serv = serv->next)
1352 if (!(serv->flags &
1353 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
1354 {
1355 char *new, *lenp;
1356 int port, newlen, bytes_avail, bytes_needed;
1357 unsigned int queries = 0, failed_queries = 0;
1358 for (serv1 = serv; serv1; serv1 = serv1->next)
1359 if (!(serv1->flags &
1360 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
1361 sockaddr_isequal(&serv->addr, &serv1->addr))
1362 {
1363 serv1->flags |= SERV_COUNTED;
1364 queries += serv1->queries;
1365 failed_queries += serv1->failed_queries;
1366 }
1367 port = prettyprint_addr(&serv->addr, daemon->addrbuff);
1368 lenp = p++; /* length */
1369 bytes_avail = (p - buff) + bufflen;
1370 bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
1371 if (bytes_needed >= bytes_avail)
1372 {
1373 /* expand buffer if necessary */
1374 newlen = bytes_needed + 1 + bufflen - bytes_avail;
1375 if (!(new = whine_malloc(newlen)))
1376 return 0;
1377 memcpy(new, buff, bufflen);
1378 free(buff);
1379 p = new + (p - buff);
1380 lenp = p - 1;
1381 buff = new;
1382 bufflen = newlen;
1383 bytes_avail = (p - buff) + bufflen;
1384 bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
1385 }
1386 *lenp = bytes_needed;
1387 p += bytes_needed;
1388 }
1389 t->txt = (unsigned char *)buff;
1390 t->len = p - buff;
1391 return 1;
1392 }
1393
1394 len = strlen(buff+1);
1395 t->txt = (unsigned char *)buff;
1396 t->len = len + 1;
1397 *buff = len;
1398 return 1;
1399 }
1400
1401 void dump_cache(time_t now)
1402 {
1403 struct server *serv, *serv1;
1404 char *t = "";
1405
1406 my_syslog(LOG_INFO, _("time %lu"), (unsigned long)now);
1407 my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
1408 daemon->cachesize, cache_live_freed, cache_inserted);
1409 my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
1410 daemon->queries_forwarded, daemon->local_answer);
1411 #ifdef HAVE_AUTH
1412 my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->auth_answer);
1413 #endif
1414 #ifdef HAVE_DNSSEC
1415 blockdata_report();
1416 #endif
1417
1418 /* sum counts from different records for same server */
1419 for (serv = daemon->servers; serv; serv = serv->next)
1420 serv->flags &= ~SERV_COUNTED;
1421
1422 for (serv = daemon->servers; serv; serv = serv->next)
1423 if (!(serv->flags &
1424 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
1425 {
1426 int port;
1427 unsigned int queries = 0, failed_queries = 0;
1428 for (serv1 = serv; serv1; serv1 = serv1->next)
1429 if (!(serv1->flags &
1430 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
1431 sockaddr_isequal(&serv->addr, &serv1->addr))
1432 {
1433 serv1->flags |= SERV_COUNTED;
1434 queries += serv1->queries;
1435 failed_queries += serv1->failed_queries;
1436 }
1437 port = prettyprint_addr(&serv->addr, daemon->addrbuff);
1438 my_syslog(LOG_INFO, _("server %s#%d: queries sent %u, retried or failed %u"), daemon->addrbuff, port, queries, failed_queries);
1439 }
1440
1441 if (option_bool(OPT_DEBUG) || option_bool(OPT_LOG))
1442 {
1443 struct crec *cache ;
1444 int i;
1445 my_syslog(LOG_INFO, "Host Address Flags Expires");
1446
1447 for (i=0; i<hash_size; i++)
1448 for (cache = hash_table[i]; cache; cache = cache->hash_next)
1449 {
1450 char *a = daemon->addrbuff, *p = daemon->namebuff, *n = cache_get_name(cache);
1451 *a = 0;
1452 if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
1453 n = "<Root>";
1454 p += sprintf(p, "%-30.30s ", n);
1455 if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
1456 a = cache_get_cname_target(cache);
1457 #ifdef HAVE_DNSSEC
1458 else if (cache->flags & F_DS)
1459 {
1460 if (cache->flags & F_DNSKEY)
1461 /* RRSIG */
1462 sprintf(a, "%5u %3u %s", cache->addr.sig.keytag,
1463 cache->addr.sig.algo, querystr("", cache->addr.sig.type_covered));
1464 else if (!(cache->flags & F_NEG))
1465 sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
1466 cache->addr.ds.algo, cache->addr.ds.digest);
1467 }
1468 else if (cache->flags & F_DNSKEY)
1469 sprintf(a, "%5u %3u %3u", cache->addr.key.keytag,
1470 cache->addr.key.algo, cache->addr.key.flags);
1471 #endif
1472 else if (!(cache->flags & F_NEG) || !(cache->flags & F_FORWARD))
1473 {
1474 a = daemon->addrbuff;
1475 if (cache->flags & F_IPV4)
1476 inet_ntop(AF_INET, &cache->addr.addr, a, ADDRSTRLEN);
1477 #ifdef HAVE_IPV6
1478 else if (cache->flags & F_IPV6)
1479 inet_ntop(AF_INET6, &cache->addr.addr, a, ADDRSTRLEN);
1480 #endif
1481 }
1482
1483 if (cache->flags & F_IPV4)
1484 t = "4";
1485 else if (cache->flags & F_IPV6)
1486 t = "6";
1487 else if (cache->flags & F_CNAME)
1488 t = "C";
1489 #ifdef HAVE_DNSSEC
1490 else if ((cache->flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY))
1491 t = "G"; /* DNSKEY and DS set -> RRISG */
1492 else if (cache->flags & F_DS)
1493 t = "S";
1494 else if (cache->flags & F_DNSKEY)
1495 t = "K";
1496 #endif
1497 p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s ", a, t,
1498 cache->flags & F_FORWARD ? "F" : " ",
1499 cache->flags & F_REVERSE ? "R" : " ",
1500 cache->flags & F_IMMORTAL ? "I" : " ",
1501 cache->flags & F_DHCP ? "D" : " ",
1502 cache->flags & F_NEG ? "N" : " ",
1503 cache->flags & F_NXDOMAIN ? "X" : " ",
1504 cache->flags & F_HOSTS ? "H" : " ",
1505 cache->flags & F_DNSSECOK ? "V" : " ");
1506 #ifdef HAVE_BROKEN_RTC
1507 p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
1508 #else
1509 p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd)));
1510 /* ctime includes trailing \n - eat it */
1511 *(p-1) = 0;
1512 #endif
1513 my_syslog(LOG_INFO, daemon->namebuff);
1514 }
1515 }
1516 }
1517
1518 char *record_source(unsigned int index)
1519 {
1520 struct hostsfile *ah;
1521
1522 if (index == SRC_CONFIG)
1523 return "config";
1524 else if (index == SRC_HOSTS)
1525 return HOSTSFILE;
1526
1527 for (ah = daemon->addn_hosts; ah; ah = ah->next)
1528 if (ah->index == index)
1529 return ah->fname;
1530
1531 #ifdef HAVE_INOTIFY
1532 for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
1533 if (ah->index == index)
1534 return ah->fname;
1535 #endif
1536
1537 return "<unknown>";
1538 }
1539
1540 char *querystr(char *desc, unsigned short type)
1541 {
1542 unsigned int i;
1543 int len = 10; /* strlen("type=xxxxx") */
1544 const char *types = NULL;
1545 static char *buff = NULL;
1546 static int bufflen = 0;
1547
1548 for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
1549 if (typestr[i].type == type)
1550 {
1551 types = typestr[i].name;
1552 len = strlen(types);
1553 break;
1554 }
1555
1556 len += 3; /* braces, terminator */
1557 len += strlen(desc);
1558
1559 if (!buff || bufflen < len)
1560 {
1561 if (buff)
1562 free(buff);
1563 else if (len < 20)
1564 len = 20;
1565
1566 buff = whine_malloc(len);
1567 bufflen = len;
1568 }
1569
1570 if (buff)
1571 {
1572 if (types)
1573 sprintf(buff, "%s[%s]", desc, types);
1574 else
1575 sprintf(buff, "%s[type=%d]", desc, type);
1576 }
1577
1578 return buff ? buff : "";
1579 }
1580
1581 void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
1582 {
1583 char *source, *dest = daemon->addrbuff;
1584 char *verb = "is";
1585
1586 if (!option_bool(OPT_LOG))
1587 return;
1588
1589 if (addr)
1590 {
1591 if (flags & F_KEYTAG)
1592 sprintf(daemon->addrbuff, arg, addr->addr.keytag);
1593 else
1594 {
1595 #ifdef HAVE_IPV6
1596 inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
1597 addr, daemon->addrbuff, ADDRSTRLEN);
1598 #else
1599 strncpy(daemon->addrbuff, inet_ntoa(addr->addr.addr4), ADDRSTRLEN);
1600 #endif
1601 }
1602 }
1603 else
1604 dest = arg;
1605
1606 if (flags & F_REVERSE)
1607 {
1608 dest = name;
1609 name = daemon->addrbuff;
1610 }
1611
1612 if (flags & F_NEG)
1613 {
1614 if (flags & F_NXDOMAIN)
1615 dest = "NXDOMAIN";
1616 else
1617 {
1618 if (flags & F_IPV4)
1619 dest = "NODATA-IPv4";
1620 else if (flags & F_IPV6)
1621 dest = "NODATA-IPv6";
1622 else
1623 dest = "NODATA";
1624 }
1625 }
1626 else if (flags & F_CNAME)
1627 dest = "<CNAME>";
1628 else if (flags & F_RRNAME)
1629 dest = arg;
1630
1631 if (flags & F_CONFIG)
1632 source = "config";
1633 else if (flags & F_DHCP)
1634 source = "DHCP";
1635 else if (flags & F_HOSTS)
1636 source = arg;
1637 else if (flags & F_UPSTREAM)
1638 source = "reply";
1639 else if (flags & F_SECSTAT)
1640 source = "validation";
1641 else if (flags & F_AUTH)
1642 source = "auth";
1643 else if (flags & F_SERVER)
1644 {
1645 source = "forwarded";
1646 verb = "to";
1647 }
1648 else if (flags & F_QUERY)
1649 {
1650 source = arg;
1651 verb = "from";
1652 }
1653 else if (flags & F_DNSSEC)
1654 {
1655 source = arg;
1656 verb = "to";
1657 }
1658 else if (flags & F_IPSET)
1659 {
1660 source = "ipset add";
1661 dest = name;
1662 name = arg;
1663 verb = daemon->addrbuff;
1664 }
1665 else
1666 source = "cached";
1667
1668 if (strlen(name) == 0)
1669 name = ".";
1670
1671 if (option_bool(OPT_EXTRALOG))
1672 {
1673 int port = prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2);
1674 if (flags & F_NOEXTRA)
1675 my_syslog(LOG_INFO, "* %s/%u %s %s %s %s", daemon->addrbuff2, port, source, name, verb, dest);
1676 else
1677 my_syslog(LOG_INFO, "%u %s/%u %s %s %s %s", daemon->log_display_id, daemon->addrbuff2, port, source, name, verb, dest);
1678 }
1679 else
1680 my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
1681 }
1682
1683