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