1 /* dnsmasq is Copyright (c) 2000-2010 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
;
28 static char *addrbuff
= NULL
;
30 /* type->string mapping: this is also used by the name-hash function as a mixing table. */
33 const char * const name
;
67 static void cache_free(struct crec
*crecp
);
68 static void cache_unlink(struct crec
*crecp
);
69 static void cache_link(struct crec
*crecp
);
70 static void rehash(int size
);
71 static void cache_hash(struct crec
*crecp
);
78 if (daemon
->options
& OPT_LOG
)
79 addrbuff
= safe_malloc(ADDRSTRLEN
);
81 bignames_left
= daemon
->cachesize
/10;
83 if (daemon
->cachesize
> 0)
85 crecp
= safe_malloc(daemon
->cachesize
*sizeof(struct crec
));
87 for (i
=0; i
< daemon
->cachesize
; i
++, crecp
++)
95 /* create initial hash table*/
96 rehash(daemon
->cachesize
);
99 /* In most cases, we create the hash table once here by calling this with (hash_table == NULL)
100 but if the hosts file(s) are big (some people have 50000 ad-block entries), the table
101 will be much too small, so the hosts reading code calls rehash every 1000 addresses, to
103 static void rehash(int size
)
105 struct crec
**new, **old
, *p
, *tmp
;
106 int i
, new_size
, old_size
;
108 /* hash_size is a power of two. */
109 for (new_size
= 64; new_size
< size
/10; new_size
= new_size
<< 1);
111 /* must succeed in getting first instance, failure later is non-fatal */
113 new = safe_malloc(new_size
* sizeof(struct crec
*));
114 else if (new_size
<= hash_size
|| !(new = whine_malloc(new_size
* sizeof(struct crec
*))))
117 for(i
= 0; i
< new_size
; i
++)
121 old_size
= hash_size
;
123 hash_size
= new_size
;
127 for (i
= 0; i
< old_size
; i
++)
128 for (p
= old
[i
]; p
; p
= tmp
)
137 static struct crec
**hash_bucket(char *name
)
139 unsigned int c
, val
= 017465; /* Barker code - minimum self-correlation in cyclic shift */
140 const unsigned char *mix_tab
= (const unsigned char*)typestr
;
142 while((c
= (unsigned char) *name
++))
144 /* don't use tolower and friends here - they may be messed up by LOCALE */
145 if (c
>= 'A' && c
<= 'Z')
147 val
= ((val
<< 7) | (val
>> (32 - 7))) + (mix_tab
[(val
+ c
) & 0x3F] ^ c
);
150 /* hash_size is a power of two */
151 return hash_table
+ ((val
^ (val
>> 16)) & (hash_size
- 1));
154 static void cache_hash(struct crec
*crecp
)
156 /* maintain an invariant that all entries with F_REVERSE set
157 are at the start of the hash-chain and all non-reverse
158 immortal entries are at the end of the hash-chain.
159 This allows reverse searches and garbage collection to be optimised */
161 struct crec
**up
= hash_bucket(cache_get_name(crecp
));
163 if (!(crecp
->flags
& F_REVERSE
))
165 while (*up
&& ((*up
)->flags
& F_REVERSE
))
166 up
= &((*up
)->hash_next
);
168 if (crecp
->flags
& F_IMMORTAL
)
169 while (*up
&& !((*up
)->flags
& F_IMMORTAL
))
170 up
= &((*up
)->hash_next
);
172 crecp
->hash_next
= *up
;
176 static void cache_free(struct crec
*crecp
)
178 crecp
->flags
&= ~F_FORWARD
;
179 crecp
->flags
&= ~F_REVERSE
;
180 crecp
->uid
= uid
++; /* invalidate CNAMES pointing to this. */
183 cache_tail
->next
= crecp
;
186 crecp
->prev
= cache_tail
;
190 /* retrieve big name for further use. */
191 if (crecp
->flags
& F_BIGNAME
)
193 crecp
->name
.bname
->next
= big_free
;
194 big_free
= crecp
->name
.bname
;
195 crecp
->flags
&= ~F_BIGNAME
;
199 /* insert a new cache entry at the head of the list (youngest entry) */
200 static void cache_link(struct crec
*crecp
)
202 if (cache_head
) /* check needed for init code */
203 cache_head
->prev
= crecp
;
204 crecp
->next
= cache_head
;
211 /* remove an arbitrary cache entry for promotion */
212 static void cache_unlink (struct crec
*crecp
)
215 crecp
->prev
->next
= crecp
->next
;
217 cache_head
= crecp
->next
;
220 crecp
->next
->prev
= crecp
->prev
;
222 cache_tail
= crecp
->prev
;
225 char *cache_get_name(struct crec
*crecp
)
227 if (crecp
->flags
& F_BIGNAME
)
228 return crecp
->name
.bname
->name
;
229 else if (crecp
->flags
& (F_DHCP
| F_CONFIG
))
230 return crecp
->name
.namep
;
232 return crecp
->name
.sname
;
235 static int is_outdated_cname_pointer(struct crec
*crecp
)
237 if (!(crecp
->flags
& F_CNAME
))
240 if (crecp
->addr
.cname
.cache
&& crecp
->addr
.cname
.uid
== crecp
->addr
.cname
.cache
->uid
)
246 static int is_expired(time_t now
, struct crec
*crecp
)
248 if (crecp
->flags
& F_IMMORTAL
)
251 if (difftime(now
, crecp
->ttd
) < 0)
257 static int cache_scan_free(char *name
, struct all_addr
*addr
, time_t now
, unsigned short flags
)
259 /* Scan and remove old entries.
260 If (flags & F_FORWARD) then remove any forward entries for name and any expired
261 entries but only in the same hash bucket as name.
262 If (flags & F_REVERSE) then remove any reverse entries for addr and any expired
263 entries in the whole cache.
264 If (flags == 0) remove any expired entries in the whole cache.
266 In the flags & F_FORWARD case, the return code is valid, and returns zero if the
267 name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
269 We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
270 so that when we hit an entry which isn't reverse and is immortal, we're done. */
272 struct crec
*crecp
, **up
;
274 if (flags
& F_FORWARD
)
276 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= crecp
->hash_next
)
277 if (is_expired(now
, crecp
) || is_outdated_cname_pointer(crecp
))
279 *up
= crecp
->hash_next
;
280 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
286 else if ((crecp
->flags
& F_FORWARD
) &&
287 ((flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) || ((crecp
->flags
| flags
) & F_CNAME
)) &&
288 hostname_isequal(cache_get_name(crecp
), name
))
290 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
292 *up
= crecp
->hash_next
;
297 up
= &crecp
->hash_next
;
303 int addrlen
= (flags
& F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
305 int addrlen
= INADDRSZ
;
307 for (i
= 0; i
< hash_size
; i
++)
308 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
309 crecp
&& ((crecp
->flags
& F_REVERSE
) || !(crecp
->flags
& F_IMMORTAL
));
310 crecp
= crecp
->hash_next
)
311 if (is_expired(now
, crecp
))
313 *up
= crecp
->hash_next
;
314 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
320 else if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)) &&
321 (flags
& crecp
->flags
& F_REVERSE
) &&
322 (flags
& crecp
->flags
& (F_IPV4
| F_IPV6
)) &&
323 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
325 *up
= crecp
->hash_next
;
330 up
= &crecp
->hash_next
;
336 /* Note: The normal calling sequence is
341 but an abort can cause the cache_end_insert to be missed
342 in which can the next cache_start_insert cleans things up. */
344 void cache_start_insert(void)
346 /* Free any entries which didn't get committed during the last
351 struct crec
*tmp
= new_chain
->next
;
352 cache_free(new_chain
);
359 struct crec
*cache_insert(char *name
, struct all_addr
*addr
,
360 time_t now
, unsigned long ttl
, unsigned short flags
)
363 union bigname
*big_name
= NULL
;
364 int freed_all
= flags
& F_REVERSE
;
367 log_query(flags
| F_UPSTREAM
, name
, addr
, NULL
);
369 /* CONFIG bit means something else when stored in cache entries */
372 /* if previous insertion failed give up now. */
376 /* First remove any expired entries and entries for the name/address we
377 are currently inserting. Fail is we attempt to delete a name from
378 /etc/hosts or DHCP. */
379 if (!cache_scan_free(name
, addr
, now
, flags
))
385 /* Now get a cache entry from the end of the LRU list */
387 if (!(new = cache_tail
)) /* no entries left - cache is too small, bail */
393 /* End of LRU list is still in use: if we didn't scan all the hash
394 chains for expired entries do that now. If we already tried that
395 then it's time to start spilling things. */
397 if (new->flags
& (F_FORWARD
| F_REVERSE
))
399 /* If free_avail set, we believe that an entry has been freed.
400 Bugs have been known to make this not true, resulting in
401 a tight loop here. If that happens, abandon the
402 insert. Once in this state, all inserts will probably fail. */
411 free_avail
= 1; /* Must be free space now. */
412 cache_scan_free(cache_get_name(new), &new->addr
.addr
, now
, new->flags
);
417 cache_scan_free(NULL
, NULL
, now
, 0);
423 /* Check if we need to and can allocate extra memory for a long name.
424 If that fails, give up now. */
425 if (name
&& (strlen(name
) > SMALLDNAME
-1))
430 big_free
= big_free
->next
;
432 else if (!bignames_left
||
433 !(big_name
= (union bigname
*)whine_malloc(sizeof(union bigname
))))
443 /* Got the rest: finally grab entry. */
451 new->name
.bname
= big_name
;
452 new->flags
|= F_BIGNAME
;
456 strcpy(cache_get_name(new), name
);
458 *cache_get_name(new) = 0;
461 new->addr
.addr
= *addr
;
463 new->addr
.cname
.cache
= NULL
;
465 new->ttd
= now
+ (time_t)ttl
;
466 new->next
= new_chain
;
472 /* after end of insertion, commit the new entries */
473 void cache_end_insert(void)
480 struct crec
*tmp
= new_chain
->next
;
481 /* drop CNAMEs which didn't find a target. */
482 if (is_outdated_cname_pointer(new_chain
))
483 cache_free(new_chain
);
486 cache_hash(new_chain
);
487 cache_link(new_chain
);
495 struct crec
*cache_find_by_name(struct crec
*crecp
, char *name
, time_t now
, unsigned short prot
)
499 if (crecp
) /* iterating */
503 /* first search, look for relevant entries and push to top of list
504 also free anything which has expired */
505 struct crec
*next
, **up
, **insert
= NULL
, **chainp
= &ans
;
508 for (up
= hash_bucket(name
), crecp
= *up
; crecp
; crecp
= next
)
510 next
= crecp
->hash_next
;
512 if (!is_expired(now
, crecp
) && !is_outdated_cname_pointer(crecp
))
514 if ((crecp
->flags
& F_FORWARD
) &&
515 (crecp
->flags
& prot
) &&
516 hostname_isequal(cache_get_name(crecp
), name
))
518 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
521 chainp
= &crecp
->next
;
529 /* Move all but the first entry up the hash chain
530 this implements round-robin.
531 Make sure that re-ordering doesn't break the hash-chain
534 if (insert
&& (crecp
->flags
& (F_REVERSE
| F_IMMORTAL
)) == ins_flags
)
536 *up
= crecp
->hash_next
;
537 crecp
->hash_next
= *insert
;
539 insert
= &crecp
->hash_next
;
546 ins_flags
= crecp
->flags
& (F_REVERSE
| F_IMMORTAL
);
548 up
= &crecp
->hash_next
;
552 /* case : not expired, incorrect entry. */
553 up
= &crecp
->hash_next
;
557 /* expired entry, free it */
558 *up
= crecp
->hash_next
;
559 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
567 *chainp
= cache_head
;
571 (ans
->flags
& F_FORWARD
) &&
572 (ans
->flags
& prot
) &&
573 hostname_isequal(cache_get_name(ans
), name
))
579 struct crec
*cache_find_by_addr(struct crec
*crecp
, struct all_addr
*addr
,
580 time_t now
, unsigned short prot
)
584 int addrlen
= (prot
== F_IPV6
) ? IN6ADDRSZ
: INADDRSZ
;
586 int addrlen
= INADDRSZ
;
589 if (crecp
) /* iterating */
593 /* first search, look for relevant entries and push to top of list
594 also free anything which has expired. All the reverse entries are at the
595 start of the hash chain, so we can give up when we find the first
598 struct crec
**up
, **chainp
= &ans
;
600 for (i
=0; i
<hash_size
; i
++)
601 for (crecp
= hash_table
[i
], up
= &hash_table
[i
];
602 crecp
&& (crecp
->flags
& F_REVERSE
);
603 crecp
= crecp
->hash_next
)
604 if (!is_expired(now
, crecp
))
606 if ((crecp
->flags
& prot
) &&
607 memcmp(&crecp
->addr
.addr
, addr
, addrlen
) == 0)
609 if (crecp
->flags
& (F_HOSTS
| F_DHCP
))
612 chainp
= &crecp
->next
;
620 up
= &crecp
->hash_next
;
624 *up
= crecp
->hash_next
;
625 if (!(crecp
->flags
& (F_HOSTS
| F_DHCP
)))
632 *chainp
= cache_head
;
636 (ans
->flags
& F_REVERSE
) &&
637 (ans
->flags
& prot
) &&
638 memcmp(&ans
->addr
.addr
, addr
, addrlen
) == 0)
644 static void add_hosts_entry(struct crec
*cache
, struct all_addr
*addr
, int addrlen
,
645 unsigned short flags
, int index
, int addr_dup
)
647 struct crec
*lookup
= cache_find_by_name(NULL
, cache
->name
.sname
, 0, flags
& (F_IPV4
| F_IPV6
));
648 int i
, nameexists
= 0;
651 /* Remove duplicates in hosts files. */
652 if (lookup
&& (lookup
->flags
& F_HOSTS
))
655 if (memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
662 /* Ensure there is only one address -> name mapping (first one trumps)
663 We do this by steam here, first we see if the address is the same as
664 the last one we saw, which eliminates most in the case of an ad-block
665 file with thousands of entries for the same address.
666 Then we search and bail at the first matching address that came from
667 a HOSTS file. Since the first host entry gets reverse, we know
668 then that it must exist without searching exhaustively for it. */
673 for (i
=0; i
<hash_size
; i
++)
675 for (lookup
= hash_table
[i
]; lookup
; lookup
= lookup
->hash_next
)
676 if ((lookup
->flags
& F_HOSTS
) &&
677 (lookup
->flags
& flags
& (F_IPV4
| F_IPV6
)) &&
678 memcmp(&lookup
->addr
.addr
, addr
, addrlen
) == 0)
687 cache
->flags
= flags
;
689 memcpy(&cache
->addr
.addr
, addr
, addrlen
);
692 /* don't need to do alias stuff for second and subsequent addresses. */
694 for (a
= daemon
->cnames
; a
; a
= a
->next
)
695 if (hostname_isequal(cache
->name
.sname
, a
->target
) &&
696 (lookup
= whine_malloc(sizeof(struct crec
))))
698 lookup
->flags
= F_FORWARD
| F_IMMORTAL
| F_CONFIG
| F_HOSTS
| F_CNAME
;
699 lookup
->name
.namep
= a
->alias
;
700 lookup
->addr
.cname
.cache
= cache
;
701 lookup
->addr
.cname
.uid
= index
;
706 static int eatspace(FILE *f
)
712 if ((c
= getc(f
)) == '#')
713 while (c
!= '\n' && c
!= EOF
)
730 static int gettok(FILE *f
, char *token
)
736 if ((c
= getc(f
)) == EOF
)
737 return (count
== 0) ? EOF
: 1;
739 if (isspace(c
) || c
== '#')
745 if (count
< (MAXDNAME
- 1))
753 static int read_hostsfile(char *filename
, int index
, int cache_size
)
755 FILE *f
= fopen(filename
, "r");
756 char *token
= daemon
->namebuff
, *domain_suffix
= NULL
;
757 int addr_count
= 0, name_count
= cache_size
, lineno
= 0;
758 unsigned short flags
= 0, saved_flags
= 0;
759 struct all_addr addr
, saved_addr
;
760 int atnl
, addrlen
= 0, addr_dup
;
764 my_syslog(LOG_ERR
, _("failed to load names from %s: %s"), filename
, strerror(errno
));
770 while ((atnl
= gettok(f
, token
)) != EOF
)
776 if (inet_pton(AF_INET
, token
, &addr
) > 0)
778 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
780 domain_suffix
= get_domain(addr
.addr
.addr4
);
782 else if (inet_pton(AF_INET6
, token
, &addr
) > 0)
784 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV6
;
786 domain_suffix
= daemon
->domain_suffix
;
789 if ((addr
.addr
.addr4
.s_addr
= inet_addr(token
)) != (in_addr_t
) -1)
791 flags
= F_HOSTS
| F_IMMORTAL
| F_FORWARD
| F_REVERSE
| F_IPV4
;
793 domain_suffix
= get_domain(addr
.addr
.addr4
);
798 my_syslog(LOG_ERR
, _("bad address at %s line %d"), filename
, lineno
);
800 atnl
= gettok(f
, token
);
804 if (saved_flags
== flags
&& memcmp(&addr
, &saved_addr
, addrlen
) == 0)
814 /* rehash every 1000 names. */
815 if ((name_count
- cache_size
) > 1000)
818 cache_size
= name_count
;
827 if ((atnl
= gettok(f
, token
)) == EOF
)
830 fqdn
= !!strchr(token
, '.');
832 if ((canon
= canonicalise(token
, &nomem
)))
834 /* If set, add a version of the name with a default domain appended */
835 if ((daemon
->options
& OPT_EXPAND
) && domain_suffix
&& !fqdn
&&
836 (cache
= whine_malloc(sizeof(struct crec
) +
837 strlen(canon
)+2+strlen(domain_suffix
)-SMALLDNAME
)))
839 strcpy(cache
->name
.sname
, canon
);
840 strcat(cache
->name
.sname
, ".");
841 strcat(cache
->name
.sname
, domain_suffix
);
842 add_hosts_entry(cache
, &addr
, addrlen
, flags
, index
, addr_dup
);
846 if ((cache
= whine_malloc(sizeof(struct crec
) + strlen(canon
)+1-SMALLDNAME
)))
848 strcpy(cache
->name
.sname
, canon
);
849 add_hosts_entry(cache
, &addr
, addrlen
, flags
, index
, addr_dup
);
856 my_syslog(LOG_ERR
, _("bad name at %s line %d"), filename
, lineno
);
863 my_syslog(LOG_INFO
, _("read %s - %d addresses"), filename
, addr_count
);
868 void cache_reload(void)
870 struct crec
*cache
, **up
, *tmp
;
871 int i
, total_size
= daemon
->cachesize
;
872 struct hostsfile
*ah
;
874 cache_inserted
= cache_live_freed
= 0;
876 for (i
=0; i
<hash_size
; i
++)
877 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= tmp
)
879 tmp
= cache
->hash_next
;
880 if (cache
->flags
& F_HOSTS
)
882 *up
= cache
->hash_next
;
885 else if (!(cache
->flags
& F_DHCP
))
887 *up
= cache
->hash_next
;
888 if (cache
->flags
& F_BIGNAME
)
890 cache
->name
.bname
->next
= big_free
;
891 big_free
= cache
->name
.bname
;
896 up
= &cache
->hash_next
;
899 if ((daemon
->options
& OPT_NO_HOSTS
) && !daemon
->addn_hosts
)
901 if (daemon
->cachesize
> 0)
902 my_syslog(LOG_INFO
, _("cleared cache"));
906 if (!(daemon
->options
& OPT_NO_HOSTS
))
907 total_size
= read_hostsfile(HOSTSFILE
, 0, total_size
);
909 for (i
= 0, ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
914 if (ah
->flags
& AH_DIR
)
915 ah
->flags
|= AH_INACTIVE
;
917 ah
->flags
&= ~AH_INACTIVE
;
920 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
921 if (!(ah
->flags
& AH_INACTIVE
))
924 if (stat(ah
->fname
, &buf
) != -1 && S_ISDIR(buf
.st_mode
))
929 /* don't read this as a file */
930 ah
->flags
|= AH_INACTIVE
;
932 if (!(dir_stream
= opendir(ah
->fname
)))
933 my_syslog(LOG_ERR
, _("cannot access directory %s: %s"),
934 ah
->fname
, strerror(errno
));
937 while ((ent
= readdir(dir_stream
)))
939 size_t lendir
= strlen(ah
->fname
);
940 size_t lenfile
= strlen(ent
->d_name
);
941 struct hostsfile
*ah1
;
944 /* ignore emacs backups and dotfiles */
946 ent
->d_name
[lenfile
- 1] == '~' ||
947 (ent
->d_name
[0] == '#' && ent
->d_name
[lenfile
- 1] == '#') ||
948 ent
->d_name
[0] == '.')
951 /* see if we have an existing record.
954 path to match is ah1->fname */
956 for (ah1
= daemon
->addn_hosts
; ah1
; ah1
= ah1
->next
)
958 if (lendir
< strlen(ah1
->fname
) &&
959 strstr(ah1
->fname
, ah
->fname
) == ah1
->fname
&&
960 ah1
->fname
[lendir
] == '/' &&
961 strcmp(ah1
->fname
+ lendir
+ 1, ent
->d_name
) == 0)
963 ah1
->flags
&= ~AH_INACTIVE
;
968 /* make new record */
971 if (!(ah1
= whine_malloc(sizeof(struct hostsfile
))))
974 if (!(path
= whine_malloc(lendir
+ lenfile
+ 2)))
980 strcpy(path
, ah
->fname
);
982 strcat(path
, ent
->d_name
);
986 ah1
->next
= daemon
->addn_hosts
;
987 daemon
->addn_hosts
= ah1
;
990 /* inactivate record if not regular file */
991 if ((ah1
->flags
& AH_DIR
) && stat(ah1
->fname
, &buf
) != -1 && !S_ISREG(buf
.st_mode
))
992 ah1
->flags
|= AH_INACTIVE
;
995 closedir(dir_stream
);
1000 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
1001 if (!(ah
->flags
& AH_INACTIVE
))
1002 total_size
= read_hostsfile(ah
->fname
, ah
->index
, total_size
);
1005 char *get_domain(struct in_addr addr
)
1007 struct cond_domain
*c
;
1009 for (c
= daemon
->cond_domain
; c
; c
= c
->next
)
1010 if (ntohl(addr
.s_addr
) >= ntohl(c
->start
.s_addr
) &&
1011 ntohl(addr
.s_addr
) <= ntohl(c
->end
.s_addr
))
1014 return daemon
->domain_suffix
;
1018 void cache_unhash_dhcp(void)
1020 struct crec
*cache
, **up
;
1023 for (i
=0; i
<hash_size
; i
++)
1024 for (cache
= hash_table
[i
], up
= &hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1025 if (cache
->flags
& F_DHCP
)
1027 *up
= cache
->hash_next
;
1028 cache
->next
= dhcp_spare
;
1032 up
= &cache
->hash_next
;
1035 void cache_add_dhcp_entry(char *host_name
,
1036 struct in_addr
*host_address
, time_t ttd
)
1038 struct crec
*crec
= NULL
, *aliasc
;
1039 unsigned short flags
= F_DHCP
| F_FORWARD
| F_IPV4
| F_REVERSE
;
1043 while ((crec
= cache_find_by_name(crec
, host_name
, 0, F_IPV4
| F_CNAME
)))
1045 /* check all addresses associated with name */
1046 if (crec
->flags
& F_HOSTS
)
1048 /* if in hosts, don't need DHCP record */
1051 if (crec
->flags
& F_CNAME
)
1052 my_syslog(LOG_WARNING
,
1053 _("%s is a CNAME, not giving it to the DHCP lease of %s"),
1054 host_name
, inet_ntoa(*host_address
));
1055 else if (crec
->addr
.addr
.addr
.addr4
.s_addr
!= host_address
->s_addr
)
1057 strcpy(daemon
->namebuff
, inet_ntoa(crec
->addr
.addr
.addr
.addr4
));
1058 my_syslog(LOG_WARNING
,
1059 _("not giving name %s to the DHCP lease of %s because "
1060 "the name exists in %s with address %s"),
1061 host_name
, inet_ntoa(*host_address
),
1062 record_source(crec
->uid
), daemon
->namebuff
);
1065 else if (!(crec
->flags
& F_DHCP
))
1067 cache_scan_free(host_name
, NULL
, 0, crec
->flags
& (F_IPV4
| F_CNAME
| F_FORWARD
));
1068 /* scan_free deletes all addresses associated with name */
1076 if ((crec
= cache_find_by_addr(NULL
, (struct all_addr
*)host_address
, 0, F_IPV4
)))
1078 if (crec
->flags
& F_NEG
)
1079 cache_scan_free(NULL
, (struct all_addr
*)host_address
, 0, F_IPV4
| F_REVERSE
);
1081 /* avoid multiple reverse mappings */
1082 flags
&= ~F_REVERSE
;
1085 if ((crec
= dhcp_spare
))
1086 dhcp_spare
= dhcp_spare
->next
;
1087 else /* need new one */
1088 crec
= whine_malloc(sizeof(struct crec
));
1090 if (crec
) /* malloc may fail */
1092 crec
->flags
= flags
;
1094 crec
->flags
|= F_IMMORTAL
;
1097 crec
->addr
.addr
.addr
.addr4
= *host_address
;
1098 crec
->name
.namep
= host_name
;
1102 for (a
= daemon
->cnames
; a
; a
= a
->next
)
1103 if (hostname_isequal(host_name
, a
->target
))
1105 if ((aliasc
= dhcp_spare
))
1106 dhcp_spare
= dhcp_spare
->next
;
1107 else /* need new one */
1108 aliasc
= whine_malloc(sizeof(struct crec
));
1112 aliasc
->flags
= F_FORWARD
| F_CONFIG
| F_DHCP
| F_CNAME
;
1114 aliasc
->flags
|= F_IMMORTAL
;
1117 aliasc
->name
.namep
= a
->alias
;
1118 aliasc
->addr
.cname
.cache
= crec
;
1119 aliasc
->addr
.cname
.uid
= crec
->uid
;
1128 void dump_cache(time_t now
)
1130 struct server
*serv
, *serv1
;
1132 my_syslog(LOG_INFO
, _("time %lu"), (unsigned long)now
);
1133 my_syslog(LOG_INFO
, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
1134 daemon
->cachesize
, cache_live_freed
, cache_inserted
);
1135 my_syslog(LOG_INFO
, _("queries forwarded %u, queries answered locally %u"),
1136 daemon
->queries_forwarded
, daemon
->local_answer
);
1138 if (!addrbuff
&& !(addrbuff
= whine_malloc(ADDRSTRLEN
)))
1141 /* sum counts from different records for same server */
1142 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1143 serv
->flags
&= ~SERV_COUNTED
;
1145 for (serv
= daemon
->servers
; serv
; serv
= serv
->next
)
1146 if (!(serv
->flags
& (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
)))
1149 unsigned int queries
= 0, failed_queries
= 0;
1150 for (serv1
= serv
; serv1
; serv1
= serv1
->next
)
1151 if (!(serv1
->flags
& (SERV_NO_ADDR
| SERV_LITERAL_ADDRESS
| SERV_COUNTED
)) && sockaddr_isequal(&serv
->addr
, &serv1
->addr
))
1153 serv1
->flags
|= SERV_COUNTED
;
1154 queries
+= serv1
->queries
;
1155 failed_queries
+= serv1
->failed_queries
;
1157 port
= prettyprint_addr(&serv
->addr
, addrbuff
);
1158 my_syslog(LOG_INFO
, _("server %s#%d: queries sent %u, retried or failed %u"), addrbuff
, port
, queries
, failed_queries
);
1161 if ((daemon
->options
& (OPT_DEBUG
| OPT_LOG
)))
1163 struct crec
*cache
;
1165 my_syslog(LOG_DEBUG
, "Host Address Flags Expires");
1167 for (i
=0; i
<hash_size
; i
++)
1168 for (cache
= hash_table
[i
]; cache
; cache
= cache
->hash_next
)
1170 char *a
, *p
= daemon
->namebuff
;
1171 p
+= sprintf(p
, "%-40.40s ", cache_get_name(cache
));
1172 if ((cache
->flags
& F_NEG
) && (cache
->flags
& F_FORWARD
))
1174 else if (cache
->flags
& F_CNAME
)
1177 if (!is_outdated_cname_pointer(cache
))
1178 a
= cache_get_name(cache
->addr
.cname
.cache
);
1184 if (cache
->flags
& F_IPV4
)
1185 inet_ntop(AF_INET
, &cache
->addr
.addr
, addrbuff
, ADDRSTRLEN
);
1186 else if (cache
->flags
& F_IPV6
)
1187 inet_ntop(AF_INET6
, &cache
->addr
.addr
, addrbuff
, ADDRSTRLEN
);
1191 a
= inet_ntoa(cache
->addr
.addr
.addr
.addr4
);
1193 p
+= sprintf(p
, "%-30.30s %s%s%s%s%s%s%s%s%s%s ", a
,
1194 cache
->flags
& F_IPV4
? "4" : "",
1195 cache
->flags
& F_IPV6
? "6" : "",
1196 cache
->flags
& F_CNAME
? "C" : "",
1197 cache
->flags
& F_FORWARD
? "F" : " ",
1198 cache
->flags
& F_REVERSE
? "R" : " ",
1199 cache
->flags
& F_IMMORTAL
? "I" : " ",
1200 cache
->flags
& F_DHCP
? "D" : " ",
1201 cache
->flags
& F_NEG
? "N" : " ",
1202 cache
->flags
& F_NXDOMAIN
? "X" : " ",
1203 cache
->flags
& F_HOSTS
? "H" : " ");
1204 #ifdef HAVE_BROKEN_RTC
1205 p
+= sprintf(p
, "%lu", cache
->flags
& F_IMMORTAL
? 0: (unsigned long)(cache
->ttd
- now
));
1207 p
+= sprintf(p
, "%s", cache
->flags
& F_IMMORTAL
? "\n" : ctime(&(cache
->ttd
)));
1208 /* ctime includes trailing \n - eat it */
1211 my_syslog(LOG_DEBUG
, daemon
->namebuff
);
1216 char *record_source(int index
)
1218 struct hostsfile
*ah
;
1223 for (ah
= daemon
->addn_hosts
; ah
; ah
= ah
->next
)
1224 if (ah
->index
== index
)
1230 void querystr(char *str
, unsigned short type
)
1234 sprintf(str
, "query[type=%d]", type
);
1235 for (i
= 0; i
< (sizeof(typestr
)/sizeof(typestr
[0])); i
++)
1236 if (typestr
[i
].type
== type
)
1237 sprintf(str
,"query[%s]", typestr
[i
].name
);
1240 void log_query(unsigned short flags
, char *name
, struct all_addr
*addr
, char *arg
)
1242 char *source
, *dest
= addrbuff
;
1245 if (!(daemon
->options
& OPT_LOG
))
1251 inet_ntop(flags
& F_IPV4
? AF_INET
: AF_INET6
,
1252 addr
, addrbuff
, ADDRSTRLEN
);
1254 strncpy(addrbuff
, inet_ntoa(addr
->addr
.addr4
), ADDRSTRLEN
);
1258 if (flags
& F_REVERSE
)
1266 if (flags
& F_NXDOMAIN
)
1269 dest
= "NXDOMAIN-IPv4";
1270 else if (flags
& F_IPV6
)
1271 dest
= "NXDOMAIN-IPv6";
1278 dest
= "NODATA-IPv4";
1279 else if (flags
& F_IPV6
)
1280 dest
= "NODATA-IPv6";
1285 else if (flags
& F_CNAME
)
1287 /* nasty abuse of NXDOMAIN and CNAME flags */
1288 if (flags
& F_NXDOMAIN
)
1294 if (flags
& F_CONFIG
)
1296 else if (flags
& F_DHCP
)
1298 else if (flags
& F_HOSTS
)
1300 else if (flags
& F_UPSTREAM
)
1302 else if (flags
& F_SERVER
)
1304 source
= "forwarded";
1307 else if (flags
& F_QUERY
)
1315 if (strlen(name
) == 0)
1318 my_syslog(LOG_DEBUG
, "%s %s %s %s", source
, name
, verb
, dest
);