]> git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/cache.c
Merge branch 'dhcpv6'
[people/ms/dnsmasq.git] / src / cache.c
1 /* dnsmasq is Copyright (c) 2000-2012 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, struct crec **rhash, int hashsz)
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 unsigned int j;
644
645 /* Remove duplicates in hosts files. */
646 if (lookup && (lookup->flags & F_HOSTS))
647 {
648 nameexists = 1;
649 if (memcmp(&lookup->addr.addr, addr, addrlen) == 0)
650 {
651 free(cache);
652 return;
653 }
654 }
655
656 /* Ensure there is only one address -> name mapping (first one trumps)
657 We do this by steam here, The entries are kept in hash chains, linked
658 by ->next (which is unused at this point) held in hash buckets in
659 the array rhash, hashed on address. Note that rhash and the values
660 in ->next are only valid whilst reading hosts files: the buckets are
661 then freed, and the ->next pointer used for other things.
662
663 Only insert each unique address once into this hashing structure.
664
665 This complexity avoids O(n^2) divergent CPU use whilst reading
666 large (10000 entry) hosts files. */
667
668 /* hash address */
669 for (j = 0, i = 0; i < addrlen; i++)
670 j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
671
672 for (lookup = rhash[j]; lookup; lookup = lookup->next)
673 if ((lookup->flags & flags & (F_IPV4 | F_IPV6)) &&
674 memcmp(&lookup->addr.addr, addr, addrlen) == 0)
675 {
676 flags &= ~F_REVERSE;
677 break;
678 }
679
680 /* maintain address hash chain, insert new unique address */
681 if (!lookup)
682 {
683 cache->next = rhash[j];
684 rhash[j] = cache;
685 }
686
687 cache->flags = flags;
688 cache->uid = index;
689 memcpy(&cache->addr.addr, addr, addrlen);
690 cache_hash(cache);
691
692 /* don't need to do alias stuff for second and subsequent addresses. */
693 if (!nameexists)
694 for (a = daemon->cnames; a; a = a->next)
695 if (hostname_isequal(cache->name.sname, a->target) &&
696 (lookup = whine_malloc(sizeof(struct crec))))
697 {
698 lookup->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_HOSTS | F_CNAME;
699 lookup->name.namep = a->alias;
700 lookup->addr.cname.cache = cache;
701 lookup->addr.cname.uid = index;
702 cache_hash(lookup);
703 }
704 }
705
706 static int eatspace(FILE *f)
707 {
708 int c, nl = 0;
709
710 while (1)
711 {
712 if ((c = getc(f)) == '#')
713 while (c != '\n' && c != EOF)
714 c = getc(f);
715
716 if (c == EOF)
717 return 1;
718
719 if (!isspace(c))
720 {
721 ungetc(c, f);
722 return nl;
723 }
724
725 if (c == '\n')
726 nl = 1;
727 }
728 }
729
730 static int gettok(FILE *f, char *token)
731 {
732 int c, count = 0;
733
734 while (1)
735 {
736 if ((c = getc(f)) == EOF)
737 return (count == 0) ? EOF : 1;
738
739 if (isspace(c) || c == '#')
740 {
741 ungetc(c, f);
742 return eatspace(f);
743 }
744
745 if (count < (MAXDNAME - 1))
746 {
747 token[count++] = c;
748 token[count] = 0;
749 }
750 }
751 }
752
753 static int read_hostsfile(char *filename, int index, int cache_size, struct crec **rhash, int hashsz)
754 {
755 FILE *f = fopen(filename, "r");
756 char *token = daemon->namebuff, *domain_suffix = NULL;
757 int addr_count = 0, name_count = cache_size, lineno = 0;
758 unsigned short flags = 0;
759 struct all_addr addr;
760 int atnl, addrlen = 0;
761
762 if (!f)
763 {
764 my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
765 return 0;
766 }
767
768 eatspace(f);
769
770 while ((atnl = gettok(f, token)) != EOF)
771 {
772 lineno++;
773
774 #ifdef HAVE_IPV6
775 if (inet_pton(AF_INET, token, &addr) > 0)
776 {
777 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
778 addrlen = INADDRSZ;
779 domain_suffix = get_domain(addr.addr.addr4);
780 }
781 else if (inet_pton(AF_INET6, token, &addr) > 0)
782 {
783 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
784 addrlen = IN6ADDRSZ;
785 domain_suffix = daemon->domain_suffix;
786 }
787 #else
788 if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1)
789 {
790 flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
791 addrlen = INADDRSZ;
792 domain_suffix = get_domain(addr.addr.addr4);
793 }
794 #endif
795 else
796 {
797 my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
798 while (atnl == 0)
799 atnl = gettok(f, token);
800 continue;
801 }
802
803 addr_count++;
804
805 /* rehash every 1000 names. */
806 if ((name_count - cache_size) > 1000)
807 {
808 rehash(name_count);
809 cache_size = name_count;
810 }
811
812 while (atnl == 0)
813 {
814 struct crec *cache;
815 int fqdn, nomem;
816 char *canon;
817
818 if ((atnl = gettok(f, token)) == EOF)
819 break;
820
821 fqdn = !!strchr(token, '.');
822
823 if ((canon = canonicalise(token, &nomem)))
824 {
825 /* If set, add a version of the name with a default domain appended */
826 if (option_bool(OPT_EXPAND) && domain_suffix && !fqdn &&
827 (cache = whine_malloc(sizeof(struct crec) +
828 strlen(canon)+2+strlen(domain_suffix)-SMALLDNAME)))
829 {
830 strcpy(cache->name.sname, canon);
831 strcat(cache->name.sname, ".");
832 strcat(cache->name.sname, domain_suffix);
833 add_hosts_entry(cache, &addr, addrlen, flags, index, rhash, hashsz);
834 name_count++;
835 }
836 if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon)+1-SMALLDNAME)))
837 {
838 strcpy(cache->name.sname, canon);
839 add_hosts_entry(cache, &addr, addrlen, flags, index, rhash, hashsz);
840 name_count++;
841 }
842 free(canon);
843
844 }
845 else if (!nomem)
846 my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
847 }
848 }
849
850 fclose(f);
851 rehash(name_count);
852
853 my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
854
855 return name_count;
856 }
857
858 void cache_reload(void)
859 {
860 struct crec *cache, **up, *tmp;
861 int revhashsz, i, total_size = daemon->cachesize;
862 struct hostsfile *ah;
863
864 cache_inserted = cache_live_freed = 0;
865
866 for (i=0; i<hash_size; i++)
867 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
868 {
869 tmp = cache->hash_next;
870 if (cache->flags & F_HOSTS)
871 {
872 *up = cache->hash_next;
873 free(cache);
874 }
875 else if (!(cache->flags & F_DHCP))
876 {
877 *up = cache->hash_next;
878 if (cache->flags & F_BIGNAME)
879 {
880 cache->name.bname->next = big_free;
881 big_free = cache->name.bname;
882 }
883 cache->flags = 0;
884 }
885 else
886 up = &cache->hash_next;
887 }
888
889 if (option_bool(OPT_NO_HOSTS) && !daemon->addn_hosts)
890 {
891 if (daemon->cachesize > 0)
892 my_syslog(LOG_INFO, _("cleared cache"));
893 return;
894 }
895
896 /* borrow the packet buffer for a temporary by-address hash */
897 memset(daemon->packet, 0, daemon->packet_buff_sz);
898 revhashsz = daemon->packet_buff_sz / sizeof(struct crec *);
899 /* we overwrote the buffer... */
900 daemon->srv_save = NULL;
901
902 if (!option_bool(OPT_NO_HOSTS))
903 total_size = read_hostsfile(HOSTSFILE, 0, total_size, (struct crec **)daemon->packet, revhashsz);
904
905 daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
906 for (ah = daemon->addn_hosts; ah; ah = ah->next)
907 if (!(ah->flags & AH_INACTIVE))
908 total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
909 }
910
911 char *get_domain(struct in_addr addr)
912 {
913 struct cond_domain *c;
914
915 for (c = daemon->cond_domain; c; c = c->next)
916 if (ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
917 ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
918 return c->domain;
919
920 return daemon->domain_suffix;
921 }
922
923 #ifdef HAVE_DHCP
924 struct in_addr a_record_from_hosts(char *name, time_t now)
925 {
926 struct crec *crecp = NULL;
927 struct in_addr ret;
928
929 while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
930 if (crecp->flags & F_HOSTS)
931 return *(struct in_addr *)&crecp->addr;
932
933 my_syslog(MS_DHCP | LOG_WARNING, _("No IPv4 address found for %s"), name);
934
935 ret.s_addr = 0;
936 return ret;
937 }
938
939 void cache_unhash_dhcp(void)
940 {
941 struct crec *cache, **up;
942 int i;
943
944 for (i=0; i<hash_size; i++)
945 for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next)
946 if (cache->flags & F_DHCP)
947 {
948 *up = cache->hash_next;
949 cache->next = dhcp_spare;
950 dhcp_spare = cache;
951 }
952 else
953 up = &cache->hash_next;
954 }
955
956 void cache_add_dhcp_entry(char *host_name,
957 struct in_addr *host_address, time_t ttd)
958 {
959 struct crec *crec = NULL, *aliasc;
960 unsigned short flags = F_NAMEP | F_DHCP | F_FORWARD | F_IPV4 | F_REVERSE;
961 int in_hosts = 0;
962 struct cname *a;
963
964 while ((crec = cache_find_by_name(crec, host_name, 0, F_IPV4 | F_CNAME)))
965 {
966 /* check all addresses associated with name */
967 if (crec->flags & F_HOSTS)
968 {
969 /* if in hosts, don't need DHCP record */
970 in_hosts = 1;
971
972 if (crec->flags & F_CNAME)
973 my_syslog(MS_DHCP | LOG_WARNING,
974 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
975 host_name, inet_ntoa(*host_address));
976 else if (crec->addr.addr.addr.addr4.s_addr != host_address->s_addr)
977 {
978 strcpy(daemon->namebuff, inet_ntoa(crec->addr.addr.addr.addr4));
979 my_syslog(MS_DHCP | LOG_WARNING,
980 _("not giving name %s to the DHCP lease of %s because "
981 "the name exists in %s with address %s"),
982 host_name, inet_ntoa(*host_address),
983 record_source(crec->uid), daemon->namebuff);
984 }
985 }
986 else if (!(crec->flags & F_DHCP))
987 {
988 cache_scan_free(host_name, NULL, 0, crec->flags & (F_IPV4 | F_CNAME | F_FORWARD));
989 /* scan_free deletes all addresses associated with name */
990 break;
991 }
992 }
993
994 if (in_hosts)
995 return;
996
997 if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, F_IPV4)))
998 {
999 if (crec->flags & F_NEG)
1000 cache_scan_free(NULL, (struct all_addr *)host_address, 0, F_IPV4 | F_REVERSE);
1001 else
1002 /* avoid multiple reverse mappings */
1003 flags &= ~F_REVERSE;
1004 }
1005
1006 if ((crec = dhcp_spare))
1007 dhcp_spare = dhcp_spare->next;
1008 else /* need new one */
1009 crec = whine_malloc(sizeof(struct crec));
1010
1011 if (crec) /* malloc may fail */
1012 {
1013 crec->flags = flags;
1014 if (ttd == 0)
1015 crec->flags |= F_IMMORTAL;
1016 else
1017 crec->ttd = ttd;
1018 crec->addr.addr.addr.addr4 = *host_address;
1019 crec->name.namep = host_name;
1020 crec->uid = uid++;
1021 cache_hash(crec);
1022
1023 for (a = daemon->cnames; a; a = a->next)
1024 if (hostname_isequal(host_name, a->target))
1025 {
1026 if ((aliasc = dhcp_spare))
1027 dhcp_spare = dhcp_spare->next;
1028 else /* need new one */
1029 aliasc = whine_malloc(sizeof(struct crec));
1030
1031 if (aliasc)
1032 {
1033 aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME;
1034 if (ttd == 0)
1035 aliasc->flags |= F_IMMORTAL;
1036 else
1037 aliasc->ttd = ttd;
1038 aliasc->name.namep = a->alias;
1039 aliasc->addr.cname.cache = crec;
1040 aliasc->addr.cname.uid = crec->uid;
1041 cache_hash(aliasc);
1042 }
1043 }
1044 }
1045 }
1046 #endif
1047
1048
1049 void dump_cache(time_t now)
1050 {
1051 struct server *serv, *serv1;
1052
1053 my_syslog(LOG_INFO, _("time %lu"), (unsigned long)now);
1054 my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
1055 daemon->cachesize, cache_live_freed, cache_inserted);
1056 my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
1057 daemon->queries_forwarded, daemon->local_answer);
1058
1059 /* sum counts from different records for same server */
1060 for (serv = daemon->servers; serv; serv = serv->next)
1061 serv->flags &= ~SERV_COUNTED;
1062
1063 for (serv = daemon->servers; serv; serv = serv->next)
1064 if (!(serv->flags &
1065 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
1066 {
1067 int port;
1068 unsigned int queries = 0, failed_queries = 0;
1069 for (serv1 = serv; serv1; serv1 = serv1->next)
1070 if (!(serv1->flags &
1071 (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
1072 sockaddr_isequal(&serv->addr, &serv1->addr))
1073 {
1074 serv1->flags |= SERV_COUNTED;
1075 queries += serv1->queries;
1076 failed_queries += serv1->failed_queries;
1077 }
1078 port = prettyprint_addr(&serv->addr, daemon->addrbuff);
1079 my_syslog(LOG_INFO, _("server %s#%d: queries sent %u, retried or failed %u"), daemon->addrbuff, port, queries, failed_queries);
1080 }
1081
1082 if (option_bool(OPT_DEBUG) || option_bool(OPT_LOG))
1083 {
1084 struct crec *cache ;
1085 int i;
1086 my_syslog(LOG_INFO, "Host Address Flags Expires");
1087
1088 for (i=0; i<hash_size; i++)
1089 for (cache = hash_table[i]; cache; cache = cache->hash_next)
1090 {
1091 char *a, *p = daemon->namebuff;
1092 p += sprintf(p, "%-40.40s ", cache_get_name(cache));
1093 if ((cache->flags & F_NEG) && (cache->flags & F_FORWARD))
1094 a = "";
1095 else if (cache->flags & F_CNAME)
1096 {
1097 a = "";
1098 if (!is_outdated_cname_pointer(cache))
1099 a = cache_get_name(cache->addr.cname.cache);
1100 }
1101 #ifdef HAVE_IPV6
1102 else
1103 {
1104 a = daemon->addrbuff;
1105 if (cache->flags & F_IPV4)
1106 inet_ntop(AF_INET, &cache->addr.addr, a, ADDRSTRLEN);
1107 else if (cache->flags & F_IPV6)
1108 inet_ntop(AF_INET6, &cache->addr.addr, a, ADDRSTRLEN);
1109 }
1110 #else
1111 else
1112 a = inet_ntoa(cache->addr.addr.addr.addr4);
1113 #endif
1114 p += sprintf(p, "%-30.30s %s%s%s%s%s%s%s%s%s%s ", a,
1115 cache->flags & F_IPV4 ? "4" : "",
1116 cache->flags & F_IPV6 ? "6" : "",
1117 cache->flags & F_CNAME ? "C" : "",
1118 cache->flags & F_FORWARD ? "F" : " ",
1119 cache->flags & F_REVERSE ? "R" : " ",
1120 cache->flags & F_IMMORTAL ? "I" : " ",
1121 cache->flags & F_DHCP ? "D" : " ",
1122 cache->flags & F_NEG ? "N" : " ",
1123 cache->flags & F_NXDOMAIN ? "X" : " ",
1124 cache->flags & F_HOSTS ? "H" : " ");
1125 #ifdef HAVE_BROKEN_RTC
1126 p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
1127 #else
1128 p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd)));
1129 /* ctime includes trailing \n - eat it */
1130 *(p-1) = 0;
1131 #endif
1132 my_syslog(LOG_INFO, daemon->namebuff);
1133 }
1134 }
1135 }
1136
1137 char *record_source(int index)
1138 {
1139 struct hostsfile *ah;
1140
1141 if (index == 0)
1142 return HOSTSFILE;
1143
1144 for (ah = daemon->addn_hosts; ah; ah = ah->next)
1145 if (ah->index == index)
1146 return ah->fname;
1147
1148 return "<unknown>";
1149 }
1150
1151 void querystr(char *str, unsigned short type)
1152 {
1153 unsigned int i;
1154
1155 sprintf(str, "query[type=%d]", type);
1156 for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
1157 if (typestr[i].type == type)
1158 sprintf(str,"query[%s]", typestr[i].name);
1159 }
1160
1161 void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
1162 {
1163 char *source, *dest = daemon->addrbuff;
1164 char *verb = "is";
1165
1166 if (!option_bool(OPT_LOG))
1167 return;
1168
1169 if (addr)
1170 {
1171 #ifdef HAVE_IPV6
1172 inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
1173 addr, daemon->addrbuff, ADDRSTRLEN);
1174 #else
1175 strncpy(daemon->addrbuff, inet_ntoa(addr->addr.addr4), ADDRSTRLEN);
1176 #endif
1177 }
1178
1179 if (flags & F_REVERSE)
1180 {
1181 dest = name;
1182 name = daemon->addrbuff;
1183 }
1184
1185 if (flags & F_NEG)
1186 {
1187 if (flags & F_NXDOMAIN)
1188 {
1189 if (flags & F_IPV4)
1190 dest = "NXDOMAIN-IPv4";
1191 else if (flags & F_IPV6)
1192 dest = "NXDOMAIN-IPv6";
1193 else
1194 dest = "NXDOMAIN";
1195 }
1196 else
1197 {
1198 if (flags & F_IPV4)
1199 dest = "NODATA-IPv4";
1200 else if (flags & F_IPV6)
1201 dest = "NODATA-IPv6";
1202 else
1203 dest = "NODATA";
1204 }
1205 }
1206 else if (flags & F_CNAME)
1207 dest = "<CNAME>";
1208 else if (flags & F_RRNAME)
1209 dest = arg;
1210
1211 if (flags & F_CONFIG)
1212 source = "config";
1213 else if (flags & F_DHCP)
1214 source = "DHCP";
1215 else if (flags & F_HOSTS)
1216 source = arg;
1217 else if (flags & F_UPSTREAM)
1218 source = "reply";
1219 else if (flags & F_SERVER)
1220 {
1221 source = "forwarded";
1222 verb = "to";
1223 }
1224 else if (flags & F_QUERY)
1225 {
1226 source = arg;
1227 verb = "from";
1228 }
1229 else
1230 source = "cached";
1231
1232 if (strlen(name) == 0)
1233 name = ".";
1234
1235 my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
1236 }
1237