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