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