]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/cache.c
1 /* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
15 static struct crec
*cache_head
, *cache_tail
, **hash_table
;
16 static struct crec
*dhcp_spare
, *new_chain
;
17 static int cache_inserted
, cache_live_freed
, insert_error
;
18 static union bigname
*big_free
;
19 static int bignames_left
, log_queries
, cache_size
, hash_size
;
21 static char *addrbuff
;
23 /* type->string mapping: this is also used by the name-hash function as a mixing table. */
26 const char * const name
;
59 static void cache_free(struct crec
*crecp
);
60 static void cache_unlink(struct crec
*crecp
);
61 static void cache_link(struct crec
*crecp
);
62 static char *record_source(struct hostsfile
*add_hosts
, int index
);
63 static void rehash(int size
);
64 static void cache_hash(struct crec
*crecp
);
66 void cache_init(int size
, int logq
)
71 if ((log_queries
= logq
))
72 addrbuff
= safe_malloc(ADDRSTRLEN
);
76 cache_head
= cache_tail
= NULL
;
82 bignames_left
= size
/10;
85 cache_inserted
= cache_live_freed
= 0;
89 crecp
= safe_malloc(size
*sizeof(struct crec
));
91 for (i
=0; i
<size
; i
++, crecp
++)
99 /* create initial hash table*/
103 /* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
104 but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
105 will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
107 static void rehash(int size
)
109 struct crec
**new, **old
, *p
, *tmp
;
110 int i
, new_size
, old_size
;
112 /* hash_size is a power of two. */
113 for (new_size
= 64; new_size
< size
/10; new_size
= new_size
<< 1);
115 /* must succeed in getting first instance, failure later is non-fatal */
117 new = safe_malloc(new_size
* sizeof(struct crec
*));
118 else if (new_size
<= hash_size
|| !(new = malloc(new_size
* sizeof(struct crec
*))))
121 for(i
= 0; i
< new_size
; i
++)
125 old_size
= hash_size
;
127 hash_size
= new_size
;
131 for (i
= 0; i
< old_size
; i
++)
132 for (p
= old
[i
]; p
; p
= tmp
)
141 static struct crec
**hash_bucket(char *name
)
143 unsigned int c
, val
= 017465; /* Barker code - minimum self-correlation in cyclic shift */
144 const unsigned char *mix_tab
= (const unsigned char*)typestr
;
146 while((c
= (unsigned char) *name
++))
148 /* don't use tolower and friends here - they may be messed up by LOCALE */
149 if (c
>= 'A' && c
<= 'Z')
151 val
= ((val
<< 7) | (val
>> (32 - 7))) + (mix_tab
[(val
+ c
) & 0x3F] ^ c
);
154 /* hash_size is a power of two */
155 return hash_table
+ ((val
^ (val
>> 16)) & (hash_size
- 1));
158 static void cache_hash(struct crec
*crecp
)
160 /* maintain an invariant that all entries with F_REVERSE set
161 are at the start of the hash-chain and all non-reverse
162 immortal entries are at the end of the hash-chain.
163 This allows reverse searches and garbage collection to be optimised */
165 struct crec
**up
= hash_bucket(cache_get_name(crecp
));
167 if (!(crecp
->flags
& F_REVERSE
))
169 while (*up
&& ((*up
)->flags
& F_REVERSE
))
170 up
= &((*up
)->hash_next
);
172 if (crecp
->flags
& F_IMMORTAL
)
173 while (*up
&& !((*up
)->flags
& F_IMMORTAL
))
174 up
= &((*up
)->hash_next
);
176 crecp
->hash_next
= *up
;
180 static void cache_free(struct crec
*crecp
)
182 crecp
->flags
&= ~F_FORWARD
;
183 crecp
->flags
&= ~F_REVERSE
;
184 crecp
->uid
= uid
++; /* invalidate CNAMES pointing to this. */
187 cache_tail
->next
= crecp
;
190 crecp
->prev
= cache_tail
;
194 /* retrieve big name for further use. */
195 if (crecp
->flags
& F_BIGNAME
)
197 crecp
->name
.bname
->next
= big_free
;
198 big_free
= crecp
->name
.bname
;
199 crecp
->flags
&= ~F_BIGNAME
;
203 /* insert a new cache entry at the head of the list (youngest entry) */
204 static void cache_link(struct crec
*crecp
)
206 if (cache_head
) /* check needed for init code */
207 cache_head
->prev
= crecp
;
208 crecp
->next
= cache_head
;
215 /* remove an arbitrary cache entry for promotion */
216 static void cache_unlink (struct crec
*crecp
)
219 crecp
->prev
->next
= crecp
->next
;
221 cache_head
= crecp
->next
;
224 crecp
->next
->prev
= crecp
->prev
;
226 cache_tail
= crecp
->prev
;
229 char *cache_get_name(struct crec
*crecp
)
231 if (crecp
->flags
& F_BIGNAME
)
232 return crecp
->name
.bname
->name
;
233 else if (crecp
->flags
& F_DHCP
)
234 return crecp
->name
.namep
;
236 return crecp
->name
.sname
;
239 static int is_outdated_cname_pointer(struct crec
*crecp
)
241 struct crec
*target
= crecp
->addr
.cname
.cache
;
243 if (!(crecp
->flags
& F_CNAME
))
249 if (crecp
->addr
.cname
.uid
== target
->uid
)
255 static int is_expired(time_t now
, struct crec
*crecp
)
257 if (crecp
->flags
& F_IMMORTAL
)
260 if (difftime(now
, crecp
->ttd
) < 0)
266 static int cache_scan_free(char *name
, struct all_addr
*addr
, time_t now
, unsigned short flags
)
268 /* Scan and remove old entries.
269 If (flags & F_FORWARD) then remove any forward entries for name and any expired
270 entries but only in the same hash bucket as name.
271 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
272 entries in the whole cache.
273 If (flags == 0) remove any expired entries in the whole cache.
275 In the flags & F_FORWARD case, the return code is valid, and returns zero if the
276 name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
278 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
279 so that when we hit an entry which isn't reverse and is immortal, we're done. */
281 struct crec
*crecp
, **up
;
283 if (flags
& F_FORWARD
)
285 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= crecp
->hash_next
)
286 if (is_expired(now
, crecp
) || is_outdated_cname_pointer(crecp
))
288 *up
= crecp
->hash_next
;
289 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
295 else if ((crecp
->flags
& F_FORWARD
) &&
296 ((flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) || ((crecp
->flags
| flags
) & F_CNAME
)) &&
297 hostname_isequal(cache_get_name(crecp
), name
))
299 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
301 *up
= crecp
->hash_next
;
306 up
= &crecp
->hash_next
;
312 int addrlen
= (flags
& F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
314 int addrlen
= INADDRSZ
;
316 for (i
= 0; i
< hash_size
; i
++)
317 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
318 crecp
&& ((crecp
->flags
& F_REVERSE
) || !(crecp
->flags
& F_IMMORTAL
));
319 crecp
= crecp
->hash_next
)
320 if (is_expired(now
, crecp
))
322 *up
= crecp
->hash_next
;
323 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
329 else if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)) &&
330 (flags
& crecp
->flags
& F_REVERSE
) &&
331 (flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) &&
332 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
334 *up
= crecp
->hash_next
;
339 up
= &crecp
->hash_next
;
345 /* Note: The normal calling sequence is
350 but an abort can cause the cache_end_insert to be missed
351 in which can the next cache_start_insert cleans things up. */
353 void cache_start_insert(void)
355 /* Free any entries which didn't get committed during the last
360 struct crec
*tmp
= new_chain
->next
;
361 cache_free(new_chain
);
368 struct crec
*cache_insert(char *name
, struct all_addr
*addr
,
369 time_t now
, unsigned long ttl
, unsigned short flags
)
372 int addrlen
= (flags
& F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
374 int addrlen
= INADDRSZ
;
377 union bigname
*big_name
= NULL
;
378 int freed_all
= flags
& F_REVERSE
;
380 log_query(flags
| F_UPSTREAM
, name
, addr
, 0, NULL
, 0);
382 /* name is needed as workspace by log_query in this case */
383 if ((flags
& F_NEG
) && (flags
& F_REVERSE
))
386 /* CONFIG bit no needed except for logging */
389 /* if previous insertion failed give up now. */
393 /* First remove any expired entries and entries for the name/address we
394 are currently inserting. Fail is we attempt to delete a name from
395 /etc/hosts or DHCP. */
396 if (!cache_scan_free(name
, addr
, now
, flags
))
402 /* Now get a cache entry from the end of the LRU list */
404 if (!(new = cache_tail
)) /* no entries left - cache is too small, bail */
410 /* End of LRU list is still in use: if we didn't scan all the hash
411 chains for expired entries do that now. If we already tried that
412 then it's time to start spilling things. */
414 if (new->flags
& (F_FORWARD
| F_REVERSE
))
418 cache_scan_free(cache_get_name(new), &new->addr
.addr
, now
, new->flags
);
423 cache_scan_free(NULL
, NULL
, now
, 0);
429 /* Check if we need to and can allocate extra memory for a long name.
430 If that fails, give up now. */
431 if (name
&& (strlen(name
) > SMALLDNAME
-1))
436 big_free
= big_free
->next
;
438 else if (!bignames_left
||
439 !(big_name
= (union bigname
*)malloc(sizeof(union bigname
))))
449 /* Got the rest: finally grab entry. */
457 new->name
.bname
= big_name
;
458 new->flags
|= F_BIGNAME
;
461 strcpy(cache_get_name(new), name
);
463 *cache_get_name(new) = 0;
465 memcpy(&new->addr
.addr
, addr
, addrlen
);
467 new->addr
.cname
.cache
= NULL
;
469 new->ttd
= now
+ (time_t)ttl
;
470 new->next
= new_chain
;
476 /* after end of insertion, commit the new entries */
477 void cache_end_insert(void)
484 struct crec
*tmp
= new_chain
->next
;
485 /* drop CNAMEs which didn't find a target. */
486 if (is_outdated_cname_pointer(new_chain
))
487 cache_free(new_chain
);
490 cache_hash(new_chain
);
491 cache_link(new_chain
);
499 struct crec
*cache_find_by_name(struct crec
*crecp
, char *name
, time_t now
, unsigned short prot
)
503 if (crecp
) /* iterating */
507 /* first search, look for relevant entries and push to top of list
508 also free anything which has expired */
509 struct crec
*next
, **up
, **insert
= NULL
, **chainp
= &ans
;
511 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= next
)
513 next
= crecp
->hash_next
;
515 if (!is_expired(now
, crecp
) && !is_outdated_cname_pointer(crecp
))
517 if ((crecp
->flags
& F_FORWARD
) &&
518 (crecp
->flags
& prot
) &&
519 hostname_isequal(cache_get_name(crecp
), name
))
521 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
524 chainp
= &crecp
->next
;
532 /* move all but the first entry up the hash chain
533 this implements round-robin */
537 up
= &crecp
->hash_next
;
541 *up
= crecp
->hash_next
;
542 crecp
->hash_next
= *insert
;
544 insert
= &crecp
->hash_next
;
548 /* case : not expired, incorrect entry. */
549 up
= &crecp
->hash_next
;
553 /* expired entry, free it */
554 *up
= crecp
->hash_next
;
555 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
563 *chainp
= cache_head
;
567 (ans
->flags
& F_FORWARD
) &&
568 (ans
->flags
& prot
) &&
569 hostname_isequal(cache_get_name(ans
), name
))
575 struct crec
*cache_find_by_addr(struct crec
*crecp
, struct all_addr
*addr
,
576 time_t now
, unsigned short prot
)
580 int addrlen
= (prot
== F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
582 int addrlen
= INADDRSZ
;
585 if (crecp
) /* iterating */
589 /* first search, look for relevant entries and push to top of list
590 also free anything which has expired. All the reverse entries are at the
591 start of the hash chain, so we can give up when we find the first
594 struct crec
**up
, **chainp
= &ans
;
596 for (i
=0; i
<hash_size
; i
++)
597 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
598 crecp
&& (crecp
->flags
& F_REVERSE
);
599 crecp
= crecp
->hash_next
)
600 if (!is_expired(now
, crecp
))
602 if ((crecp
->flags
& prot
) &&
603 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
605 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
608 chainp
= &crecp
->next
;
616 up
= &crecp
->hash_next
;
620 *up
= crecp
->hash_next
;
621 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
628 *chainp
= cache_head
;
632 (ans
->flags
& F_REVERSE
) &&
633 (ans
->flags
& prot
) &&
634 memcmp(&ans
->addr
.addr
, addr
, addrlen
) == 0)
640 static void add_hosts_entry(struct crec
*cache
, struct all_addr
*addr
, int addrlen
,
641 unsigned short flags
, int index
, int addr_dup
)
643 struct crec
*lookup
= cache_find_by_name(NULL
, cache
->name
.sname
, 0, flags
& (F_IPV4
| F_IPV6
));
646 /* Remove duplicates in hosts files. */
647 if (lookup
&& (lookup
->flags
& F_HOSTS
) &&
648 memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
652 /* Ensure there is only one address -> name mapping (first one trumps)
653 We do this by steam here, first we see if the address is the same as
654 the last one we saw, which eliminates most in the case of an ad-block
655 file with thousands of entries for the same address.
656 Then we search and bail at the first matching address that came from
657 a HOSTS file. Since the first host entry gets reverse, we know
658 then that it must exist without searching exhaustively for it. */
663 for (i
=0; i
<hash_size
; i
++)
665 for (lookup
= hash_table
[i
]; lookup
; lookup
= lookup
->hash_next
)
666 if ((lookup
->flags
& F_HOSTS
) &&
667 (lookup
->flags
& flags
& (F_IPV4
| F_IPV6
)) &&
668 memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
677 cache
->flags
= flags
;
679 memcpy(&cache
->addr
.addr
, addr
, addrlen
);
684 static int read_hostsfile(char *filename
, int opts
, char *buff
, char *domain_suffix
, int index
, int cache_size
)
686 FILE *f
= fopen(filename
, "r");
688 int addr_count
= 0, name_count
= cache_size
, lineno
= 0;
689 unsigned short flags
, saved_flags
= 0;
690 struct all_addr addr
, saved_addr
;
694 syslog(LOG_ERR
, _("failed to load names from %s: %m"), filename
);
698 while ((line
= fgets(buff
, MAXDNAME
, f
)))
700 char *token
= strtok(line
, " \t\n\r");
701 int addrlen
, addr_dup
= 0;
705 if (!token
|| (*token
== '#'))
709 if (inet_pton(AF_INET
, token
, &addr
) > 0)
711 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
714 else if (inet_pton(AF_INET6
, token
, &addr
) > 0)
716 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
;
720 if ((addr
.addr
.addr4
.s_addr
= inet_addr(token
)) != (in_addr_t
) -1)
722 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
728 syslog(LOG_ERR
, _("bad address at %s line %d"), filename
, lineno
);
732 if (saved_flags
== flags
&& memcmp(&addr
, &saved_addr
, addrlen
) == 0)
742 /* rehash every 1000 names. */
743 if ((name_count
- cache_size
) > 1000)
746 cache_size
= name_count
;
749 while ((token
= strtok(NULL
, " \t\n\r")) && (*token
!= '#'))
752 if (canonicalise(token
))
754 /* If set, add a version of the name with a default domain appended */
755 if ((opts
& OPT_EXPAND
) && domain_suffix
&& !strchr(token
, '.') &&
756 (cache
= malloc(sizeof(struct crec
) +
757 strlen(token
)+2+strlen(domain_suffix
)-SMALLDNAME
)))
759 strcpy(cache
->name
.sname
, token
);
760 strcat(cache
->name
.sname
, ".");
761 strcat(cache
->name
.sname
, domain_suffix
);
762 add_hosts_entry(cache
, &addr
, addrlen
, flags
, index
, addr_dup
);
766 if ((cache
= malloc(sizeof(struct crec
) + strlen(token
)+1-SMALLDNAME
)))
768 strcpy(cache
->name
.sname
, token
);
769 add_hosts_entry(cache
, &addr
, addrlen
, flags
, index
, addr_dup
);
774 syslog(LOG_ERR
, _("bad name at %s line %d"), filename
, lineno
);
781 syslog(LOG_INFO
, _("read %s - %d addresses"), filename
, addr_count
);
786 void cache_reload(int opts
, char *buff
, char *domain_suffix
, struct hostsfile
*addn_hosts
)
788 struct crec
*cache
, **up
, *tmp
;
789 int i
, total_size
= cache_size
;
791 cache_inserted
= cache_live_freed
= 0;
793 for (i
=0; i
<hash_size
; i
++)
794 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= tmp
)
796 tmp
= cache
->hash_next
;
797 if (cache
->flags
& F_HOSTS
)
799 *up
= cache
->hash_next
;
802 else if (!(cache
->flags
& F_DHCP
))
804 *up
= cache
->hash_next
;
805 if (cache
->flags
& F_BIGNAME
)
807 cache
->name
.bname
->next
= big_free
;
808 big_free
= cache
->name
.bname
;
813 up
= &cache
->hash_next
;
816 if ((opts
& OPT_NO_HOSTS
) && !addn_hosts
)
819 syslog(LOG_INFO
, _("cleared cache"));
823 if (!(opts
& OPT_NO_HOSTS
))
824 total_size
= read_hostsfile(HOSTSFILE
, opts
, buff
, domain_suffix
, 0, total_size
);
827 total_size
= read_hostsfile(addn_hosts
->fname
, opts
, buff
, domain_suffix
, addn_hosts
->index
, total_size
);
828 addn_hosts
= addn_hosts
->next
;
832 void cache_unhash_dhcp(void)
834 struct crec
*cache
, **up
;
837 for (i
=0; i
<hash_size
; i
++)
838 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= cache
->hash_next
)
839 if (cache
->flags
& F_DHCP
)
841 *up
= cache
->hash_next
;
842 cache
->next
= dhcp_spare
;
846 up
= &cache
->hash_next
;
849 void cache_add_dhcp_entry(struct daemon
*daemon
, char *host_name
,
850 struct in_addr
*host_address
, time_t ttd
)
853 unsigned short flags
= F_DHCP
| F_FORWARD
| F_IPV4
| F_REVERSE
;
858 if ((crec
= cache_find_by_name(NULL
, host_name
, 0, F_IPV4
| F_CNAME
)))
860 if (crec
->flags
& F_HOSTS
)
862 if (crec
->addr
.addr
.addr
.addr4
.s_addr
!= host_address
->s_addr
)
864 strcpy(daemon
->namebuff
, inet_ntoa(crec
->addr
.addr
.addr
.addr4
));
866 _("not giving name %s to the DHCP lease of %s because "
867 "the name exists in %s with address %s"),
868 host_name
, inet_ntoa(*host_address
),
869 record_source(daemon
->addn_hosts
, crec
->uid
), daemon
->namebuff
);
873 else if (!(crec
->flags
& F_DHCP
))
874 cache_scan_free(host_name
, NULL
, 0, crec
->flags
& (F_IPV4
| F_CNAME
| F_FORWARD
));
877 if ((crec
= cache_find_by_addr(NULL
, (struct all_addr
*)host_address
, 0, F_IPV4
)))
879 if (crec
->flags
& F_NEG
)
880 cache_scan_free(NULL
, (struct all_addr
*)host_address
, 0, F_IPV4
| F_REVERSE
);
882 /* avoid multiple reverse mappings */
886 if ((crec
= dhcp_spare
))
887 dhcp_spare
= dhcp_spare
->next
;
888 else /* need new one */
889 crec
= malloc(sizeof(struct crec
));
891 if (crec
) /* malloc may fail */
895 crec
->flags
|= F_IMMORTAL
;
898 crec
->addr
.addr
.addr
.addr4
= *host_address
;
899 crec
->name
.namep
= host_name
;
904 void dump_cache(struct daemon
*daemon
, time_t now
)
906 syslog(LOG_INFO
, _("time %lu, cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
907 (unsigned long)now
, daemon
->cachesize
, cache_live_freed
, cache_inserted
);
909 if ((daemon
->options
& (OPT_DEBUG
| OPT_LOG
)) &&
910 (addrbuff
|| (addrbuff
= malloc(ADDRSTRLEN
))))
914 syslog(LOG_DEBUG
, "Host Address Flags Expires");
916 for (i
=0; i
<hash_size
; i
++)
917 for (cache
= hash_table
[i
]; cache
; cache
= cache
->hash_next
)
919 if ((cache
->flags
& F_NEG
) && (cache
->flags
& F_FORWARD
))
921 else if (cache
->flags
& F_CNAME
)
924 addrbuff
[ADDRSTRLEN
-1] = 0;
925 if (!is_outdated_cname_pointer(cache
))
926 strncpy(addrbuff
, cache_get_name(cache
->addr
.cname
.cache
), ADDRSTRLEN
);
929 else if (cache
->flags
& F_IPV4
)
930 inet_ntop(AF_INET
, &cache
->addr
.addr
, addrbuff
, ADDRSTRLEN
);
931 else if (cache
->flags
& F_IPV6
)
932 inet_ntop(AF_INET6
, &cache
->addr
.addr
, addrbuff
, ADDRSTRLEN
);
935 strcpy(addrbuff
, inet_ntoa(cache
->addr
.addr
.addr
.addr4
));
938 #ifdef HAVE_BROKEN_RTC
939 "%-40.40s %-30.30s %s%s%s%s%s%s%s%s%s%s %lu",
941 "%-40.40s %-30.30s %s%s%s%s%s%s%s%s%s%s %s",
943 cache_get_name(cache
), addrbuff
,
944 cache
->flags
& F_IPV4
? "4" : "",
945 cache
->flags
& F_IPV6
? "6" : "",
946 cache
->flags
& F_CNAME
? "C" : "",
947 cache
->flags
& F_FORWARD
? "F" : " ",
948 cache
->flags
& F_REVERSE
? "R" : " ",
949 cache
->flags
& F_IMMORTAL
? "I" : " ",
950 cache
->flags
& F_DHCP
? "D" : " ",
951 cache
->flags
& F_NEG
? "N" : " ",
952 cache
->flags
& F_NXDOMAIN
? "X" : " ",
953 cache
->flags
& F_HOSTS
? "H" : " ",
954 #ifdef HAVE_BROKEN_RTC
955 cache
->flags
& F_IMMORTAL
? 0: (unsigned long)(cache
->ttd
- now
)
957 cache
->flags
& F_IMMORTAL
? "\n" : ctime(&(cache
->ttd
))
964 static char *record_source(struct hostsfile
*addn_hosts
, int index
)
966 char *source
= HOSTSFILE
;
969 if (addn_hosts
->index
== index
)
971 source
= addn_hosts
->fname
;
974 addn_hosts
= addn_hosts
->next
;
980 void log_query(unsigned short flags
, char *name
, struct all_addr
*addr
,
981 unsigned short type
, struct hostsfile
*addn_hosts
, int index
)
992 if (flags
& F_REVERSE
)
994 inet_ntop(flags
& F_IPV4
? AF_INET
: AF_INET6
,
995 addr
, name
, MAXDNAME
);
997 strcpy(name
, inet_ntoa(addr
->addr
.addr4
));
1000 if (flags
& F_NXDOMAIN
)
1001 strcpy(addrbuff
, "<NXDOMAIN>");
1003 strcpy(addrbuff
, "<NODATA>");
1006 strcat(addrbuff
, "-IPv4");
1007 else if (flags
& F_IPV6
)
1008 strcat(addrbuff
, "-IPv6");
1010 else if (flags
& F_CNAME
)
1012 /* nasty abuse of IPV4 and IPV6 flags */
1014 strcpy(addrbuff
, "<MX>");
1015 else if (flags
& F_IPV6
)
1016 strcpy(addrbuff
, "<SRV>");
1017 else if (flags
& F_NXDOMAIN
)
1018 strcpy(addrbuff
, "<TXT>");
1019 else if (flags
& F_BIGNAME
)
1020 strcpy(addrbuff
, "<PTR>");
1022 strcpy(addrbuff
, "<CNAME>");
1026 inet_ntop(flags
& F_IPV4
? AF_INET
: AF_INET6
,
1027 addr
, addrbuff
, ADDRSTRLEN
);
1029 strcpy(addrbuff
, inet_ntoa(addr
->addr
.addr4
));
1034 else if (flags
& F_HOSTS
)
1035 source
= record_source(addn_hosts
, index
);
1036 else if (flags
& F_CONFIG
)
1038 else if (flags
& F_UPSTREAM
)
1040 else if (flags
& F_SERVER
)
1042 source
= "forwarded";
1045 else if (flags
& F_QUERY
)
1051 sprintf(types
, "query[type=%d]", type
);
1052 for (i
= 0; i
< (sizeof(typestr
)/sizeof(typestr
[0])); i
++)
1053 if (typestr
[i
].type
== type
)
1054 sprintf(types
,"query[%s]", typestr
[i
].name
);
1062 if (strlen(name
) == 0)
1065 if ((flags
& F_FORWARD
) | (flags
& F_NEG
))
1066 syslog(LOG_DEBUG
, "%s %s %s %s", source
, name
, verb
, addrbuff
);
1067 else if (flags
& F_REVERSE
)
1068 syslog(LOG_DEBUG
, "%s %s is %s", source
, addrbuff
, name
);