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