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