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