]> git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/cache.c
Accumulated 2.60 changes going into git
[people/ms/dnsmasq.git] / src / cache.c
1 /* dnsmasq is Copyright (c) 2000-2011 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 static int uid = 0;
28
29 /* type->string mapping: this is also used by the name-hash function as a mixing table. */
30 static const struct {
31 unsigned int type;
32 const char * const name;
33 } typestr[] = {
34 { 1, "A" },
35 { 2, "NS" },
36 { 5, "CNAME" },
37 { 6, "SOA" },
38 { 10, "NULL" },
39 { 11, "WKS" },
40 { 12, "PTR" },
41 { 13, "HINFO" },
42 { 15, "MX" },
43 { 16, "TXT" },
44 { 22, "NSAP" },
45 { 23, "NSAP_PTR" },
46 { 24, "SIG" },
47 { 25, "KEY" },
48 { 28, "AAAA" },
49 { 33, "SRV" },
50 { 35, "NAPTR" },
51 { 36, "KX" },
52 { 37, "CERT" },
53 { 38, "A6" },
54 { 39, "DNAME" },
55 { 41, "OPT" },
56 { 48, "DNSKEY" },
57 { 249, "TKEY" },
58 { 250, "TSIG" },
59 { 251, "IXFR" },
60 { 252, "AXFR" },
61 { 253, "MAILB" },
62 { 254, "MAILA" },
63 { 255, "ANY" }
64 };
65
66 static void cache_free(struct crec *crecp);
67 static void cache_unlink(struct crec *crecp);
68 static void cache_link(struct crec *crecp);
69 static void rehash(int size);
70 static void cache_hash(struct crec *crecp);
71
72 void cache_init(void)
73 {
74 struct crec *crecp;
75 int i;
76
77 bignames_left = daemon->cachesize/10;
78
79 if (daemon->cachesize > 0)
80 {
81 crecp = safe_malloc(daemon->cachesize*sizeof(struct crec));
82
83 for (i=0; i < daemon->cachesize; i++, crecp++)
84 {
85 cache_link(crecp);
86 crecp->flags = 0;
87 crecp->uid = uid++;
88 }
89 }
90
91 /* create initial hash table*/
92 rehash(daemon->cachesize);
93 }
94
95 /* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
96 but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
97 will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
98 expand the table. */
99 static void rehash(int size)
100 {
101 struct crec **new, **old, *p, *tmp;
102 int i, new_size, old_size;
103
104 /* hash_size is a power of two. */
105 for (new_size = 64; new_size < size/10; new_size = new_size << 1);
106
107 /* must succeed in getting first instance, failure later is non-fatal */
108 if (!hash_table)
109 new = safe_malloc(new_size * sizeof(struct crec *));
110 else if (new_size <= hash_size || !(new = whine_malloc(new_size * sizeof(struct crec *))))
111 return;
112
113 for(i = 0; i < new_size; i++)
114 new[i] = NULL;
115
116 old = hash_table;
117 old_size = hash_size;
118 hash_table = new;
119 hash_size = new_size;
120
121 if (old)
122 {
123 for (i = 0; i < old_size; i++)
124 for (p = old[i]; p ; p = tmp)
125 {
126 tmp = p->hash_next;
127 cache_hash(p);
128 }
129 free(old);
130 }
131 }
132
133 static struct crec **hash_bucket(char *name)
134 {
135 unsigned int c, val = 017465; /* Barker code - minimum self-correlation in cyclic shift */
136 const unsigned char *mix_tab = (const unsigned char*)typestr;
137
138 while((c = (unsigned char) *name++))
139 {
140 /* don't use tolower and friends here - they may be messed up by LOCALE */
141 if (c >= 'A' && c <= 'Z')
142 c += 'a' - 'A';
143 val = ((val << 7) | (val >> (32 - 7))) + (mix_tab[(val + c) & 0x3F] ^ c);
144 }
145
146 /* hash_size is a power of two */
147 return hash_table + ((val ^ (val >> 16)) & (hash_size - 1));
148 }
149
150 static void cache_hash(struct crec *crecp)
151 {
152 /* maintain an invariant that all entries with F_REVERSE set
153 are at the start of the hash-chain and all non-reverse
154 immortal entries are at the end of the hash-chain.
155 This allows reverse searches and garbage collection to be optimised */
156
157 struct crec **up = hash_bucket(cache_get_name(crecp));
158
159 if (!(crecp->flags & F_REVERSE))
160 {
161 while (*up && ((*up)->flags & F_REVERSE))
162 up = &((*up)->hash_next);
163
164 if (crecp->flags & F_IMMORTAL)
165 while (*up && !((*up)->flags & F_IMMORTAL))
166 up = &((*up)->hash_next);
167 }
168 crecp->hash_next = *up;
169 *up = crecp;
170 }
171
172 static void cache_free(struct crec *crecp)
173 {
174 crecp->flags &= ~F_FORWARD;
175 crecp->flags &= ~F_REVERSE;
176 crecp->uid = uid++; /* invalidate CNAMES pointing to this. */
177
178 if (cache_tail)
179 cache_tail->next = crecp;
180 else
181 cache_head = crecp;
182 crecp->prev = cache_tail;
183 crecp->next = NULL;
184 cache_tail = crecp;
185
186 /* retrieve big name for further use. */
187 if (crecp->flags & F_BIGNAME)
188 {
189 crecp->name.bname->next = big_free;
190 big_free = crecp->name.bname;
191 crecp->flags &= ~F_BIGNAME;
192 }
193 }
194
195 /* insert a new cache entry at the head of the list (youngest entry) */
196 static void cache_link(struct crec *crecp)
197 {
198 if (cache_head) /* check needed for init code */
199 cache_head->prev = crecp;
200 crecp->next = cache_head;
201 crecp->prev = NULL;
202 cache_head = crecp;
203 if (!cache_tail)
204 cache_tail = crecp;
205 }
206
207 /* remove an arbitrary cache entry for promotion */
208 static void cache_unlink (struct crec *crecp)
209 {
210 if (crecp->prev)
211 crecp->prev->next = crecp->next;
212 else
213 cache_head = crecp->next;
214
215 if (crecp->next)
216 crecp->next->prev = crecp->prev;
217 else
218 cache_tail = crecp->prev;
219 }
220
221 char *cache_get_name(struct crec *crecp)
222 {
223 if (crecp->flags & F_BIGNAME)
224 return crecp->name.bname->name;
225 else if (crecp->flags & F_NAMEP)
226 return crecp->name.namep;
227
228 return crecp->name.sname;
229 }
230
231 static int is_outdated_cname_pointer(struct crec *crecp)
232 {
233 if (!(crecp->flags & F_CNAME))
234 return 0;
235
236 if (crecp->addr.cname.cache && crecp->addr.cname.uid == crecp->addr.cname.cache->uid)
237 return 0;
238
239 return 1;
240 }
241
242 static int is_expired(time_t now, struct crec *crecp)
243 {
244 if (crecp->flags & F_IMMORTAL)
245 return 0;
246
247 if (difftime(now, crecp->ttd) < 0)
248 return 0;
249
250 return 1;
251 }
252
253 static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags)
254 {
255 /* Scan and remove old entries.
256 If (flags & F_FORWARD) then remove any forward entries for name and any expired
257 entries but only in the same hash bucket as name.
258 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
259 entries in the whole cache.
260 If (flags == 0) remove any expired entries in the whole cache.
261
262 In the flags & F_FORWARD case, the return code is valid, and returns zero if the
263 name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
264
265 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
266 so that when we hit an entry which isn't reverse and is immortal, we're done. */
267
268 struct crec *crecp, **up;
269
270 if (flags & F_FORWARD)
271 {
272 for (up = hash_bucket(name), crecp = *up; crecp; crecp = crecp->hash_next)
273 if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp))
274 {
275 *up = crecp->hash_next;
276 if (!(crecp->flags & (F_HOSTS | F_DHCP)))
277 {
278 cache_unlink(crecp);
279 cache_free(crecp);
280 }
281 }
282 else if ((crecp->flags & F_FORWARD) &&
283 ((flags & crecp->flags & (F_IPV4 | F_IPV6)) || ((crecp->flags | flags) & F_CNAME)) &&
284 hostname_isequal(cache_get_name(crecp), name))
285 {
286 if (crecp->flags & (F_HOSTS | F_DHCP))
287 return 0;
288 *up = crecp->hash_next;
289 cache_unlink(crecp);
290 cache_free(crecp);
291 }
292 else
293 up = &crecp->hash_next;
294 }
295 else
296 {
297 int i;
298 #ifdef HAVE_IPV6
299 int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ;
300 #else
301 int addrlen = INADDRSZ;
302 #endif
303 for (i = 0; i < hash_size; i++)
304 for (crecp = hash_table[i], up = &hash_table[i];
305 crecp && ((crecp->flags & F_REVERSE) || !(crecp->flags & F_IMMORTAL));
306 crecp = crecp->hash_next)
307 if (is_expired(now, crecp))
308 {
309 *up = crecp->hash_next;
310 if (!(crecp->flags & (F_HOSTS | F_DHCP)))
311 {
312 cache_unlink(crecp);
313 cache_free(crecp);
314 }
315 }
316 else if (!(crecp->flags & (F_HOSTS | F_DHCP)) &&
317 (flags & crecp->flags & F_REVERSE) &&
318 (flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
319 memcmp(&crecp->addr.addr, addr, addrlen) == 0)
320 {
321 *up = crecp->hash_next;
322 cache_unlink(crecp);
323 cache_free(crecp);
324 }
325 else
326 up = &crecp->hash_next;
327 }
328
329 return 1;
330 }
331
332 /* Note: The normal calling sequence is
333 cache_start_insert
334 cache_insert * n
335 cache_end_insert
336
337 but an abort can cause the cache_end_insert to be missed
338 in which can the next cache_start_insert cleans things up. */
339
340 void cache_start_insert(void)
341 {
342 /* Free any entries which didn't get committed during the last
343 insert due to error.
344 */
345 while (new_chain)
346 {
347 struct crec *tmp = new_chain->next;
348 cache_free(new_chain);
349 new_chain = tmp;
350 }
351 new_chain = NULL;
352 insert_error = 0;
353 }
354
355 struct crec *cache_insert(char *name, struct all_addr *addr,
356 time_t now, unsigned long ttl, unsigned short flags)
357 {
358 struct crec *new;
359 union bigname *big_name = NULL;
360 int freed_all = flags & F_REVERSE;
361 int free_avail = 0;
362
363 log_query(flags | F_UPSTREAM, name, addr, NULL);
364
365 /* if previous insertion failed give up now. */
366 if (insert_error)
367 return NULL;
368
369 /* First remove any expired entries and entries for the name/address we
370 are currently inserting. Fail is we attempt to delete a name from
371 /etc/hosts or DHCP. */
372 if (!cache_scan_free(name, addr, now, flags))
373 {
374 insert_error = 1;
375 return NULL;
376 }
377
378 /* Now get a cache entry from the end of the LRU list */
379 while (1) {
380 if (!(new = cache_tail)) /* no entries left - cache is too small, bail */
381 {
382 insert_error = 1;
383 return NULL;
384 }
385
386 /* End of LRU list is still in use: if we didn't scan all the hash
387 chains for expired entries do that now. If we already tried that
388 then it's time to start spilling things. */
389
390 if (new->flags & (F_FORWARD | F_REVERSE))
391 {
392 /* If free_avail set, we believe that an entry has been freed.
393 Bugs have been known to make this not true, resulting in
394 a tight loop here. If that happens, abandon the
395 insert. Once in this state, all inserts will probably fail. */
396 if (free_avail)
397 {
398 insert_error = 1;
399 return NULL;
400 }
401
402 if (freed_all)
403 {
404 free_avail = 1; /* Must be free space now. */
405 cache_scan_free(cache_get_name(new), &new->addr.addr, now, new->flags);
406 cache_live_freed++;
407 }
408 else
409 {
410 cache_scan_free(NULL, NULL, now, 0);
411 freed_all = 1;
412 }
413 continue;
414 }
415
416 /* Check if we need to and can allocate extra memory for a long name.
417 If that fails, give up now. */
418 if (name && (strlen(name) > SMALLDNAME-1))
419 {
420 if (big_free)
421 {
422 big_name = big_free;
423 big_free = big_free->next;
424 }
425 else if (!bignames_left ||
426 !(big_name = (union bigname *)whine_malloc(sizeof(union bigname))))
427 {
428 insert_error = 1;
429 return NULL;
430 }
431 else
432 bignames_left--;
433
434 }
435
436 /* Got the rest: finally grab entry. */
437 cache_unlink(new);
438 break;
439 }
440
441 new->flags = flags;
442 if (big_name)
443 {
444 new->name.bname = big_name;
445 new->flags |= F_BIGNAME;
446 }
447
448 if (name)
449 strcpy(cache_get_name(new), name);
450 else
451 *cache_get_name(new) = 0;
452
453 if (addr)
454 new->addr.addr = *addr;
455 else
456 new->addr.cname.cache = NULL;
457
458 new->ttd = now + (time_t)ttl;
459 new->next = new_chain;
460 new_chain = new;
461
462 return new;
463 }
464
465 /* after end of insertion, commit the new entries */
466 void cache_end_insert(void)
467 {
468 if (insert_error)
469 return;
470
471 while (new_chain)
472 {
473 struct crec *tmp = new_chain->next;
474 /* drop CNAMEs which didn't find a target. */
475 if (is_outdated_cname_pointer(new_chain))
476 cache_free(new_chain);
477 else
478 {
479 cache_hash(new_chain);
480 cache_link(new_chain);
481 cache_inserted++;
482 }
483 new_chain = tmp;
484 }
485 new_chain = NULL;
486 }
487
488 struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned short prot)
489 {
490 struct crec *ans;
491
492 if (crecp) /* iterating */
493 ans = crecp->next;
494 else
495 {
496 /* first search, look for relevant entries and push to top of list
497 also free anything which has expired */
498 struct crec *next, **up, **insert = NULL, **chainp = &ans;
499 unsigned short ins_flags = 0;
500
501 for (up = hash_bucket(name), crecp = *up; crecp; crecp = next)
502 {
503 next = crecp->hash_next;
504
505 if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp))
506 {
507 if ((crecp->flags & F_FORWARD) &&
508 (crecp->flags & prot) &&
509 hostname_isequal(cache_get_name(crecp), name))
510 {
511 if (crecp->flags & (F_HOSTS | F_DHCP))
512 {
513 *chainp = crecp;
514 chainp = &crecp->next;
515 }
516 else
517 {
518 cache_unlink(crecp);
519 cache_link(crecp);
520 }
521
522 /* Move all but the first entry up the hash chain
523 this implements round-robin.
524 Make sure that re-ordering doesn't break the hash-chain
525 order invariants.
526 */
527 if (insert && (crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags)
528 {
529 *up = crecp->hash_next;
530 crecp->hash_next = *insert;
531 *insert = crecp;
532 insert = &crecp->hash_next;
533 }
534 else
535 {
536 if (!insert)
537 {
538 insert = up;
539 ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
540 }
541 up = &crecp->hash_next;
542 }
543 }
544 else
545 /* case : not expired, incorrect entry. */
546 up = &crecp->hash_next;
547 }
548 else
549 {
550 /* expired entry, free it */
551 *up = crecp->hash_next;
552 if (!(crecp->flags & (F_HOSTS | F_DHCP)))
553 {
554 cache_unlink(crecp);
555 cache_free(crecp);
556 }
557 }
558 }
559
560 *chainp = cache_head;
561 }
562
563 if (ans &&
564 (ans->flags & F_FORWARD) &&
565 (ans->flags & prot) &&
566 hostname_isequal(cache_get_name(ans), name))
567 return ans;
568
569 return NULL;
570 }
571
572 struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
573 time_t now, unsigned short prot)
574 {
575 struct crec *ans;
576 #ifdef HAVE_IPV6
577 int addrlen = (prot == F_IPV6) ? IN6ADDRSZ : INADDRSZ;
578 #else
579 int addrlen = INADDRSZ;
580 #endif
581
582 if (crecp) /* iterating */
583 ans = crecp->next;
584 else
585 {
586 /* first search, look for relevant entries and push to top of list
587 also free anything which has expired. All the reverse entries are at the
588 start of the hash chain, so we can give up when we find the first
589 non-REVERSE one. */
590 int i;
591 struct crec **up, **chainp = &ans;
592
593 for (i=0; i<hash_size; i++)
594 for (crecp = hash_table[i], up = &hash_table[i];
595 crecp && (crecp->flags & F_REVERSE);
596 crecp = crecp->hash_next)
597 if (!is_expired(now, crecp))
598 {
599 if ((crecp->flags & prot) &&
600 memcmp(&crecp->addr.addr, addr, addrlen) == 0)
601 {
602 if (crecp->flags & (F_HOSTS | F_DHCP))
603 {
604 *chainp = crecp;
605 chainp = &crecp->next;
606 }
607 else
608 {
609 cache_unlink(crecp);
610 cache_link(crecp);
611 }
612 }
613 up = &crecp->hash_next;
614 }
615 else
616 {
617 *up = crecp->hash_next;
618 if (!(crecp->flags & (F_HOSTS | F_DHCP)))
619 {
620 cache_unlink(crecp);
621 cache_free(crecp);
622 }
623 }
624
625 *chainp = cache_head;
626 }
627
628 if (ans &&
629 (ans->flags & F_REVERSE) &&
630 (ans->flags & prot) &&
631 memcmp(&ans->addr.addr, addr, addrlen) == 0)
632 return ans;
633
634 return NULL;
635 }
636
637 static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
638 unsigned short flags, int index, int addr_dup)
639 {
640 struct crec *lookup = cache_find_by_name(NULL, cache->name.sname, 0, flags & (F_IPV4 | F_IPV6));
641 int i, nameexists = 0;
642 struct cname *a;
643
644 /* Remove duplicates in hosts files. */
645 if (lookup && (lookup->flags & F_HOSTS))
646 {
647 nameexists = 1;
648 if (memcmp(&lookup->addr.addr, addr, addrlen) == 0)
649 {
650 free(cache);
651 return;
652 }
653 }
654
655 /* Ensure there is only one address -> name mapping (first one trumps)
656 We do this by steam here, first we see if the address is the same as
657 the last one we saw, which eliminates most in the case of an ad-block
658 file with thousands of entries for the same address.
659 Then we search and bail at the first matching address that came from
660 a HOSTS file. Since the first host entry gets reverse, we know
661 then that it must exist without searching exhaustively for it. */
662
663 if (addr_dup)
664 flags &= ~F_REVERSE;
665 else
666 for (i=0; i<hash_size; i++)
667 {
668 for (lookup = hash_table[i]; lookup; lookup = lookup->hash_next)
669 if ((lookup->flags & F_HOSTS) &&
670 (lookup->flags & flags & (F_IPV4 | F_IPV6)) &&
671 memcmp(&lookup->addr.addr, addr, addrlen) == 0)
672 {
673 flags &= ~F_REVERSE;
674 break;
675 }
676 if (lookup)
677 break;
678 }
679
680 cache->flags = flags;
681 cache->uid = index;
682 memcpy(&cache->addr.addr, addr, addrlen);
683 cache_hash(cache);
684
685 /* don't need to do alias stuff for second and subsequent addresses. */
686 if (!nameexists)
687 for (a = daemon->cnames; a; a = a->next)
688 if (hostname_isequal(cache->name.sname, a->target) &&
689 (lookup = whine_malloc(sizeof(struct crec))))
690 {
691 lookup->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_HOSTS | F_CNAME;
692 lookup->name.namep = a->alias;
693 lookup->addr.cname.cache = cache;
694 lookup->addr.cname.uid = index;
695 cache_hash(lookup);
696 }
697 }
698
699 static int eatspace(FILE *f)
700 {
701 int c, nl = 0;
702
703 while (1)
704 {
705 if ((c = getc(f)) == '#')
706 while (c != '\n' && c != EOF)
707 c = getc(f);
708
709 if (c == EOF)
710 return 1;
711
712 if (!isspace(c))
713 {
714 ungetc(c, f);
715 return nl;
716 }
717
718 if (c == '\n')
719 nl = 1;
720 }
721 }
722
723 static int gettok(FILE *f, char *token)
724 {
725 int c, count = 0;
726
727 while (1)
728 {
729 if ((c = getc(f)) == EOF)
730 return (count == 0) ? EOF : 1;
731
732 if (isspace(c) || c == '#')
733 {
734 ungetc(c, f);
735 return eatspace(f);
736 }
737
738 if (count < (MAXDNAME - 1))
739 {
740 token[count++] = c;
741 token[count] = 0;
742 }
743 }
744 }
745
746 static int read_hostsfile(char *filename, int index, int cache_size)
747 {
748 FILE *f = fopen(filename, "r");
749 char *token = daemon->namebuff, *domain_suffix = NULL;
750 int addr_count = 0, name_count = cache_size, lineno = 0;
751 unsigned short flags = 0, saved_flags = 0;
752 struct all_addr addr, saved_addr;
753 int atnl, addrlen = 0, addr_dup;
754
755 if (!f)
756 {
757 my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
758 return 0;
759 }
760
761 eatspace(f);
762
763 while ((atnl = gettok(f, token)) != EOF)
764 {
765 addr_dup = 0;
766 lineno++;
767
768 #ifdef HAVE_IPV6
769 if (inet_pton(AF_INET, token, &addr) > 0)
770 {
771 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
772 addrlen = INADDRSZ;
773 domain_suffix = get_domain(addr.addr.addr4);
774 }
775 else if (inet_pton(AF_INET6, token, &addr) > 0)
776 {
777 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
778 addrlen = IN6ADDRSZ;
779 domain_suffix = daemon->domain_suffix;
780 }
781 #else
782 if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1)
783 {
784 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
785 addrlen = INADDRSZ;
786 domain_suffix = get_domain(addr.addr.addr4);
787 }
788 #endif
789 else
790 {
791 my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
792 while (atnl == 0)
793 atnl = gettok(f, token);
794 continue;
795 }
796
797 if (saved_flags == flags && memcmp(&addr, &saved_addr, addrlen) == 0)
798 addr_dup = 1;
799 else
800 {
801 saved_flags = flags;
802 saved_addr = addr;
803 }
804
805 addr_count++;
806
807 /* rehash every 1000 names. */
808 if ((name_count - cache_size) > 1000)
809 {
810 rehash(name_count);
811 cache_size = name_count;
812 }
813
814 while (atnl == 0)
815 {
816 struct crec *cache;
817 int fqdn, nomem;
818 char *canon;
819
820 if ((atnl = gettok(f, token)) == EOF)
821 break;
822
823 fqdn = !!strchr(token, '.');
824
825 if ((canon = canonicalise(token, &nomem)))
826 {
827 /* If set, add a version of the name with a default domain appended */
828 if (option_bool(OPT_EXPAND) && domain_suffix && !fqdn &&
829 (cache = whine_malloc(sizeof(struct crec) +
830 strlen(canon)+2+strlen(domain_suffix)-SMALLDNAME)))
831 {
832 strcpy(cache->name.sname, canon);
833 strcat(cache->name.sname, ".");
834 strcat(cache->name.sname, domain_suffix);
835 add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
836 addr_dup = 1;
837 name_count++;
838 }
839 if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon)+1-SMALLDNAME)))
840 {
841 strcpy(cache->name.sname, canon);
842 add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
843 name_count++;
844 }
845 free(canon);
846
847 }
848 else if (!nomem)
849 my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
850 }
851 }
852
853 fclose(f);
854 rehash(name_count);
855
856 my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
857
858 return name_count;
859 }
860
861 void cache_reload(void)
862 {
863 struct crec *cache, **up, *tmp;
864 int i, total_size = daemon->cachesize;
865 struct hostsfile *ah;
866
867 cache_inserted = cache_live_freed = 0;
868
869 for (i=0; i<hash_size; i++)
870 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
871 {
872 tmp = cache->hash_next;
873 if (cache->flags & F_HOSTS)
874 {
875 *up = cache->hash_next;
876 free(cache);
877 }
878 else if (!(cache->flags & F_DHCP))
879 {
880 *up = cache->hash_next;
881 if (cache->flags & F_BIGNAME)
882 {
883 cache->name.bname->next = big_free;
884 big_free = cache->name.bname;
885 }
886 cache->flags = 0;
887 }
888 else
889 up = &cache->hash_next;
890 }
891
892 if (option_bool(OPT_NO_HOSTS) && !daemon->addn_hosts)
893 {
894 if (daemon->cachesize > 0)
895 my_syslog(LOG_INFO, _("cleared cache"));
896 return;
897 }
898
899 if (!option_bool(OPT_NO_HOSTS))
900 total_size = read_hostsfile(HOSTSFILE, 0, total_size);
901
902 daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
903 for (ah = daemon->addn_hosts; ah; ah = ah->next)
904 if (!(ah->flags & AH_INACTIVE))
905 total_size = read_hostsfile(ah->fname, ah->index, total_size);
906 }
907
908 char *get_domain(struct in_addr addr)
909 {
910 struct cond_domain *c;
911
912 for (c = daemon->cond_domain; c; c = c->next)
913 if (ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
914 ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
915 return c->domain;
916
917 return daemon->domain_suffix;
918 }
919
920 #ifdef HAVE_DHCP
921 struct in_addr a_record_from_hosts(char *name, time_t now)
922 {
923 struct crec *crecp = NULL;
924 struct in_addr ret;
925
926 while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
927 if (crecp->flags & F_HOSTS)
928 return *(struct in_addr *)&crecp->addr;
929
930 my_syslog(MS_DHCP | LOG_WARNING, _("No IPv4 address found for %s"), name);
931
932 ret.s_addr = 0;
933 return ret;
934 }
935
936 void cache_unhash_dhcp(void)
937 {
938 struct crec *cache, **up;
939 int i;
940
941 for (i=0; i<hash_size; i++)
942 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next)
943 if (cache->flags & F_DHCP)
944 {
945 *up = cache->hash_next;
946 cache->next = dhcp_spare;
947 dhcp_spare = cache;
948 }
949 else
950 up = &cache->hash_next;
951 }
952
953 void cache_add_dhcp_entry(char *host_name,
954 struct in_addr *host_address, time_t ttd)
955 {
956 struct crec *crec = NULL, *aliasc;
957 unsigned short flags = F_NAMEP | F_DHCP | F_FORWARD | F_IPV4 | F_REVERSE;
958 int in_hosts = 0;
959 struct cname *a;
960
961 while ((crec = cache_find_by_name(crec, host_name, 0, F_IPV4 | F_CNAME)))
962 {
963 /* check all addresses associated with name */
964 if (crec->flags & F_HOSTS)
965 {
966 /* if in hosts, don't need DHCP record */
967 in_hosts = 1;
968
969 if (crec->flags & F_CNAME)
970 my_syslog(MS_DHCP | LOG_WARNING,
971 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
972 host_name, inet_ntoa(*host_address));
973 else if (crec->addr.addr.addr.addr4.s_addr != host_address->s_addr)
974 {
975 strcpy(daemon->namebuff, inet_ntoa(crec->addr.addr.addr.addr4));
976 my_syslog(MS_DHCP | LOG_WARNING,
977 _("not giving name %s to the DHCP lease of %s because "
978 "the name exists in %s with address %s"),
979 host_name, inet_ntoa(*host_address),
980 record_source(crec->uid), daemon->namebuff);
981 }
982 }
983 else if (!(crec->flags & F_DHCP))
984 {
985 cache_scan_free(host_name, NULL, 0, crec->flags & (F_IPV4 | F_CNAME | F_FORWARD));
986 /* scan_free deletes all addresses associated with name */
987 break;
988 }
989 }
990
991 if (in_hosts)
992 return;
993
994 if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, F_IPV4)))
995 {
996 if (crec->flags & F_NEG)
997 cache_scan_free(NULL, (struct all_addr *)host_address, 0, F_IPV4 | F_REVERSE);
998 else
999 /* avoid multiple reverse mappings */
1000 flags &= ~F_REVERSE;
1001 }
1002
1003 if ((crec = dhcp_spare))
1004 dhcp_spare = dhcp_spare->next;
1005 else /* need new one */
1006 crec = whine_malloc(sizeof(struct crec));
1007
1008 if (crec) /* malloc may fail */
1009 {
1010 crec->flags = flags;
1011 if (ttd == 0)
1012 crec->flags |= F_IMMORTAL;
1013 else
1014 crec->ttd = ttd;
1015 crec->addr.addr.addr.addr4 = *host_address;
1016 crec->name.namep = host_name;
1017 crec->uid = uid++;
1018 cache_hash(crec);
1019
1020 for (a = daemon->cnames; a; a = a->next)
1021 if (hostname_isequal(host_name, a->target))
1022 {
1023 if ((aliasc = dhcp_spare))
1024 dhcp_spare = dhcp_spare->next;
1025 else /* need new one */
1026 aliasc = whine_malloc(sizeof(struct crec));
1027
1028 if (aliasc)
1029 {
1030 aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME;
1031 if (ttd == 0)
1032 aliasc->flags |= F_IMMORTAL;
1033 else
1034 aliasc->ttd = ttd;
1035 aliasc->name.namep = a->alias;
1036 aliasc->addr.cname.cache = crec;
1037 aliasc->addr.cname.uid = crec->uid;
1038 cache_hash(aliasc);
1039 }
1040 }
1041 }
1042 }
1043 #endif
1044
1045
1046 void dump_cache(time_t now)
1047 {
1048 struct server *serv, *serv1;
1049
1050 my_syslog(LOG_INFO, _("time %lu"), (unsigned long)now);
1051 my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
1052 daemon->cachesize, cache_live_freed, cache_inserted);
1053 my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
1054 daemon->queries_forwarded, daemon->local_answer);
1055
1056 /* sum counts from different records for same server */
1057 for (serv = daemon->servers; serv; serv = serv->next)
1058 serv->flags &= ~SERV_COUNTED;
1059
1060 for (serv = daemon->servers; serv; serv = serv->next)
1061 if (!(serv->flags &
1062 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
1063 {
1064 int port;
1065 unsigned int queries = 0, failed_queries = 0;
1066 for (serv1 = serv; serv1; serv1 = serv1->next)
1067 if (!(serv1->flags &
1068 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
1069 sockaddr_isequal(&serv->addr, &serv1->addr))
1070 {
1071 serv1->flags |= SERV_COUNTED;
1072 queries += serv1->queries;
1073 failed_queries += serv1->failed_queries;
1074 }
1075 port = prettyprint_addr(&serv->addr, daemon->addrbuff);
1076 my_syslog(LOG_INFO, _("server %s#%d: queries sent %u, retried or failed %u"), daemon->addrbuff, port, queries, failed_queries);
1077 }
1078
1079 if (option_bool(OPT_DEBUG) || option_bool(OPT_LOG))
1080 {
1081 struct crec *cache ;
1082 int i;
1083 my_syslog(LOG_INFO, "Host Address Flags Expires");
1084
1085 for (i=0; i<hash_size; i++)
1086 for (cache = hash_table[i]; cache; cache = cache->hash_next)
1087 {
1088 char *a, *p = daemon->namebuff;
1089 p += sprintf(p, "%-40.40s ", cache_get_name(cache));
1090 if ((cache->flags & F_NEG) && (cache->flags & F_FORWARD))
1091 a = "";
1092 else if (cache->flags & F_CNAME)
1093 {
1094 a = "";
1095 if (!is_outdated_cname_pointer(cache))
1096 a = cache_get_name(cache->addr.cname.cache);
1097 }
1098 #ifdef HAVE_IPV6
1099 else
1100 {
1101 a = daemon->addrbuff;
1102 if (cache->flags & F_IPV4)
1103 inet_ntop(AF_INET, &cache->addr.addr, a, ADDRSTRLEN);
1104 else if (cache->flags & F_IPV6)
1105 inet_ntop(AF_INET6, &cache->addr.addr, a, ADDRSTRLEN);
1106 }
1107 #else
1108 else
1109 a = inet_ntoa(cache->addr.addr.addr.addr4);
1110 #endif
1111 p += sprintf(p, "%-30.30s %s%s%s%s%s%s%s%s%s%s ", a,
1112 cache->flags & F_IPV4 ? "4" : "",
1113 cache->flags & F_IPV6 ? "6" : "",
1114 cache->flags & F_CNAME ? "C" : "",
1115 cache->flags & F_FORWARD ? "F" : " ",
1116 cache->flags & F_REVERSE ? "R" : " ",
1117 cache->flags & F_IMMORTAL ? "I" : " ",
1118 cache->flags & F_DHCP ? "D" : " ",
1119 cache->flags & F_NEG ? "N" : " ",
1120 cache->flags & F_NXDOMAIN ? "X" : " ",
1121 cache->flags & F_HOSTS ? "H" : " ");
1122 #ifdef HAVE_BROKEN_RTC
1123 p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
1124 #else
1125 p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd)));
1126 /* ctime includes trailing \n - eat it */
1127 *(p-1) = 0;
1128 #endif
1129 my_syslog(LOG_INFO, daemon->namebuff);
1130 }
1131 }
1132 }
1133
1134 char *record_source(int index)
1135 {
1136 struct hostsfile *ah;
1137
1138 if (index == 0)
1139 return HOSTSFILE;
1140
1141 for (ah = daemon->addn_hosts; ah; ah = ah->next)
1142 if (ah->index == index)
1143 return ah->fname;
1144
1145 return "<unknown>";
1146 }
1147
1148 void querystr(char *str, unsigned short type)
1149 {
1150 unsigned int i;
1151
1152 sprintf(str, "query[type=%d]", type);
1153 for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
1154 if (typestr[i].type == type)
1155 sprintf(str,"query[%s]", typestr[i].name);
1156 }
1157
1158 void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
1159 {
1160 char *source, *dest = daemon->addrbuff;
1161 char *verb = "is";
1162
1163 if (!option_bool(OPT_LOG))
1164 return;
1165
1166 if (addr)
1167 {
1168 #ifdef HAVE_IPV6
1169 inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
1170 addr, daemon->addrbuff, ADDRSTRLEN);
1171 #else
1172 strncpy(daemon->addrbuff, inet_ntoa(addr->addr.addr4), ADDRSTRLEN);
1173 #endif
1174 }
1175
1176 if (flags & F_REVERSE)
1177 {
1178 dest = name;
1179 name = daemon->addrbuff;
1180 }
1181
1182 if (flags & F_NEG)
1183 {
1184 if (flags & F_NXDOMAIN)
1185 {
1186 if (flags & F_IPV4)
1187 dest = "NXDOMAIN-IPv4";
1188 else if (flags & F_IPV6)
1189 dest = "NXDOMAIN-IPv6";
1190 else
1191 dest = "NXDOMAIN";
1192 }
1193 else
1194 {
1195 if (flags & F_IPV4)
1196 dest = "NODATA-IPv4";
1197 else if (flags & F_IPV6)
1198 dest = "NODATA-IPv6";
1199 else
1200 dest = "NODATA";
1201 }
1202 }
1203 else if (flags & F_CNAME)
1204 dest = "<CNAME>";
1205 else if (flags & F_RRNAME)
1206 dest = arg;
1207
1208 if (flags & F_CONFIG)
1209 source = "config";
1210 else if (flags & F_DHCP)
1211 source = "DHCP";
1212 else if (flags & F_HOSTS)
1213 source = arg;
1214 else if (flags & F_UPSTREAM)
1215 source = "reply";
1216 else if (flags & F_SERVER)
1217 {
1218 source = "forwarded";
1219 verb = "to";
1220 }
1221 else if (flags & F_QUERY)
1222 {
1223 source = arg;
1224 verb = "from";
1225 }
1226 else
1227 source = "cached";
1228
1229 if (strlen(name) == 0)
1230 name = ".";
1231
1232 my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
1233 }
1234