]> git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/cache.c
Add --dnssec-timestamp option and facility.
[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 }
1137 else
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
1148 #ifdef HAVE_INOTIFY
1149 set_dynamic_inotify(AH_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
1150 #endif
1151
1152 }
1153
1154 #ifdef HAVE_DHCP
1155 struct in_addr a_record_from_hosts(char *name, time_t now)
1156 {
1157 struct crec *crecp = NULL;
1158 struct in_addr ret;
1159
1160 while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
1161 if (crecp->flags & F_HOSTS)
1162 return *(struct in_addr *)&crecp->addr;
1163
1164 my_syslog(MS_DHCP | LOG_WARNING, _("No IPv4 address found for %s"), name);
1165
1166 ret.s_addr = 0;
1167 return ret;
1168 }
1169
1170 void cache_unhash_dhcp(void)
1171 {
1172 struct crec *cache, **up;
1173 int i;
1174
1175 for (i=0; i<hash_size; i++)
1176 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next)
1177 if (cache->flags & F_DHCP)
1178 {
1179 *up = cache->hash_next;
1180 cache->next = dhcp_spare;
1181 dhcp_spare = cache;
1182 }
1183 else
1184 up = &cache->hash_next;
1185 }
1186
1187 static void add_dhcp_cname(struct crec *target, time_t ttd)
1188 {
1189 struct crec *aliasc;
1190 struct cname *a;
1191
1192 for (a = daemon->cnames; a; a = a->next)
1193 if (hostname_isequal(cache_get_name(target), a->target))
1194 {
1195 if ((aliasc = dhcp_spare))
1196 dhcp_spare = dhcp_spare->next;
1197 else /* need new one */
1198 aliasc = whine_malloc(sizeof(struct crec));
1199
1200 if (aliasc)
1201 {
1202 aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME | F_CONFIG;
1203 if (ttd == 0)
1204 aliasc->flags |= F_IMMORTAL;
1205 else
1206 aliasc->ttd = ttd;
1207 aliasc->name.namep = a->alias;
1208 aliasc->addr.cname.target.cache = target;
1209 aliasc->addr.cname.uid = target->uid;
1210 aliasc->uid = next_uid();
1211 cache_hash(aliasc);
1212 add_dhcp_cname(aliasc, ttd);
1213 }
1214 }
1215 }
1216
1217 void cache_add_dhcp_entry(char *host_name, int prot,
1218 struct all_addr *host_address, time_t ttd)
1219 {
1220 struct crec *crec = NULL, *fail_crec = NULL;
1221 unsigned short flags = F_IPV4;
1222 int in_hosts = 0;
1223 size_t addrlen = sizeof(struct in_addr);
1224
1225 #ifdef HAVE_IPV6
1226 if (prot == AF_INET6)
1227 {
1228 flags = F_IPV6;
1229 addrlen = sizeof(struct in6_addr);
1230 }
1231 #endif
1232
1233 inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN);
1234
1235 while ((crec = cache_find_by_name(crec, host_name, 0, flags | F_CNAME)))
1236 {
1237 /* check all addresses associated with name */
1238 if (crec->flags & (F_HOSTS | F_CONFIG))
1239 {
1240 if (crec->flags & F_CNAME)
1241 my_syslog(MS_DHCP | LOG_WARNING,
1242 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
1243 host_name, daemon->addrbuff);
1244 else if (memcmp(&crec->addr.addr, host_address, addrlen) == 0)
1245 in_hosts = 1;
1246 else
1247 fail_crec = crec;
1248 }
1249 else if (!(crec->flags & F_DHCP))
1250 {
1251 cache_scan_free(host_name, NULL, 0, crec->flags & (flags | F_CNAME | F_FORWARD));
1252 /* scan_free deletes all addresses associated with name */
1253 break;
1254 }
1255 }
1256
1257 /* if in hosts, don't need DHCP record */
1258 if (in_hosts)
1259 return;
1260
1261 /* Name in hosts, address doesn't match */
1262 if (fail_crec)
1263 {
1264 inet_ntop(prot, &fail_crec->addr.addr, daemon->namebuff, MAXDNAME);
1265 my_syslog(MS_DHCP | LOG_WARNING,
1266 _("not giving name %s to the DHCP lease of %s because "
1267 "the name exists in %s with address %s"),
1268 host_name, daemon->addrbuff,
1269 record_source(fail_crec->uid), daemon->namebuff);
1270 return;
1271 }
1272
1273 if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, flags)))
1274 {
1275 if (crec->flags & F_NEG)
1276 {
1277 flags |= F_REVERSE;
1278 cache_scan_free(NULL, (struct all_addr *)host_address, 0, flags);
1279 }
1280 }
1281 else
1282 flags |= F_REVERSE;
1283
1284 if ((crec = dhcp_spare))
1285 dhcp_spare = dhcp_spare->next;
1286 else /* need new one */
1287 crec = whine_malloc(sizeof(struct crec));
1288
1289 if (crec) /* malloc may fail */
1290 {
1291 crec->flags = flags | F_NAMEP | F_DHCP | F_FORWARD;
1292 if (ttd == 0)
1293 crec->flags |= F_IMMORTAL;
1294 else
1295 crec->ttd = ttd;
1296 crec->addr.addr = *host_address;
1297 crec->name.namep = host_name;
1298 crec->uid = next_uid();
1299 cache_hash(crec);
1300
1301 add_dhcp_cname(crec, ttd);
1302 }
1303 }
1304 #endif
1305
1306 int cache_make_stat(struct txt_record *t)
1307 {
1308 static char *buff = NULL;
1309 static int bufflen = 60;
1310 int len;
1311 struct server *serv, *serv1;
1312 char *p;
1313
1314 if (!buff && !(buff = whine_malloc(60)))
1315 return 0;
1316
1317 p = buff;
1318
1319 switch (t->stat)
1320 {
1321 case TXT_STAT_CACHESIZE:
1322 sprintf(buff+1, "%d", daemon->cachesize);
1323 break;
1324
1325 case TXT_STAT_INSERTS:
1326 sprintf(buff+1, "%d", cache_inserted);
1327 break;
1328
1329 case TXT_STAT_EVICTIONS:
1330 sprintf(buff+1, "%d", cache_live_freed);
1331 break;
1332
1333 case TXT_STAT_MISSES:
1334 sprintf(buff+1, "%u", daemon->queries_forwarded);
1335 break;
1336
1337 case TXT_STAT_HITS:
1338 sprintf(buff+1, "%u", daemon->local_answer);
1339 break;
1340
1341 #ifdef HAVE_AUTH
1342 case TXT_STAT_AUTH:
1343 sprintf(buff+1, "%u", daemon->auth_answer);
1344 break;
1345 #endif
1346
1347 case TXT_STAT_SERVERS:
1348 /* sum counts from different records for same server */
1349 for (serv = daemon->servers; serv; serv = serv->next)
1350 serv->flags &= ~SERV_COUNTED;
1351
1352 for (serv = daemon->servers; serv; serv = serv->next)
1353 if (!(serv->flags &
1354 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
1355 {
1356 char *new, *lenp;
1357 int port, newlen, bytes_avail, bytes_needed;
1358 unsigned int queries = 0, failed_queries = 0;
1359 for (serv1 = serv; serv1; serv1 = serv1->next)
1360 if (!(serv1->flags &
1361 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
1362 sockaddr_isequal(&serv->addr, &serv1->addr))
1363 {
1364 serv1->flags |= SERV_COUNTED;
1365 queries += serv1->queries;
1366 failed_queries += serv1->failed_queries;
1367 }
1368 port = prettyprint_addr(&serv->addr, daemon->addrbuff);
1369 lenp = p++; /* length */
1370 bytes_avail = (p - buff) + bufflen;
1371 bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
1372 if (bytes_needed >= bytes_avail)
1373 {
1374 /* expand buffer if necessary */
1375 newlen = bytes_needed + 1 + bufflen - bytes_avail;
1376 if (!(new = whine_malloc(newlen)))
1377 return 0;
1378 memcpy(new, buff, bufflen);
1379 free(buff);
1380 p = new + (p - buff);
1381 lenp = p - 1;
1382 buff = new;
1383 bufflen = newlen;
1384 bytes_avail = (p - buff) + bufflen;
1385 bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
1386 }
1387 *lenp = bytes_needed;
1388 p += bytes_needed;
1389 }
1390 t->txt = (unsigned char *)buff;
1391 t->len = p - buff;
1392 return 1;
1393 }
1394
1395 len = strlen(buff+1);
1396 t->txt = (unsigned char *)buff;
1397 t->len = len + 1;
1398 *buff = len;
1399 return 1;
1400 }
1401
1402 void dump_cache(time_t now)
1403 {
1404 struct server *serv, *serv1;
1405 char *t = "";
1406
1407 my_syslog(LOG_INFO, _("time %lu"), (unsigned long)now);
1408 my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
1409 daemon->cachesize, cache_live_freed, cache_inserted);
1410 my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
1411 daemon->queries_forwarded, daemon->local_answer);
1412 #ifdef HAVE_AUTH
1413 my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->auth_answer);
1414 #endif
1415 #ifdef HAVE_DNSSEC
1416 blockdata_report();
1417 #endif
1418
1419 /* sum counts from different records for same server */
1420 for (serv = daemon->servers; serv; serv = serv->next)
1421 serv->flags &= ~SERV_COUNTED;
1422
1423 for (serv = daemon->servers; serv; serv = serv->next)
1424 if (!(serv->flags &
1425 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
1426 {
1427 int port;
1428 unsigned int queries = 0, failed_queries = 0;
1429 for (serv1 = serv; serv1; serv1 = serv1->next)
1430 if (!(serv1->flags &
1431 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
1432 sockaddr_isequal(&serv->addr, &serv1->addr))
1433 {
1434 serv1->flags |= SERV_COUNTED;
1435 queries += serv1->queries;
1436 failed_queries += serv1->failed_queries;
1437 }
1438 port = prettyprint_addr(&serv->addr, daemon->addrbuff);
1439 my_syslog(LOG_INFO, _("server %s#%d: queries sent %u, retried or failed %u"), daemon->addrbuff, port, queries, failed_queries);
1440 }
1441
1442 if (option_bool(OPT_DEBUG) || option_bool(OPT_LOG))
1443 {
1444 struct crec *cache ;
1445 int i;
1446 my_syslog(LOG_INFO, "Host Address Flags Expires");
1447
1448 for (i=0; i<hash_size; i++)
1449 for (cache = hash_table[i]; cache; cache = cache->hash_next)
1450 {
1451 char *a = daemon->addrbuff, *p = daemon->namebuff, *n = cache_get_name(cache);
1452 *a = 0;
1453 if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
1454 n = "<Root>";
1455 p += sprintf(p, "%-30.30s ", n);
1456 if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
1457 a = cache_get_cname_target(cache);
1458 #ifdef HAVE_DNSSEC
1459 else if (cache->flags & F_DS)
1460 {
1461 if (cache->flags & F_DNSKEY)
1462 /* RRSIG */
1463 sprintf(a, "%5u %3u %s", cache->addr.sig.keytag,
1464 cache->addr.sig.algo, querystr("", cache->addr.sig.type_covered));
1465 else if (!(cache->flags & F_NEG))
1466 sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
1467 cache->addr.ds.algo, cache->addr.ds.digest);
1468 }
1469 else if (cache->flags & F_DNSKEY)
1470 sprintf(a, "%5u %3u %3u", cache->addr.key.keytag,
1471 cache->addr.key.algo, cache->addr.key.flags);
1472 #endif
1473 else if (!(cache->flags & F_NEG) || !(cache->flags & F_FORWARD))
1474 {
1475 a = daemon->addrbuff;
1476 if (cache->flags & F_IPV4)
1477 inet_ntop(AF_INET, &cache->addr.addr, a, ADDRSTRLEN);
1478 #ifdef HAVE_IPV6
1479 else if (cache->flags & F_IPV6)
1480 inet_ntop(AF_INET6, &cache->addr.addr, a, ADDRSTRLEN);
1481 #endif
1482 }
1483
1484 if (cache->flags & F_IPV4)
1485 t = "4";
1486 else if (cache->flags & F_IPV6)
1487 t = "6";
1488 else if (cache->flags & F_CNAME)
1489 t = "C";
1490 #ifdef HAVE_DNSSEC
1491 else if ((cache->flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY))
1492 t = "G"; /* DNSKEY and DS set -> RRISG */
1493 else if (cache->flags & F_DS)
1494 t = "S";
1495 else if (cache->flags & F_DNSKEY)
1496 t = "K";
1497 #endif
1498 p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s ", a, t,
1499 cache->flags & F_FORWARD ? "F" : " ",
1500 cache->flags & F_REVERSE ? "R" : " ",
1501 cache->flags & F_IMMORTAL ? "I" : " ",
1502 cache->flags & F_DHCP ? "D" : " ",
1503 cache->flags & F_NEG ? "N" : " ",
1504 cache->flags & F_NXDOMAIN ? "X" : " ",
1505 cache->flags & F_HOSTS ? "H" : " ",
1506 cache->flags & F_DNSSECOK ? "V" : " ");
1507 #ifdef HAVE_BROKEN_RTC
1508 p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
1509 #else
1510 p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd)));
1511 /* ctime includes trailing \n - eat it */
1512 *(p-1) = 0;
1513 #endif
1514 my_syslog(LOG_INFO, daemon->namebuff);
1515 }
1516 }
1517 }
1518
1519 char *record_source(unsigned int index)
1520 {
1521 struct hostsfile *ah;
1522
1523 if (index == SRC_CONFIG)
1524 return "config";
1525 else if (index == SRC_HOSTS)
1526 return HOSTSFILE;
1527
1528 for (ah = daemon->addn_hosts; ah; ah = ah->next)
1529 if (ah->index == index)
1530 return ah->fname;
1531
1532 #ifdef HAVE_INOTIFY
1533 for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
1534 if (ah->index == index)
1535 return ah->fname;
1536 #endif
1537
1538 return "<unknown>";
1539 }
1540
1541 char *querystr(char *desc, unsigned short type)
1542 {
1543 unsigned int i;
1544 int len = 10; /* strlen("type=xxxxx") */
1545 const char *types = NULL;
1546 static char *buff = NULL;
1547 static int bufflen = 0;
1548
1549 for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
1550 if (typestr[i].type == type)
1551 {
1552 types = typestr[i].name;
1553 len = strlen(types);
1554 break;
1555 }
1556
1557 len += 3; /* braces, terminator */
1558 len += strlen(desc);
1559
1560 if (!buff || bufflen < len)
1561 {
1562 if (buff)
1563 free(buff);
1564 else if (len < 20)
1565 len = 20;
1566
1567 buff = whine_malloc(len);
1568 bufflen = len;
1569 }
1570
1571 if (buff)
1572 {
1573 if (types)
1574 sprintf(buff, "%s[%s]", desc, types);
1575 else
1576 sprintf(buff, "%s[type=%d]", desc, type);
1577 }
1578
1579 return buff ? buff : "";
1580 }
1581
1582 void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
1583 {
1584 char *source, *dest = daemon->addrbuff;
1585 char *verb = "is";
1586
1587 if (!option_bool(OPT_LOG))
1588 return;
1589
1590 if (addr)
1591 {
1592 if (flags & F_KEYTAG)
1593 sprintf(daemon->addrbuff, arg, addr->addr.keytag);
1594 else
1595 {
1596 #ifdef HAVE_IPV6
1597 inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
1598 addr, daemon->addrbuff, ADDRSTRLEN);
1599 #else
1600 strncpy(daemon->addrbuff, inet_ntoa(addr->addr.addr4), ADDRSTRLEN);
1601 #endif
1602 }
1603 }
1604 else
1605 dest = arg;
1606
1607 if (flags & F_REVERSE)
1608 {
1609 dest = name;
1610 name = daemon->addrbuff;
1611 }
1612
1613 if (flags & F_NEG)
1614 {
1615 if (flags & F_NXDOMAIN)
1616 dest = "NXDOMAIN";
1617 else
1618 {
1619 if (flags & F_IPV4)
1620 dest = "NODATA-IPv4";
1621 else if (flags & F_IPV6)
1622 dest = "NODATA-IPv6";
1623 else
1624 dest = "NODATA";
1625 }
1626 }
1627 else if (flags & F_CNAME)
1628 dest = "<CNAME>";
1629 else if (flags & F_RRNAME)
1630 dest = arg;
1631
1632 if (flags & F_CONFIG)
1633 source = "config";
1634 else if (flags & F_DHCP)
1635 source = "DHCP";
1636 else if (flags & F_HOSTS)
1637 source = arg;
1638 else if (flags & F_UPSTREAM)
1639 source = "reply";
1640 else if (flags & F_SECSTAT)
1641 source = "validation";
1642 else if (flags & F_AUTH)
1643 source = "auth";
1644 else if (flags & F_SERVER)
1645 {
1646 source = "forwarded";
1647 verb = "to";
1648 }
1649 else if (flags & F_QUERY)
1650 {
1651 source = arg;
1652 verb = "from";
1653 }
1654 else if (flags & F_DNSSEC)
1655 {
1656 source = arg;
1657 verb = "to";
1658 }
1659 else if (flags & F_IPSET)
1660 {
1661 source = "ipset add";
1662 dest = name;
1663 name = arg;
1664 verb = daemon->addrbuff;
1665 }
1666 else
1667 source = "cached";
1668
1669 if (strlen(name) == 0)
1670 name = ".";
1671
1672 if (option_bool(OPT_EXTRALOG))
1673 {
1674 int port = prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2);
1675 if (flags & F_NOEXTRA)
1676 my_syslog(LOG_INFO, "* %s/%u %s %s %s %s", daemon->addrbuff2, port, source, name, verb, dest);
1677 else
1678 my_syslog(LOG_INFO, "%u %s/%u %s %s %s %s", daemon->log_display_id, daemon->addrbuff2, port, source, name, verb, dest);
1679 }
1680 else
1681 my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
1682 }
1683
1684