File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / cache.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:02:07 2023 UTC (9 months, 2 weeks ago) by misho
Branches: elwix, dnsmasq, MAIN
CVS tags: v8_2p1, HEAD
Version 8.2p1

    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>