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