File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / cache.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:56:46 2021 UTC (3 years, 4 months ago) by misho
Branches: elwix, dnsmasq, MAIN
CVS tags: v2_84, HEAD
dnsmasq 2.84

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>