Home | History | Annotate | Download | only in src
      1 /* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
      2 
      3    This program is free software; you can redistribute it and/or modify
      4    it under the terms of the GNU General Public License as published by
      5    the Free Software Foundation; version 2 dated June, 1991, or
      6    (at your option) version 3 dated 29 June, 2007.
      7 
      8    This program is distributed in the hope that it will be useful,
      9    but WITHOUT ANY WARRANTY; without even the implied warranty of
     10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11    GNU General Public License for more details.
     12 
     13    You should have received a copy of the GNU General Public License
     14    along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15 */
     16 
     17 #include "dnsmasq.h"
     18 
     19 static struct crec *cache_head = NULL, *cache_tail = NULL, **hash_table = NULL;
     20 #ifdef HAVE_DHCP
     21 static struct crec* dhcp_spare = NULL;
     22 #endif
     23 static struct crec* new_chain = NULL;
     24 static int cache_inserted = 0, cache_live_freed = 0, insert_error;
     25 static union bigname* big_free = NULL;
     26 static int bignames_left, hash_size;
     27 static int uid = 0;
     28 static char* addrbuff = NULL;
     29 
     30 /* type->string mapping: this is also used by the name-hash function as a mixing table. */
     31 static const struct {
     32     unsigned int type;
     33     const char* const name;
     34 } typestr[] = {{1, "A"},      {2, "NS"},        {5, "CNAME"},   {6, "SOA"},     {10, "NULL"},
     35                {11, "WKS"},   {12, "PTR"},      {13, "HINFO"},  {15, "MX"},     {16, "TXT"},
     36                {22, "NSAP"},  {23, "NSAP_PTR"}, {24, "SIG"},    {25, "KEY"},    {28, "AAAA"},
     37                {33, "SRV"},   {35, "NAPTR"},    {36, "KX"},     {37, "CERT"},   {38, "A6"},
     38                {39, "DNAME"}, {41, "OPT"},      {48, "DNSKEY"}, {249, "TKEY"},  {250, "TSIG"},
     39                {251, "IXFR"}, {252, "AXFR"},    {253, "MAILB"}, {254, "MAILA"}, {255, "ANY"}};
     40 
     41 static void cache_free(struct crec* crecp);
     42 static void cache_unlink(struct crec* crecp);
     43 static void cache_link(struct crec* crecp);
     44 static void rehash(int size);
     45 static void cache_hash(struct crec* crecp);
     46 
     47 void cache_init(void) {
     48     struct crec* crecp;
     49     int i;
     50 
     51     if (daemon->options & OPT_LOG) addrbuff = safe_malloc(ADDRSTRLEN);
     52 
     53     bignames_left = daemon->cachesize / 10;
     54 
     55     if (daemon->cachesize > 0) {
     56         crecp = safe_malloc(daemon->cachesize * sizeof(struct crec));
     57 
     58         for (i = 0; i < daemon->cachesize; i++, crecp++) {
     59             cache_link(crecp);
     60             crecp->flags = 0;
     61             crecp->uid = uid++;
     62         }
     63     }
     64 
     65     /* create initial hash table*/
     66     rehash(daemon->cachesize);
     67 }
     68 
     69 /* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
     70    but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
     71    will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
     72    expand the table. */
     73 static void rehash(int size) {
     74     struct crec** new, **old, *p, *tmp;
     75     int i, new_size, old_size;
     76 
     77     /* hash_size is a power of two. */
     78     for (new_size = 64; new_size < size / 10; new_size = new_size << 1)
     79         ;
     80 
     81     /* must succeed in getting first instance, failure later is non-fatal */
     82     if (!hash_table)
     83         new = safe_malloc(new_size * sizeof(struct crec*));
     84     else if (new_size <= hash_size || !(new = whine_malloc(new_size * sizeof(struct crec*))))
     85         return;
     86 
     87     for (i = 0; i < new_size; i++) new[i] = NULL;
     88 
     89     old = hash_table;
     90     old_size = hash_size;
     91     hash_table = new;
     92     hash_size = new_size;
     93 
     94     if (old) {
     95         for (i = 0; i < old_size; i++)
     96             for (p = old[i]; p; p = tmp) {
     97                 tmp = p->hash_next;
     98                 cache_hash(p);
     99             }
    100         free(old);
    101     }
    102 }
    103 
    104 static struct crec** hash_bucket(char* name) {
    105     unsigned int c, val = 017465; /* Barker code - minimum self-correlation in cyclic shift */
    106     const unsigned char* mix_tab = (const unsigned char*) typestr;
    107 
    108     while ((c = (unsigned char) *name++)) {
    109         /* don't use tolower and friends here - they may be messed up by LOCALE */
    110         if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
    111         val = ((val << 7) | (val >> (32 - 7))) + (mix_tab[(val + c) & 0x3F] ^ c);
    112     }
    113 
    114     /* hash_size is a power of two */
    115     return hash_table + ((val ^ (val >> 16)) & (hash_size - 1));
    116 }
    117 
    118 static void cache_hash(struct crec* crecp) {
    119     /* maintain an invariant that all entries with F_REVERSE set
    120        are at the start of the hash-chain  and all non-reverse
    121        immortal entries are at the end of the hash-chain.
    122        This allows reverse searches and garbage collection to be optimised */
    123 
    124     struct crec** up = hash_bucket(cache_get_name(crecp));
    125 
    126     if (!(crecp->flags & F_REVERSE)) {
    127         while (*up && ((*up)->flags & F_REVERSE)) up = &((*up)->hash_next);
    128 
    129         if (crecp->flags & F_IMMORTAL)
    130             while (*up && !((*up)->flags & F_IMMORTAL)) up = &((*up)->hash_next);
    131     }
    132     crecp->hash_next = *up;
    133     *up = crecp;
    134 }
    135 
    136 static void cache_free(struct crec* crecp) {
    137     crecp->flags &= ~F_FORWARD;
    138     crecp->flags &= ~F_REVERSE;
    139     crecp->uid = uid++; /* invalidate CNAMES pointing to this. */
    140 
    141     if (cache_tail)
    142         cache_tail->next = crecp;
    143     else
    144         cache_head = crecp;
    145     crecp->prev = cache_tail;
    146     crecp->next = NULL;
    147     cache_tail = crecp;
    148 
    149     /* retrieve big name for further use. */
    150     if (crecp->flags & F_BIGNAME) {
    151         crecp->name.bname->next = big_free;
    152         big_free = crecp->name.bname;
    153         crecp->flags &= ~F_BIGNAME;
    154     }
    155 }
    156 
    157 /* insert a new cache entry at the head of the list (youngest entry) */
    158 static void cache_link(struct crec* crecp) {
    159     if (cache_head) /* check needed for init code */
    160         cache_head->prev = crecp;
    161     crecp->next = cache_head;
    162     crecp->prev = NULL;
    163     cache_head = crecp;
    164     if (!cache_tail) cache_tail = crecp;
    165 }
    166 
    167 /* remove an arbitrary cache entry for promotion */
    168 static void cache_unlink(struct crec* crecp) {
    169     if (crecp->prev)
    170         crecp->prev->next = crecp->next;
    171     else
    172         cache_head = crecp->next;
    173 
    174     if (crecp->next)
    175         crecp->next->prev = crecp->prev;
    176     else
    177         cache_tail = crecp->prev;
    178 }
    179 
    180 char* cache_get_name(struct crec* crecp) {
    181     if (crecp->flags & F_BIGNAME)
    182         return crecp->name.bname->name;
    183     else if (crecp->flags & (F_DHCP | F_CONFIG))
    184         return crecp->name.namep;
    185 
    186     return crecp->name.sname;
    187 }
    188 
    189 static int is_outdated_cname_pointer(struct crec* crecp) {
    190     if (!(crecp->flags & F_CNAME)) return 0;
    191 
    192     if (crecp->addr.cname.cache && crecp->addr.cname.uid == crecp->addr.cname.cache->uid) return 0;
    193 
    194     return 1;
    195 }
    196 
    197 static int is_expired(time_t now, struct crec* crecp) {
    198     if (crecp->flags & F_IMMORTAL) return 0;
    199 
    200     if (difftime(now, crecp->ttd) < 0) return 0;
    201 
    202     return 1;
    203 }
    204 
    205 static int cache_scan_free(char* name, struct all_addr* addr, time_t now, unsigned short flags) {
    206     /* Scan and remove old entries.
    207        If (flags & F_FORWARD) then remove any forward entries for name and any expired
    208        entries but only in the same hash bucket as name.
    209        If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
    210        entries in the whole cache.
    211        If (flags == 0) remove any expired entries in the whole cache.
    212 
    213        In the flags & F_FORWARD case, the return code is valid, and returns zero if the
    214        name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
    215 
    216        We take advantage of the fact that hash chains have stuff in the order
    217        <reverse>,<other>,<immortal> so that when we hit an entry which isn't reverse and is
    218        immortal, we're done. */
    219 
    220     struct crec *crecp, **up;
    221 
    222     if (flags & F_FORWARD) {
    223         for (up = hash_bucket(name), crecp = *up; crecp; crecp = crecp->hash_next)
    224             if (is_expired(now, crecp) || is_outdated_cname_pointer(crecp)) {
    225                 *up = crecp->hash_next;
    226                 if (!(crecp->flags & (F_HOSTS | F_DHCP))) {
    227                     cache_unlink(crecp);
    228                     cache_free(crecp);
    229                 }
    230             } else if ((crecp->flags & F_FORWARD) &&
    231                        ((flags & crecp->flags & (F_IPV4 | F_IPV6)) ||
    232                         ((crecp->flags | flags) & F_CNAME)) &&
    233                        hostname_isequal(cache_get_name(crecp), name)) {
    234                 if (crecp->flags & (F_HOSTS | F_DHCP)) return 0;
    235                 *up = crecp->hash_next;
    236                 cache_unlink(crecp);
    237                 cache_free(crecp);
    238             } else
    239                 up = &crecp->hash_next;
    240     } else {
    241         int i;
    242 #ifdef HAVE_IPV6
    243         int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ;
    244 #else
    245         int addrlen = INADDRSZ;
    246 #endif
    247         for (i = 0; i < hash_size; i++)
    248             for (crecp = hash_table[i], up = &hash_table[i];
    249                  crecp && ((crecp->flags & F_REVERSE) || !(crecp->flags & F_IMMORTAL));
    250                  crecp = crecp->hash_next)
    251                 if (is_expired(now, crecp)) {
    252                     *up = crecp->hash_next;
    253                     if (!(crecp->flags & (F_HOSTS | F_DHCP))) {
    254                         cache_unlink(crecp);
    255                         cache_free(crecp);
    256                     }
    257                 } else if (!(crecp->flags & (F_HOSTS | F_DHCP)) &&
    258                            (flags & crecp->flags & F_REVERSE) &&
    259                            (flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
    260                            memcmp(&crecp->addr.addr, addr, addrlen) == 0) {
    261                     *up = crecp->hash_next;
    262                     cache_unlink(crecp);
    263                     cache_free(crecp);
    264                 } else
    265                     up = &crecp->hash_next;
    266     }
    267 
    268     return 1;
    269 }
    270 
    271 /* Note: The normal calling sequence is
    272    cache_start_insert
    273    cache_insert * n
    274    cache_end_insert
    275 
    276    but an abort can cause the cache_end_insert to be missed
    277    in which can the next cache_start_insert cleans things up. */
    278 
    279 void cache_start_insert(void) {
    280     /* Free any entries which didn't get committed during the last
    281        insert due to error.
    282     */
    283     while (new_chain) {
    284         struct crec* tmp = new_chain->next;
    285         cache_free(new_chain);
    286         new_chain = tmp;
    287     }
    288     new_chain = NULL;
    289     insert_error = 0;
    290 }
    291 
    292 struct crec* cache_insert(char* name, struct all_addr* addr, time_t now, unsigned long ttl,
    293                           unsigned short flags) {
    294     struct crec* new;
    295     union bigname* big_name = NULL;
    296     int freed_all = flags & F_REVERSE;
    297     int free_avail = 0;
    298 
    299     log_query(flags | F_UPSTREAM, name, addr, NULL);
    300 
    301     /* CONFIG bit means something else when stored in cache entries */
    302     flags &= ~F_CONFIG;
    303 
    304     /* if previous insertion failed give up now. */
    305     if (insert_error) return NULL;
    306 
    307     /* First remove any expired entries and entries for the name/address we
    308        are currently inserting. Fail is we attempt to delete a name from
    309        /etc/hosts or DHCP. */
    310     if (!cache_scan_free(name, addr, now, flags)) {
    311         insert_error = 1;
    312         return NULL;
    313     }
    314 
    315     /* Now get a cache entry from the end of the LRU list */
    316     while (1) {
    317         if (!(new = cache_tail)) /* no entries left - cache is too small, bail */
    318         {
    319             insert_error = 1;
    320             return NULL;
    321         }
    322 
    323         /* End of LRU list is still in use: if we didn't scan all the hash
    324            chains for expired entries do that now. If we already tried that
    325            then it's time to start spilling things. */
    326 
    327         if (new->flags&(F_FORWARD | F_REVERSE)) {
    328             /* If free_avail set, we believe that an entry has been freed.
    329                Bugs have been known to make this not true, resulting in
    330                a tight loop here. If that happens, abandon the
    331                insert. Once in this state, all inserts will probably fail. */
    332             if (free_avail) {
    333                 insert_error = 1;
    334                 return NULL;
    335             }
    336 
    337             if (freed_all) {
    338                 free_avail = 1; /* Must be free space now. */
    339                 cache_scan_free(cache_get_name(new), &new->addr.addr, now, new->flags);
    340                 cache_live_freed++;
    341             } else {
    342                 cache_scan_free(NULL, NULL, now, 0);
    343                 freed_all = 1;
    344             }
    345             continue;
    346         }
    347 
    348         /* Check if we need to and can allocate extra memory for a long name.
    349            If that fails, give up now. */
    350         if (name && (strlen(name) > SMALLDNAME - 1)) {
    351             if (big_free) {
    352                 big_name = big_free;
    353                 big_free = big_free->next;
    354             } else if (!bignames_left ||
    355                        !(big_name = (union bigname*) whine_malloc(sizeof(union bigname)))) {
    356                 insert_error = 1;
    357                 return NULL;
    358             } else
    359                 bignames_left--;
    360         }
    361 
    362         /* Got the rest: finally grab entry. */
    363         cache_unlink(new);
    364         break;
    365     }
    366 
    367     new->flags = flags;
    368     if (big_name) {
    369         new->name.bname = big_name;
    370         new->flags |= F_BIGNAME;
    371     }
    372 
    373     if (name)
    374         strcpy(cache_get_name(new), name);
    375     else
    376         *cache_get_name(new) = 0;
    377 
    378     if (addr)
    379         new->addr.addr = *addr;
    380     else
    381         new->addr.cname.cache = NULL;
    382 
    383     new->ttd = now + (time_t) ttl;
    384     new->next = new_chain;
    385     new_chain = new;
    386 
    387     return new;
    388 }
    389 
    390 /* after end of insertion, commit the new entries */
    391 void cache_end_insert(void) {
    392     if (insert_error) return;
    393 
    394     while (new_chain) {
    395         struct crec* tmp = new_chain->next;
    396         /* drop CNAMEs which didn't find a target. */
    397         if (is_outdated_cname_pointer(new_chain))
    398             cache_free(new_chain);
    399         else {
    400             cache_hash(new_chain);
    401             cache_link(new_chain);
    402             cache_inserted++;
    403         }
    404         new_chain = tmp;
    405     }
    406     new_chain = NULL;
    407 }
    408 
    409 struct crec* cache_find_by_name(struct crec* crecp, char* name, time_t now, unsigned short prot) {
    410     struct crec* ans;
    411 
    412     if (crecp) /* iterating */
    413         ans = crecp->next;
    414     else {
    415         /* first search, look for relevant entries and push to top of list
    416        also free anything which has expired */
    417         struct crec *next, **up, **insert = NULL, **chainp = &ans;
    418         int ins_flags = 0;
    419 
    420         for (up = hash_bucket(name), crecp = *up; crecp; crecp = next) {
    421             next = crecp->hash_next;
    422 
    423             if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp)) {
    424                 if ((crecp->flags & F_FORWARD) && (crecp->flags & prot) &&
    425                     hostname_isequal(cache_get_name(crecp), name)) {
    426                     if (crecp->flags & (F_HOSTS | F_DHCP)) {
    427                         *chainp = crecp;
    428                         chainp = &crecp->next;
    429                     } else {
    430                         cache_unlink(crecp);
    431                         cache_link(crecp);
    432                     }
    433 
    434                     /* Move all but the first entry up the hash chain
    435                        this implements round-robin.
    436                        Make sure that re-ordering doesn't break the hash-chain
    437                        order invariants.
    438                     */
    439                     if (insert && (crecp->flags & (F_REVERSE | F_IMMORTAL)) == ins_flags) {
    440                         *up = crecp->hash_next;
    441                         crecp->hash_next = *insert;
    442                         *insert = crecp;
    443                         insert = &crecp->hash_next;
    444                     } else {
    445                         if (!insert) {
    446                             insert = up;
    447                             ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
    448                         }
    449                         up = &crecp->hash_next;
    450                     }
    451                 } else
    452                     /* case : not expired, incorrect entry. */
    453                     up = &crecp->hash_next;
    454             } else {
    455                 /* expired entry, free it */
    456                 *up = crecp->hash_next;
    457                 if (!(crecp->flags & (F_HOSTS | F_DHCP))) {
    458                     cache_unlink(crecp);
    459                     cache_free(crecp);
    460                 }
    461             }
    462         }
    463 
    464         *chainp = cache_head;
    465     }
    466 
    467     if (ans && (ans->flags & F_FORWARD) && (ans->flags & prot) &&
    468         hostname_isequal(cache_get_name(ans), name))
    469         return ans;
    470 
    471     return NULL;
    472 }
    473 
    474 struct crec* cache_find_by_addr(struct crec* crecp, struct all_addr* addr, time_t now,
    475                                 unsigned short prot) {
    476     struct crec* ans;
    477 #ifdef HAVE_IPV6
    478     int addrlen = (prot == F_IPV6) ? IN6ADDRSZ : INADDRSZ;
    479 #else
    480     int addrlen = INADDRSZ;
    481 #endif
    482 
    483     if (crecp) /* iterating */
    484         ans = crecp->next;
    485     else {
    486         /* first search, look for relevant entries and push to top of list
    487        also free anything which has expired. All the reverse entries are at the
    488        start of the hash chain, so we can give up when we find the first
    489        non-REVERSE one.  */
    490         int i;
    491         struct crec **up, **chainp = &ans;
    492 
    493         for (i = 0; i < hash_size; i++)
    494             for (crecp = hash_table[i], up = &hash_table[i]; crecp && (crecp->flags & F_REVERSE);
    495                  crecp = crecp->hash_next)
    496                 if (!is_expired(now, crecp)) {
    497                     if ((crecp->flags & prot) && memcmp(&crecp->addr.addr, addr, addrlen) == 0) {
    498                         if (crecp->flags & (F_HOSTS | F_DHCP)) {
    499                             *chainp = crecp;
    500                             chainp = &crecp->next;
    501                         } else {
    502                             cache_unlink(crecp);
    503                             cache_link(crecp);
    504                         }
    505                     }
    506                     up = &crecp->hash_next;
    507                 } else {
    508                     *up = crecp->hash_next;
    509                     if (!(crecp->flags & (F_HOSTS | F_DHCP))) {
    510                         cache_unlink(crecp);
    511                         cache_free(crecp);
    512                     }
    513                 }
    514 
    515         *chainp = cache_head;
    516     }
    517 
    518     if (ans && (ans->flags & F_REVERSE) && (ans->flags & prot) &&
    519         memcmp(&ans->addr.addr, addr, addrlen) == 0)
    520         return ans;
    521 
    522     return NULL;
    523 }
    524 
    525 static void add_hosts_entry(struct crec* cache, struct all_addr* addr, int addrlen,
    526                             unsigned short flags, int index, int addr_dup) {
    527     struct crec* lookup = cache_find_by_name(NULL, cache->name.sname, 0, flags & (F_IPV4 | F_IPV6));
    528     int i, nameexists = 0;
    529     struct cname* a;
    530 
    531     /* Remove duplicates in hosts files. */
    532     if (lookup && (lookup->flags & F_HOSTS)) {
    533         nameexists = 1;
    534         if (memcmp(&lookup->addr.addr, addr, addrlen) == 0) {
    535             free(cache);
    536             return;
    537         }
    538     }
    539 
    540     /* Ensure there is only one address -> name mapping (first one trumps)
    541        We do this by steam here, first we see if the address is the same as
    542        the last one we saw, which eliminates most in the case of an ad-block
    543        file with thousands of entries for the same address.
    544        Then we search and bail at the first matching address that came from
    545        a HOSTS file. Since the first host entry gets reverse, we know
    546        then that it must exist without searching exhaustively for it. */
    547 
    548     if (addr_dup)
    549         flags &= ~F_REVERSE;
    550     else
    551         for (i = 0; i < hash_size; i++) {
    552             for (lookup = hash_table[i]; lookup; lookup = lookup->hash_next)
    553                 if ((lookup->flags & F_HOSTS) && (lookup->flags & flags & (F_IPV4 | F_IPV6)) &&
    554                     memcmp(&lookup->addr.addr, addr, addrlen) == 0) {
    555                     flags &= ~F_REVERSE;
    556                     break;
    557                 }
    558             if (lookup) break;
    559         }
    560 
    561     cache->flags = flags;
    562     cache->uid = index;
    563     memcpy(&cache->addr.addr, addr, addrlen);
    564     cache_hash(cache);
    565 
    566     /* don't need to do alias stuff for second and subsequent addresses. */
    567     if (!nameexists)
    568         for (a = daemon->cnames; a; a = a->next)
    569             if (hostname_isequal(cache->name.sname, a->target) &&
    570                 (lookup = whine_malloc(sizeof(struct crec)))) {
    571                 lookup->flags = F_FORWARD | F_IMMORTAL | F_CONFIG | F_HOSTS | F_CNAME;
    572                 lookup->name.namep = a->alias;
    573                 lookup->addr.cname.cache = cache;
    574                 lookup->addr.cname.uid = index;
    575                 cache_hash(lookup);
    576             }
    577 }
    578 
    579 static int eatspace(FILE* f) {
    580     int c, nl = 0;
    581 
    582     while (1) {
    583         if ((c = getc(f)) == '#')
    584             while (c != '\n' && c != EOF) c = getc(f);
    585 
    586         if (c == EOF) return 1;
    587 
    588         if (!isspace(c)) {
    589             ungetc(c, f);
    590             return nl;
    591         }
    592 
    593         if (c == '\n') nl = 1;
    594     }
    595 }
    596 
    597 static int gettok(FILE* f, char* token) {
    598     int c, count = 0;
    599 
    600     while (1) {
    601         if ((c = getc(f)) == EOF) return (count == 0) ? EOF : 1;
    602 
    603         if (isspace(c) || c == '#') {
    604             ungetc(c, f);
    605             return eatspace(f);
    606         }
    607 
    608         if (count < (MAXDNAME - 1)) {
    609             token[count++] = c;
    610             token[count] = 0;
    611         }
    612     }
    613 }
    614 
    615 static int read_hostsfile(char* filename, int index, int cache_size) {
    616     FILE* f = fopen(filename, "r");
    617     char *token = daemon->namebuff, *domain_suffix = NULL;
    618     int addr_count = 0, name_count = cache_size, lineno = 0;
    619     unsigned short flags = 0, saved_flags = 0;
    620     struct all_addr addr, saved_addr;
    621     int atnl, addrlen = 0, addr_dup;
    622 
    623     if (!f) {
    624         my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
    625         return 0;
    626     }
    627 
    628     eatspace(f);
    629 
    630     while ((atnl = gettok(f, token)) != EOF) {
    631         addr_dup = 0;
    632         lineno++;
    633 
    634 #ifdef HAVE_IPV6
    635         if (inet_pton(AF_INET, token, &addr) > 0) {
    636             flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
    637             addrlen = INADDRSZ;
    638             domain_suffix = get_domain(addr.addr.addr4);
    639         } else if (inet_pton(AF_INET6, token, &addr) > 0) {
    640             flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
    641             addrlen = IN6ADDRSZ;
    642             domain_suffix = daemon->domain_suffix;
    643         }
    644 #else
    645         if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1) {
    646             flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
    647             addrlen = INADDRSZ;
    648             domain_suffix = get_domain(addr.addr.addr4);
    649         }
    650 #endif
    651         else {
    652             my_syslog(LOG_ERR, _("bad address at %s line %d"), filename, lineno);
    653             while (atnl == 0) atnl = gettok(f, token);
    654             continue;
    655         }
    656 
    657         if (saved_flags == flags && memcmp(&addr, &saved_addr, addrlen) == 0)
    658             addr_dup = 1;
    659         else {
    660             saved_flags = flags;
    661             saved_addr = addr;
    662         }
    663 
    664         addr_count++;
    665 
    666         /* rehash every 1000 names. */
    667         if ((name_count - cache_size) > 1000) {
    668             rehash(name_count);
    669             cache_size = name_count;
    670         }
    671 
    672         while (atnl == 0) {
    673             struct crec* cache;
    674             int fqdn, nomem;
    675             char* canon;
    676 
    677             if ((atnl = gettok(f, token)) == EOF) break;
    678 
    679             fqdn = !!strchr(token, '.');
    680 
    681             if ((canon = canonicalise(token, &nomem))) {
    682                 /* If set, add a version of the name with a default domain appended */
    683                 if ((daemon->options & OPT_EXPAND) && domain_suffix && !fqdn &&
    684                     (cache = whine_malloc(sizeof(struct crec) + strlen(canon) + 2 +
    685                                           strlen(domain_suffix) - SMALLDNAME))) {
    686                     strcpy(cache->name.sname, canon);
    687                     strcat(cache->name.sname, ".");
    688                     strcat(cache->name.sname, domain_suffix);
    689                     add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
    690                     addr_dup = 1;
    691                     name_count++;
    692                 }
    693                 if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon) + 1 - SMALLDNAME))) {
    694                     strcpy(cache->name.sname, canon);
    695                     add_hosts_entry(cache, &addr, addrlen, flags, index, addr_dup);
    696                     name_count++;
    697                 }
    698                 free(canon);
    699 
    700             } else if (!nomem)
    701                 my_syslog(LOG_ERR, _("bad name at %s line %d"), filename, lineno);
    702         }
    703     }
    704 
    705     fclose(f);
    706     rehash(name_count);
    707 
    708     my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
    709 
    710     return name_count;
    711 }
    712 
    713 void cache_reload(void) {
    714     struct crec *cache, **up, *tmp;
    715     int i, total_size = daemon->cachesize;
    716     struct hostsfile* ah;
    717 
    718     cache_inserted = cache_live_freed = 0;
    719 
    720     for (i = 0; i < hash_size; i++)
    721         for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp) {
    722             tmp = cache->hash_next;
    723             if (cache->flags & F_HOSTS) {
    724                 *up = cache->hash_next;
    725                 free(cache);
    726             } else if (!(cache->flags & F_DHCP)) {
    727                 *up = cache->hash_next;
    728                 if (cache->flags & F_BIGNAME) {
    729                     cache->name.bname->next = big_free;
    730                     big_free = cache->name.bname;
    731                 }
    732                 cache->flags = 0;
    733             } else
    734                 up = &cache->hash_next;
    735         }
    736 
    737     if ((daemon->options & OPT_NO_HOSTS) && !daemon->addn_hosts) {
    738         if (daemon->cachesize > 0) my_syslog(LOG_INFO, _("cleared cache"));
    739         return;
    740     }
    741 
    742     if (!(daemon->options & OPT_NO_HOSTS)) total_size = read_hostsfile(HOSTSFILE, 0, total_size);
    743 
    744     for (i = 0, ah = daemon->addn_hosts; ah; ah = ah->next) {
    745         if (i <= ah->index) i = ah->index + 1;
    746 
    747         if (ah->flags & AH_DIR)
    748             ah->flags |= AH_INACTIVE;
    749         else
    750             ah->flags &= ~AH_INACTIVE;
    751     }
    752 
    753     for (ah = daemon->addn_hosts; ah; ah = ah->next)
    754         if (!(ah->flags & AH_INACTIVE)) {
    755             struct stat buf;
    756             if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode)) {
    757                 DIR* dir_stream;
    758                 struct dirent* ent;
    759 
    760                 /* don't read this as a file */
    761                 ah->flags |= AH_INACTIVE;
    762 
    763                 if (!(dir_stream = opendir(ah->fname)))
    764                     my_syslog(LOG_ERR, _("cannot access directory %s: %s"), ah->fname,
    765                               strerror(errno));
    766                 else {
    767                     while ((ent = readdir(dir_stream))) {
    768                         size_t lendir = strlen(ah->fname);
    769                         size_t lenfile = strlen(ent->d_name);
    770                         struct hostsfile* ah1;
    771                         char* path;
    772 
    773                         /* ignore emacs backups and dotfiles */
    774                         if (lenfile == 0 || ent->d_name[lenfile - 1] == '~' ||
    775                             (ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
    776                             ent->d_name[0] == '.')
    777                             continue;
    778 
    779                         /* see if we have an existing record.
    780                            dir is ah->fname
    781                            file is ent->d_name
    782                            path to match is ah1->fname */
    783 
    784                         for (ah1 = daemon->addn_hosts; ah1; ah1 = ah1->next) {
    785                             if (lendir < strlen(ah1->fname) &&
    786                                 strstr(ah1->fname, ah->fname) == ah1->fname &&
    787                                 ah1->fname[lendir] == '/' &&
    788                                 strcmp(ah1->fname + lendir + 1, ent->d_name) == 0) {
    789                                 ah1->flags &= ~AH_INACTIVE;
    790                                 break;
    791                             }
    792                         }
    793 
    794                         /* make new record */
    795                         if (!ah1) {
    796                             if (!(ah1 = whine_malloc(sizeof(struct hostsfile)))) continue;
    797 
    798                             if (!(path = whine_malloc(lendir + lenfile + 2))) {
    799                                 free(ah1);
    800                                 continue;
    801                             }
    802 
    803                             strcpy(path, ah->fname);
    804                             strcat(path, "/");
    805                             strcat(path, ent->d_name);
    806                             ah1->fname = path;
    807                             ah1->index = i++;
    808                             ah1->flags = AH_DIR;
    809                             ah1->next = daemon->addn_hosts;
    810                             daemon->addn_hosts = ah1;
    811                         }
    812 
    813                         /* inactivate record if not regular file */
    814                         if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 &&
    815                             !S_ISREG(buf.st_mode))
    816                             ah1->flags |= AH_INACTIVE;
    817                     }
    818                     closedir(dir_stream);
    819                 }
    820             }
    821         }
    822 
    823     for (ah = daemon->addn_hosts; ah; ah = ah->next)
    824         if (!(ah->flags & AH_INACTIVE))
    825             total_size = read_hostsfile(ah->fname, ah->index, total_size);
    826 }
    827 
    828 char* get_domain(struct in_addr addr) {
    829     struct cond_domain* c;
    830 
    831     for (c = daemon->cond_domain; c; c = c->next)
    832         if (ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
    833             ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
    834             return c->domain;
    835 
    836     return daemon->domain_suffix;
    837 }
    838 
    839 #ifdef HAVE_DHCP
    840 void cache_unhash_dhcp(void) {
    841     struct crec *cache, **up;
    842     int i;
    843 
    844     for (i = 0; i < hash_size; i++)
    845         for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next)
    846             if (cache->flags & F_DHCP) {
    847                 *up = cache->hash_next;
    848                 cache->next = dhcp_spare;
    849                 dhcp_spare = cache;
    850             } else
    851                 up = &cache->hash_next;
    852 }
    853 
    854 void cache_add_dhcp_entry(char* host_name, struct in_addr* host_address, time_t ttd) {
    855     struct crec *crec = NULL, *aliasc;
    856     unsigned short flags = F_DHCP | F_FORWARD | F_IPV4 | F_REVERSE;
    857     int in_hosts = 0;
    858     struct cname* a;
    859 
    860     while ((crec = cache_find_by_name(crec, host_name, 0, F_IPV4 | F_CNAME))) {
    861         /* check all addresses associated with name */
    862         if (crec->flags & F_HOSTS) {
    863             if (crec->addr.addr.addr.addr4.s_addr != host_address->s_addr) {
    864                 strcpy(daemon->namebuff, inet_ntoa(crec->addr.addr.addr.addr4));
    865                 my_syslog(LOG_WARNING,
    866                           _("not giving name %s to the DHCP lease of %s because "
    867                             "the name exists in %s with address %s"),
    868                           host_name, inet_ntoa(*host_address), record_source(crec->uid),
    869                           daemon->namebuff);
    870                 return;
    871             } else
    872                 /* if in hosts, don't need DHCP record */
    873                 in_hosts = 1;
    874         } else if (!(crec->flags & F_DHCP)) {
    875             cache_scan_free(host_name, NULL, 0, crec->flags & (F_IPV4 | F_CNAME | F_FORWARD));
    876             /* scan_free deletes all addresses associated with name */
    877             break;
    878         }
    879     }
    880 
    881     if (in_hosts) return;
    882 
    883     if ((crec = cache_find_by_addr(NULL, (struct all_addr*) host_address, 0, F_IPV4))) {
    884         if (crec->flags & F_NEG)
    885             cache_scan_free(NULL, (struct all_addr*) host_address, 0, F_IPV4 | F_REVERSE);
    886         else
    887             /* avoid multiple reverse mappings */
    888             flags &= ~F_REVERSE;
    889     }
    890 
    891     if ((crec = dhcp_spare))
    892         dhcp_spare = dhcp_spare->next;
    893     else /* need new one */
    894         crec = whine_malloc(sizeof(struct crec));
    895 
    896     if (crec) /* malloc may fail */
    897     {
    898         crec->flags = flags;
    899         if (ttd == 0)
    900             crec->flags |= F_IMMORTAL;
    901         else
    902             crec->ttd = ttd;
    903         crec->addr.addr.addr.addr4 = *host_address;
    904         crec->name.namep = host_name;
    905         crec->uid = uid++;
    906         cache_hash(crec);
    907 
    908         for (a = daemon->cnames; a; a = a->next)
    909             if (hostname_isequal(host_name, a->target)) {
    910                 if ((aliasc = dhcp_spare))
    911                     dhcp_spare = dhcp_spare->next;
    912                 else /* need new one */
    913                     aliasc = whine_malloc(sizeof(struct crec));
    914 
    915                 if (aliasc) {
    916                     aliasc->flags = F_FORWARD | F_CONFIG | F_DHCP | F_CNAME;
    917                     if (ttd == 0)
    918                         aliasc->flags |= F_IMMORTAL;
    919                     else
    920                         aliasc->ttd = ttd;
    921                     aliasc->name.namep = a->alias;
    922                     aliasc->addr.cname.cache = crec;
    923                     aliasc->addr.cname.uid = crec->uid;
    924                     cache_hash(aliasc);
    925                 }
    926             }
    927     }
    928 }
    929 #endif
    930 
    931 void dump_cache(time_t now) {
    932     struct server *serv, *serv1;
    933 
    934     my_syslog(LOG_INFO, _("time %lu"), (unsigned long) now);
    935     my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
    936               daemon->cachesize, cache_live_freed, cache_inserted);
    937     my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
    938               daemon->queries_forwarded, daemon->local_answer);
    939 
    940     if (!addrbuff && !(addrbuff = whine_malloc(ADDRSTRLEN))) return;
    941 
    942     /* sum counts from different records for same server */
    943     for (serv = daemon->servers; serv; serv = serv->next) serv->flags &= ~SERV_COUNTED;
    944 
    945     for (serv = daemon->servers; serv; serv = serv->next)
    946         if (!(serv->flags & (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED))) {
    947             int port;
    948             unsigned int queries = 0, failed_queries = 0;
    949             for (serv1 = serv; serv1; serv1 = serv1->next)
    950                 if (!(serv1->flags & (SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED)) &&
    951                     sockaddr_isequal(&serv->addr, &serv1->addr)) {
    952                     serv1->flags |= SERV_COUNTED;
    953                     queries += serv1->queries;
    954                     failed_queries += serv1->failed_queries;
    955                 }
    956             port = prettyprint_addr(&serv->addr, addrbuff);
    957             my_syslog(LOG_INFO, _("server %s#%d: queries sent %u, retried or failed %u"), addrbuff,
    958                       port, queries, failed_queries);
    959         }
    960 
    961     if ((daemon->options & (OPT_DEBUG | OPT_LOG))) {
    962         struct crec* cache;
    963         int i;
    964         my_syslog(LOG_DEBUG,
    965                   "Host                                     Address                        Flags   "
    966                   "  Expires");
    967 
    968         for (i = 0; i < hash_size; i++)
    969             for (cache = hash_table[i]; cache; cache = cache->hash_next) {
    970                 char *a, *p = daemon->namebuff;
    971                 p += sprintf(p, "%-40.40s ", cache_get_name(cache));
    972                 if ((cache->flags & F_NEG) && (cache->flags & F_FORWARD))
    973                     a = "";
    974                 else if (cache->flags & F_CNAME) {
    975                     a = "";
    976                     if (!is_outdated_cname_pointer(cache))
    977                         a = cache_get_name(cache->addr.cname.cache);
    978                 }
    979 #ifdef HAVE_IPV6
    980                 else {
    981                     a = addrbuff;
    982                     if (cache->flags & F_IPV4)
    983                         inet_ntop(AF_INET, &cache->addr.addr, addrbuff, ADDRSTRLEN);
    984                     else if (cache->flags & F_IPV6)
    985                         inet_ntop(AF_INET6, &cache->addr.addr, addrbuff, ADDRSTRLEN);
    986                 }
    987 #else
    988                 else
    989                     a = inet_ntoa(cache->addr.addr.addr.addr4);
    990 #endif
    991                 p += sprintf(
    992                     p, "%-30.30s %s%s%s%s%s%s%s%s%s%s  ", a, cache->flags & F_IPV4 ? "4" : "",
    993                     cache->flags & F_IPV6 ? "6" : "", cache->flags & F_CNAME ? "C" : "",
    994                     cache->flags & F_FORWARD ? "F" : " ", cache->flags & F_REVERSE ? "R" : " ",
    995                     cache->flags & F_IMMORTAL ? "I" : " ", cache->flags & F_DHCP ? "D" : " ",
    996                     cache->flags & F_NEG ? "N" : " ", cache->flags & F_NXDOMAIN ? "X" : " ",
    997                     cache->flags & F_HOSTS ? "H" : " ");
    998 #ifdef HAVE_BROKEN_RTC
    999                 p += sprintf(p, "%lu",
   1000                              cache->flags & F_IMMORTAL ? 0 : (unsigned long) (cache->ttd - now));
   1001 #else
   1002                 p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd)));
   1003                 /* ctime includes trailing \n - eat it */
   1004                 *(p - 1) = 0;
   1005 #endif
   1006                 my_syslog(LOG_DEBUG, daemon->namebuff);
   1007             }
   1008     }
   1009 }
   1010 
   1011 char* record_source(int index) {
   1012     struct hostsfile* ah;
   1013 
   1014     if (index == 0) return HOSTSFILE;
   1015 
   1016     for (ah = daemon->addn_hosts; ah; ah = ah->next)
   1017         if (ah->index == index) return ah->fname;
   1018 
   1019     return "<unknown>";
   1020 }
   1021 
   1022 void querystr(char* str, unsigned short type) {
   1023     unsigned int i;
   1024 
   1025     sprintf(str, "query[type=%d]", type);
   1026     for (i = 0; i < (sizeof(typestr) / sizeof(typestr[0])); i++)
   1027         if (typestr[i].type == type) sprintf(str, "query[%s]", typestr[i].name);
   1028 }
   1029 
   1030 void log_query(unsigned short flags, char* name, struct all_addr* addr, char* arg) {
   1031     char *source, *dest = addrbuff;
   1032     char* verb = "is";
   1033 
   1034     if (!(daemon->options & OPT_LOG)) return;
   1035 
   1036     if (addr) {
   1037 #ifdef HAVE_IPV6
   1038         /* TODO: support scoped addresses. struct all_addr doesn't store scope IDs. */
   1039         inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6, addr, addrbuff, ADDRSTRLEN);
   1040 #else
   1041         strncpy(addrbuff, inet_ntoa(addr->addr.addr4), ADDRSTRLEN);
   1042 #endif
   1043     }
   1044 
   1045     if (flags & F_REVERSE) {
   1046         dest = name;
   1047         name = addrbuff;
   1048     }
   1049 
   1050     if (flags & F_NEG) {
   1051         if (flags & F_NXDOMAIN) {
   1052             if (flags & F_IPV4)
   1053                 dest = "NXDOMAIN-IPv4";
   1054             else if (flags & F_IPV6)
   1055                 dest = "NXDOMAIN-IPv6";
   1056             else
   1057                 dest = "NXDOMAIN";
   1058         } else {
   1059             if (flags & F_IPV4)
   1060                 dest = "NODATA-IPv4";
   1061             else if (flags & F_IPV6)
   1062                 dest = "NODATA-IPv6";
   1063             else
   1064                 dest = "NODATA";
   1065         }
   1066     } else if (flags & F_CNAME) {
   1067         /* nasty abuse of NXDOMAIN and CNAME flags */
   1068         if (flags & F_NXDOMAIN)
   1069             dest = arg;
   1070         else
   1071             dest = "<CNAME>";
   1072     }
   1073 
   1074     if (flags & F_CONFIG)
   1075         source = "config";
   1076     else if (flags & F_DHCP)
   1077         source = "DHCP";
   1078     else if (flags & F_HOSTS)
   1079         source = arg;
   1080     else if (flags & F_UPSTREAM)
   1081         source = "reply";
   1082     else if (flags & F_SERVER) {
   1083         source = "forwarded";
   1084         verb = "to";
   1085     } else if (flags & F_QUERY) {
   1086         source = arg;
   1087         verb = "from";
   1088     } else
   1089         source = "cached";
   1090 
   1091     if (strlen(name) == 0) name = ".";
   1092 
   1093     my_syslog(LOG_DEBUG, "%s %s %s %s", source, name, verb, dest);
   1094 }
   1095