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