]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/cache.c
1 /* dnsmasq is Copyright (c) 2000-2012 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, or
6 (at your option) version 3 dated 29 June, 2007.
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.
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/>.
19 static struct crec
*cache_head
= NULL
, *cache_tail
= NULL
, **hash_table
= NULL
;
21 static struct crec
*dhcp_spare
= NULL
;
23 static struct crec
*new_chain
= NULL
;
24 static int cache_inserted
= 0, cache_live_freed
= 0, insert_error
;
25 static union bigname
*big_free
= NULL
;
26 static int bignames_left
, hash_size
;
29 /* type->string mapping: this is also used by the name-hash function as a mixing table. */
32 const char * const name
;
66 static void cache_free(struct crec
*crecp
);
67 static void cache_unlink(struct crec
*crecp
);
68 static void cache_link(struct crec
*crecp
);
69 static void rehash(int size
);
70 static void cache_hash(struct crec
*crecp
);
77 bignames_left
= daemon
->cachesize
/10;
79 if (daemon
->cachesize
> 0)
81 crecp
= safe_malloc(daemon
->cachesize
*sizeof(struct crec
));
83 for (i
=0; i
< daemon
->cachesize
; i
++, crecp
++)
91 /* create initial hash table*/
92 rehash(daemon
->cachesize
);
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
99 static void rehash(int size
)
101 struct crec
**new, **old
, *p
, *tmp
;
102 int i
, new_size
, old_size
;
104 /* hash_size is a power of two. */
105 for (new_size
= 64; new_size
< size
/10; new_size
= new_size
<< 1);
107 /* must succeed in getting first instance, failure later is non-fatal */
109 new = safe_malloc(new_size
* sizeof(struct crec
*));
110 else if (new_size
<= hash_size
|| !(new = whine_malloc(new_size
* sizeof(struct crec
*))))
113 for(i
= 0; i
< new_size
; i
++)
117 old_size
= hash_size
;
119 hash_size
= new_size
;
123 for (i
= 0; i
< old_size
; i
++)
124 for (p
= old
[i
]; p
; p
= tmp
)
133 static struct crec
**hash_bucket(char *name
)
135 unsigned int c
, val
= 017465; /* Barker code - minimum self-correlation in cyclic shift */
136 const unsigned char *mix_tab
= (const unsigned char*)typestr
;
138 while((c
= (unsigned char) *name
++))
140 /* don't use tolower and friends here - they may be messed up by LOCALE */
141 if (c
>= 'A' && c
<= 'Z')
143 val
= ((val
<< 7) | (val
>> (32 - 7))) + (mix_tab
[(val
+ c
) & 0x3F] ^ c
);
146 /* hash_size is a power of two */
147 return hash_table
+ ((val
^ (val
>> 16)) & (hash_size
- 1));
150 static void cache_hash(struct crec
*crecp
)
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 */
157 struct crec
**up
= hash_bucket(cache_get_name(crecp
));
159 if (!(crecp
->flags
& F_REVERSE
))
161 while (*up
&& ((*up
)->flags
& F_REVERSE
))
162 up
= &((*up
)->hash_next
);
164 if (crecp
->flags
& F_IMMORTAL
)
165 while (*up
&& !((*up
)->flags
& F_IMMORTAL
))
166 up
= &((*up
)->hash_next
);
168 crecp
->hash_next
= *up
;
172 static void cache_free(struct crec
*crecp
)
174 crecp
->flags
&= ~F_FORWARD
;
175 crecp
->flags
&= ~F_REVERSE
;
176 crecp
->uid
= uid
++; /* invalidate CNAMES pointing to this. */
179 cache_tail
->next
= crecp
;
182 crecp
->prev
= cache_tail
;
186 /* retrieve big name for further use. */
187 if (crecp
->flags
& F_BIGNAME
)
189 crecp
->name
.bname
->next
= big_free
;
190 big_free
= crecp
->name
.bname
;
191 crecp
->flags
&= ~F_BIGNAME
;
195 /* insert a new cache entry at the head of the list (youngest entry) */
196 static void cache_link(struct crec
*crecp
)
198 if (cache_head
) /* check needed for init code */
199 cache_head
->prev
= crecp
;
200 crecp
->next
= cache_head
;
207 /* remove an arbitrary cache entry for promotion */
208 static void cache_unlink (struct crec
*crecp
)
211 crecp
->prev
->next
= crecp
->next
;
213 cache_head
= crecp
->next
;
216 crecp
->next
->prev
= crecp
->prev
;
218 cache_tail
= crecp
->prev
;
221 char *cache_get_name(struct crec
*crecp
)
223 if (crecp
->flags
& F_BIGNAME
)
224 return crecp
->name
.bname
->name
;
225 else if (crecp
->flags
& F_NAMEP
)
226 return crecp
->name
.namep
;
228 return crecp
->name
.sname
;
231 static int is_outdated_cname_pointer(struct crec
*crecp
)
233 if (!(crecp
->flags
& F_CNAME
))
236 if (crecp
->addr
.cname
.cache
&& crecp
->addr
.cname
.uid
== crecp
->addr
.cname
.cache
->uid
)
242 static int is_expired(time_t now
, struct crec
*crecp
)
244 if (crecp
->flags
& F_IMMORTAL
)
247 if (difftime(now
, crecp
->ttd
) < 0)
253 static int cache_scan_free(char *name
, struct all_addr
*addr
, time_t now
, unsigned short flags
)
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.
260 If (flags == 0) remove any expired entries in the whole cache.
262 In the flags & F_FORWARD case, the return code is valid, and returns zero if the
263 name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
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. */
268 struct crec
*crecp
, **up
;
270 if (flags
& F_FORWARD
)
272 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= crecp
->hash_next
)
273 if (is_expired(now
, crecp
) || is_outdated_cname_pointer(crecp
))
275 *up
= crecp
->hash_next
;
276 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
282 else if ((crecp
->flags
& F_FORWARD
) &&
283 ((flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) || ((crecp
->flags
| flags
) & F_CNAME
)) &&
284 hostname_isequal(cache_get_name(crecp
), name
))
286 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
288 *up
= crecp
->hash_next
;
293 up
= &crecp
->hash_next
;
299 int addrlen
= (flags
& F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
301 int addrlen
= INADDRSZ
;
303 for (i
= 0; i
< hash_size
; i
++)
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
)
307 if (is_expired(now
, crecp
))
309 *up
= crecp
->hash_next
;
310 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
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)
321 *up
= crecp
->hash_next
;
326 up
= &crecp
->hash_next
;
332 /* Note: The normal calling sequence is
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. */
340 void cache_start_insert(void)
342 /* Free any entries which didn't get committed during the last
347 struct crec
*tmp
= new_chain
->next
;
348 cache_free(new_chain
);
355 struct crec
*cache_insert(char *name
, struct all_addr
*addr
,
356 time_t now
, unsigned long ttl
, unsigned short flags
)
359 union bigname
*big_name
= NULL
;
360 int freed_all
= flags
& F_REVERSE
;
363 log_query(flags
| F_UPSTREAM
, name
, addr
, NULL
);
365 /* if previous insertion failed give up now. */
369 /* First remove any expired entries and entries for the name/address we
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
))
378 /* Now get a cache entry from the end of the LRU list */
380 if (!(new = cache_tail
)) /* no entries left - cache is too small, bail */
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. */
390 if (new->flags
& (F_FORWARD
| F_REVERSE
))
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
394 a tight loop here. If that happens, abandon the
395 insert. Once in this state, all inserts will probably fail. */
404 free_avail
= 1; /* Must be free space now. */
405 cache_scan_free(cache_get_name(new), &new->addr
.addr
, now
, new->flags
);
410 cache_scan_free(NULL
, NULL
, now
, 0);
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))
423 big_free
= big_free
->next
;
425 else if (!bignames_left
||
426 !(big_name
= (union bigname
*)whine_malloc(sizeof(union bigname
))))
436 /* Got the rest: finally grab entry. */
444 new->name
.bname
= big_name
;
445 new->flags
|= F_BIGNAME
;
449 strcpy(cache_get_name(new), name
);
451 *cache_get_name(new) = 0;
454 new->addr
.addr
= *addr
;
456 new->addr
.cname
.cache
= NULL
;
458 new->ttd
= now
+ (time_t)ttl
;
459 new->next
= new_chain
;
465 /* after end of insertion, commit the new entries */
466 void cache_end_insert(void)
473 struct crec
*tmp
= new_chain
->next
;
474 /* drop CNAMEs which didn't find a target. */
475 if (is_outdated_cname_pointer(new_chain
))
476 cache_free(new_chain
);
479 cache_hash(new_chain
);
480 cache_link(new_chain
);
488 struct crec
*cache_find_by_name(struct crec
*crecp
, char *name
, time_t now
, unsigned short prot
)
492 if (crecp
) /* iterating */
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
;
499 unsigned short ins_flags
= 0;
501 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= next
)
503 next
= crecp
->hash_next
;
505 if (!is_expired(now
, crecp
) && !is_outdated_cname_pointer(crecp
))
507 if ((crecp
->flags
& F_FORWARD
) &&
508 (crecp
->flags
& prot
) &&
509 hostname_isequal(cache_get_name(crecp
), name
))
511 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
514 chainp
= &crecp
->next
;
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
527 if (insert
&& (crecp
->flags
& (F_REVERSE
| F_IMMORTAL
)) == ins_flags
)
529 *up
= crecp
->hash_next
;
530 crecp
->hash_next
= *insert
;
532 insert
= &crecp
->hash_next
;
539 ins_flags
= crecp
->flags
& (F_REVERSE
| F_IMMORTAL
);
541 up
= &crecp
->hash_next
;
545 /* case : not expired, incorrect entry. */
546 up
= &crecp
->hash_next
;
550 /* expired entry, free it */
551 *up
= crecp
->hash_next
;
552 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
560 *chainp
= cache_head
;
564 (ans
->flags
& F_FORWARD
) &&
565 (ans
->flags
& prot
) &&
566 hostname_isequal(cache_get_name(ans
), name
))
572 struct crec
*cache_find_by_addr(struct crec
*crecp
, struct all_addr
*addr
,
573 time_t now
, unsigned short prot
)
577 int addrlen
= (prot
== F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
579 int addrlen
= INADDRSZ
;
582 if (crecp
) /* iterating */
586 /* first search, look for relevant entries and push to top of list
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
591 struct crec
**up
, **chainp
= &ans
;
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
)
597 if (!is_expired(now
, crecp
))
599 if ((crecp
->flags
& prot
) &&
600 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
602 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
605 chainp
= &crecp
->next
;
613 up
= &crecp
->hash_next
;
617 *up
= crecp
->hash_next
;
618 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
625 *chainp
= cache_head
;
629 (ans
->flags
& F_REVERSE
) &&
630 (ans
->flags
& prot
) &&
631 memcmp(&ans
->addr
.addr
, addr
, addrlen
) == 0)
637 static void add_hosts_entry(struct crec
*cache
, struct all_addr
*addr
, int addrlen
,
638 unsigned short flags
, int index
, struct crec
**rhash
)
640 struct crec
*lookup
= cache_find_by_name(NULL
, cache
->name
.sname
, 0, flags
& (F_IPV4
| F_IPV6
));
641 int i
, nameexists
= 0;
645 /* Remove duplicates in hosts files. */
646 if (lookup
&& (lookup
->flags
& F_HOSTS
))
649 if (memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
656 /* Ensure there is only one address -> name mapping (first one trumps)
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
659 the array rhash. Note that rhash and the values in ->next are only valid
660 whilst reading hosts files: the buckets are then freed, and the
661 ->next pointer used for other things.
663 We search and bail at the first matching address that came from
664 a HOSTS file. Since the first host entry gets reverse, we know
665 then that it must exist without searching exhaustively for it.
667 This complexity avoids O(n^2) divergent CPU use whilst reading
668 large (10000 entry) hosts files. */
671 for (j
= 0, i
= 0; i
< addrlen
; i
++)
672 j
+= ((unsigned char *)addr
)[i
] + (j
<< 6) + (j
<< 16) - j
;
674 for (lookup
= rhash
[j
% RHASHSIZE
]; lookup
; lookup
= lookup
->next
)
675 if ((lookup
->flags
& F_HOSTS
) &&
676 (lookup
->flags
& flags
& (F_IPV4
| F_IPV6
)) &&
677 memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
683 cache
->flags
= flags
;
686 /* maintain address has chain */
687 cache
->next
= rhash
[j
% RHASHSIZE
];
688 rhash
[j
% RHASHSIZE
] = cache
;
690 memcpy(&cache
->addr
.addr
, addr
, addrlen
);
694 /* don't need to do alias stuff for second and subsequent addresses. */
696 for (a
= daemon
->cnames
; a
; a
= a
->next
)
697 if (hostname_isequal(cache
->name
.sname
, a
->target
) &&
698 (lookup
= whine_malloc(sizeof(struct crec
))))
700 lookup
->flags
= F_FORWARD
| F_IMMORTAL
| F_NAMEP
| F_HOSTS
| F_CNAME
;
701 lookup
->name
.namep
= a
->alias
;
702 lookup
->addr
.cname
.cache
= cache
;
703 lookup
->addr
.cname
.uid
= index
;
708 static int eatspace(FILE *f
)
714 if ((c
= getc(f
)) == '#')
715 while (c
!= '\n' && c
!= EOF
)
732 static int gettok(FILE *f
, char *token
)
738 if ((c
= getc(f
)) == EOF
)
739 return (count
== 0) ? EOF
: 1;
741 if (isspace(c
) || c
== '#')
747 if (count
< (MAXDNAME
- 1))
755 static int read_hostsfile(char *filename
, int index
, int cache_size
, struct crec
**rhash
)
757 FILE *f
= fopen(filename
, "r");
758 char *token
= daemon
->namebuff
, *domain_suffix
= NULL
;
759 int addr_count
= 0, name_count
= cache_size
, lineno
= 0;
760 unsigned short flags
= 0;
761 struct all_addr addr
;
762 int atnl
, addrlen
= 0;
766 my_syslog(LOG_ERR
, _("failed to load names from %s: %s"), filename
, strerror(errno
));
772 while ((atnl
= gettok(f
, token
)) != EOF
)
777 if (inet_pton(AF_INET
, token
, &addr
) > 0)
779 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
781 domain_suffix
= get_domain(addr
.addr
.addr4
);
783 else if (inet_pton(AF_INET6
, token
, &addr
) > 0)
785 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
;
787 domain_suffix
= daemon
->domain_suffix
;
790 if ((addr
.addr
.addr4
.s_addr
= inet_addr(token
)) != (in_addr_t
) -1)
792 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
794 domain_suffix
= get_domain(addr
.addr
.addr4
);
799 my_syslog(LOG_ERR
, _("bad address at %s line %d"), filename
, lineno
);
801 atnl
= gettok(f
, token
);
807 /* rehash every 1000 names. */
808 if ((name_count
- cache_size
) > 1000)
811 cache_size
= name_count
;
820 if ((atnl
= gettok(f
, token
)) == EOF
)
823 fqdn
= !!strchr(token
, '.');
825 if ((canon
= canonicalise(token
, &nomem
)))
827 /* If set, add a version of the name with a default domain appended */
828 if (option_bool(OPT_EXPAND
) && domain_suffix
&& !fqdn
&&
829 (cache
= whine_malloc(sizeof(struct crec
) +
830 strlen(canon
)+2+strlen(domain_suffix
)-SMALLDNAME
)))
832 strcpy(cache
->name
.sname
, canon
);
833 strcat(cache
->name
.sname
, ".");
834 strcat(cache
->name
.sname
, domain_suffix
);
835 add_hosts_entry(cache
, &addr
, addrlen
, flags
, index
, rhash
);
838 if ((cache
= whine_malloc(sizeof(struct crec
) + strlen(canon
)+1-SMALLDNAME
)))
840 strcpy(cache
->name
.sname
, canon
);
841 add_hosts_entry(cache
, &addr
, addrlen
, flags
, index
, rhash
);
848 my_syslog(LOG_ERR
, _("bad name at %s line %d"), filename
, lineno
);
855 my_syslog(LOG_INFO
, _("read %s - %d addresses"), filename
, addr_count
);
860 void cache_reload(void)
862 struct crec
*cache
, **up
, *tmp
;
863 int i
, total_size
= daemon
->cachesize
;
864 struct hostsfile
*ah
;
865 struct crec
**reverse_hash
;
867 cache_inserted
= cache_live_freed
= 0;
869 for (i
=0; i
<hash_size
; i
++)
870 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= tmp
)
872 tmp
= cache
->hash_next
;
873 if (cache
->flags
& F_HOSTS
)
875 *up
= cache
->hash_next
;
878 else if (!(cache
->flags
& F_DHCP
))
880 *up
= cache
->hash_next
;
881 if (cache
->flags
& F_BIGNAME
)
883 cache
->name
.bname
->next
= big_free
;
884 big_free
= cache
->name
.bname
;
889 up
= &cache
->hash_next
;
892 if (option_bool(OPT_NO_HOSTS
) && !daemon
->addn_hosts
)
894 if (daemon
->cachesize
> 0)
895 my_syslog(LOG_INFO
, _("cleared cache"));
899 if (!(reverse_hash
= whine_malloc(sizeof(struct crec
*) * RHASHSIZE
)))
902 for (i
= 0; i
< RHASHSIZE
; i
++)
903 reverse_hash
[i
] = NULL
;
905 if (!option_bool(OPT_NO_HOSTS
))
906 total_size
= read_hostsfile(HOSTSFILE
, 0, total_size
, reverse_hash
);
908 daemon
->addn_hosts
= expand_filelist(daemon
->addn_hosts
);
909 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
910 if (!(ah
->flags
& AH_INACTIVE
))
911 total_size
= read_hostsfile(ah
->fname
, ah
->index
, total_size
, reverse_hash
);
916 char *get_domain(struct in_addr addr
)
918 struct cond_domain
*c
;
920 for (c
= daemon
->cond_domain
; c
; c
= c
->next
)
921 if (ntohl(addr
.s_addr
) >= ntohl(c
->start
.s_addr
) &&
922 ntohl(addr
.s_addr
) <= ntohl(c
->end
.s_addr
))
925 return daemon
->domain_suffix
;
929 struct in_addr
a_record_from_hosts(char *name
, time_t now
)
931 struct crec
*crecp
= NULL
;
934 while ((crecp
= cache_find_by_name(crecp
, name
, now
, F_IPV4
)))
935 if (crecp
->flags
& F_HOSTS
)
936 return *(struct in_addr
*)&crecp
->addr
;
938 my_syslog(MS_DHCP
| LOG_WARNING
, _("No IPv4 address found for %s"), name
);
944 void cache_unhash_dhcp(void)
946 struct crec
*cache
, **up
;
949 for (i
=0; i
<hash_size
; i
++)
950 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= cache
->hash_next
)
951 if (cache
->flags
& F_DHCP
)
953 *up
= cache
->hash_next
;
954 cache
->next
= dhcp_spare
;
958 up
= &cache
->hash_next
;
961 void cache_add_dhcp_entry(char *host_name
,
962 struct in_addr
*host_address
, time_t ttd
)
964 struct crec
*crec
= NULL
, *aliasc
;
965 unsigned short flags
= F_NAMEP
| F_DHCP
| F_FORWARD
| F_IPV4
| F_REVERSE
;
969 while ((crec
= cache_find_by_name(crec
, host_name
, 0, F_IPV4
| F_CNAME
)))
971 /* check all addresses associated with name */
972 if (crec
->flags
& F_HOSTS
)
974 /* if in hosts, don't need DHCP record */
977 if (crec
->flags
& F_CNAME
)
978 my_syslog(MS_DHCP
| LOG_WARNING
,
979 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
980 host_name
, inet_ntoa(*host_address
));
981 else if (crec
->addr
.addr
.addr
.addr4
.s_addr
!= host_address
->s_addr
)
983 strcpy(daemon
->namebuff
, inet_ntoa(crec
->addr
.addr
.addr
.addr4
));
984 my_syslog(MS_DHCP
| LOG_WARNING
,
985 _("not giving name %s to the DHCP lease of %s because "
986 "the name exists in %s with address %s"),
987 host_name
, inet_ntoa(*host_address
),
988 record_source(crec
->uid
), daemon
->namebuff
);
991 else if (!(crec
->flags
& F_DHCP
))
993 cache_scan_free(host_name
, NULL
, 0, crec
->flags
& (F_IPV4
| F_CNAME
| F_FORWARD
));
994 /* scan_free deletes all addresses associated with name */
1002 if ((crec
= cache_find_by_addr(NULL
, (struct all_addr
*)host_address
, 0, F_IPV4
)))
1004 if (crec
->flags
& F_NEG
)
1005 cache_scan_free(NULL
, (struct all_addr
*)host_address
, 0, F_IPV4
| F_REVERSE
);
1007 /* avoid multiple reverse mappings */
1008 flags
&= ~F_REVERSE
;
1011 if ((crec
= dhcp_spare
))
1012 dhcp_spare
= dhcp_spare
->next
;
1013 else /* need new one */
1014 crec
= whine_malloc(sizeof(struct crec
));
1016 if (crec
) /* malloc may fail */
1018 crec
->flags
= flags
;
1020 crec
->flags
|= F_IMMORTAL
;
1023 crec
->addr
.addr
.addr
.addr4
= *host_address
;
1024 crec
->name
.namep
= host_name
;
1028 for (a
= daemon
->cnames
; a
; a
= a
->next
)
1029 if (hostname_isequal(host_name
, a
->target
))
1031 if ((aliasc
= dhcp_spare
))
1032 dhcp_spare
= dhcp_spare
->next
;
1033 else /* need new one */
1034 aliasc
= whine_malloc(sizeof(struct crec
));
1038 aliasc
->flags
= F_FORWARD
| F_NAMEP
| F_DHCP
| F_CNAME
;
1040 aliasc
->flags
|= F_IMMORTAL
;
1043 aliasc
->name
.namep
= a
->alias
;
1044 aliasc
->addr
.cname
.cache
= crec
;
1045 aliasc
->addr
.cname
.uid
= crec
->uid
;
1054 void dump_cache(time_t now
)
1056 struct server
*serv
, *serv1
;
1058 my_syslog(LOG_INFO
, _("time %lu"), (unsigned long)now
);
1059 my_syslog(LOG_INFO
, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
1060 daemon
->cachesize
, cache_live_freed
, cache_inserted
);
1061 my_syslog(LOG_INFO
, _("queries forwarded %u, queries answered locally %u"),
1062 daemon
->queries_forwarded
, daemon
->local_answer
);
1064 /* sum counts from different records for same server */
1065 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1066 serv
->flags
&= ~SERV_COUNTED
;
1068 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1070 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)))
1073 unsigned int queries
= 0, failed_queries
= 0;
1074 for (serv1
= serv
; serv1
; serv1
= serv1
->next
)
1075 if (!(serv1
->flags
&
1076 (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
| SERV_USE_RESOLV
| SERV_NO_REBIND
)) &&
1077 sockaddr_isequal(&serv
->addr
, &serv1
->addr
))
1079 serv1
->flags
|= SERV_COUNTED
;
1080 queries
+= serv1
->queries
;
1081 failed_queries
+= serv1
->failed_queries
;
1083 port
= prettyprint_addr(&serv
->addr
, daemon
->addrbuff
);
1084 my_syslog(LOG_INFO
, _("server %s#%d: queries sent %u, retried or failed %u"), daemon
->addrbuff
, port
, queries
, failed_queries
);
1087 if (option_bool(OPT_DEBUG
) || option_bool(OPT_LOG
))
1089 struct crec
*cache
;
1091 my_syslog(LOG_INFO
, "Host Address Flags Expires");
1093 for (i
=0; i
<hash_size
; i
++)
1094 for (cache
= hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1096 char *a
, *p
= daemon
->namebuff
;
1097 p
+= sprintf(p
, "%-40.40s ", cache_get_name(cache
));
1098 if ((cache
->flags
& F_NEG
) && (cache
->flags
& F_FORWARD
))
1100 else if (cache
->flags
& F_CNAME
)
1103 if (!is_outdated_cname_pointer(cache
))
1104 a
= cache_get_name(cache
->addr
.cname
.cache
);
1109 a
= daemon
->addrbuff
;
1110 if (cache
->flags
& F_IPV4
)
1111 inet_ntop(AF_INET
, &cache
->addr
.addr
, a
, ADDRSTRLEN
);
1112 else if (cache
->flags
& F_IPV6
)
1113 inet_ntop(AF_INET6
, &cache
->addr
.addr
, a
, ADDRSTRLEN
);
1117 a
= inet_ntoa(cache
->addr
.addr
.addr
.addr4
);
1119 p
+= sprintf(p
, "%-30.30s %s%s%s%s%s%s%s%s%s%s ", a
,
1120 cache
->flags
& F_IPV4
? "4" : "",
1121 cache
->flags
& F_IPV6
? "6" : "",
1122 cache
->flags
& F_CNAME
? "C" : "",
1123 cache
->flags
& F_FORWARD
? "F" : " ",
1124 cache
->flags
& F_REVERSE
? "R" : " ",
1125 cache
->flags
& F_IMMORTAL
? "I" : " ",
1126 cache
->flags
& F_DHCP
? "D" : " ",
1127 cache
->flags
& F_NEG
? "N" : " ",
1128 cache
->flags
& F_NXDOMAIN
? "X" : " ",
1129 cache
->flags
& F_HOSTS
? "H" : " ");
1130 #ifdef HAVE_BROKEN_RTC
1131 p
+= sprintf(p
, "%lu", cache
->flags
& F_IMMORTAL
? 0: (unsigned long)(cache
->ttd
- now
));
1133 p
+= sprintf(p
, "%s", cache
->flags
& F_IMMORTAL
? "\n" : ctime(&(cache
->ttd
)));
1134 /* ctime includes trailing \n - eat it */
1137 my_syslog(LOG_INFO
, daemon
->namebuff
);
1142 char *record_source(int index
)
1144 struct hostsfile
*ah
;
1149 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
1150 if (ah
->index
== index
)
1156 void querystr(char *str
, unsigned short type
)
1160 sprintf(str
, "query[type=%d]", type
);
1161 for (i
= 0; i
< (sizeof(typestr
)/sizeof(typestr
[0])); i
++)
1162 if (typestr
[i
].type
== type
)
1163 sprintf(str
,"query[%s]", typestr
[i
].name
);
1166 void log_query(unsigned int flags
, char *name
, struct all_addr
*addr
, char *arg
)
1168 char *source
, *dest
= daemon
->addrbuff
;
1171 if (!option_bool(OPT_LOG
))
1177 inet_ntop(flags
& F_IPV4
? AF_INET
: AF_INET6
,
1178 addr
, daemon
->addrbuff
, ADDRSTRLEN
);
1180 strncpy(daemon
->addrbuff
, inet_ntoa(addr
->addr
.addr4
), ADDRSTRLEN
);
1184 if (flags
& F_REVERSE
)
1187 name
= daemon
->addrbuff
;
1192 if (flags
& F_NXDOMAIN
)
1195 dest
= "NXDOMAIN-IPv4";
1196 else if (flags
& F_IPV6
)
1197 dest
= "NXDOMAIN-IPv6";
1204 dest
= "NODATA-IPv4";
1205 else if (flags
& F_IPV6
)
1206 dest
= "NODATA-IPv6";
1211 else if (flags
& F_CNAME
)
1213 else if (flags
& F_RRNAME
)
1216 if (flags
& F_CONFIG
)
1218 else if (flags
& F_DHCP
)
1220 else if (flags
& F_HOSTS
)
1222 else if (flags
& F_UPSTREAM
)
1224 else if (flags
& F_SERVER
)
1226 source
= "forwarded";
1229 else if (flags
& F_QUERY
)
1237 if (strlen(name
) == 0)
1240 my_syslog(LOG_INFO
, "%s %s %s %s", source
, name
, verb
, dest
);