Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 1 | /* dnsmasq is Copyright (c) 2000 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. |
| 6 | |
| 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. |
| 11 | */ |
| 12 | |
| 13 | #include "dnsmasq.h" |
| 14 | |
| 15 | static struct crec *cache_head, *cache_tail, **hash_table; |
| 16 | static struct crec *dhcp_inuse, *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; |
Simon Kelley | 26128d2 | 2004-11-14 16:43:54 +0000 | [diff] [blame^] | 20 | static int uid; |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 21 | |
| 22 | static void cache_free(struct crec *crecp); |
| 23 | static void cache_unlink(struct crec *crecp); |
| 24 | static void cache_link(struct crec *crecp); |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 25 | static char *record_source(struct hostsfile *add_hosts, int index); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 26 | |
| 27 | void cache_init(int size, int logq) |
| 28 | { |
| 29 | struct crec *crecp; |
| 30 | int i; |
| 31 | |
| 32 | log_queries = logq; |
| 33 | cache_head = cache_tail = NULL; |
| 34 | dhcp_inuse = dhcp_spare = NULL; |
| 35 | new_chain = NULL; |
| 36 | cache_size = size; |
| 37 | big_free = NULL; |
| 38 | bignames_left = size/10; |
Simon Kelley | 26128d2 | 2004-11-14 16:43:54 +0000 | [diff] [blame^] | 39 | uid = 0; |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 40 | |
| 41 | cache_inserted = cache_live_freed = 0; |
| 42 | |
| 43 | if (cache_size > 0) |
| 44 | { |
| 45 | crecp = safe_malloc(size*sizeof(struct crec)); |
| 46 | |
| 47 | for (i=0; i<size; i++, crecp++) |
| 48 | { |
| 49 | cache_link(crecp); |
| 50 | crecp->flags = 0; |
Simon Kelley | 26128d2 | 2004-11-14 16:43:54 +0000 | [diff] [blame^] | 51 | crecp->uid = uid++; |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 52 | } |
| 53 | } |
| 54 | |
| 55 | /* hash_size is a power of two. */ |
| 56 | for (hash_size = 64; hash_size < cache_size/10; hash_size = hash_size << 1); |
| 57 | hash_table = safe_malloc(hash_size*sizeof(struct crec *)); |
| 58 | for(i=0; i < hash_size; i++) |
| 59 | hash_table[i] = NULL; |
| 60 | } |
| 61 | |
| 62 | static struct crec **hash_bucket(unsigned char *name) |
| 63 | { |
| 64 | unsigned int c, val = 0; |
| 65 | |
| 66 | /* don't use tolower and friends here - they may be messed up by LOCALE */ |
| 67 | while((c = *name++)) |
| 68 | if (c >= 'A' && c <= 'Z') |
| 69 | val += c + 'a' - 'A'; |
| 70 | else |
| 71 | val += c; |
| 72 | |
| 73 | /* hash_size is a power of two */ |
| 74 | return hash_table + (val & (hash_size - 1)); |
| 75 | } |
| 76 | |
| 77 | static void cache_hash(struct crec *crecp) |
| 78 | { |
| 79 | struct crec **bucket = hash_bucket(cache_get_name(crecp)); |
| 80 | crecp->hash_next = *bucket; |
| 81 | *bucket = crecp; |
| 82 | } |
| 83 | |
| 84 | static void cache_free(struct crec *crecp) |
| 85 | { |
| 86 | crecp->flags &= ~F_FORWARD; |
| 87 | crecp->flags &= ~F_REVERSE; |
Simon Kelley | 26128d2 | 2004-11-14 16:43:54 +0000 | [diff] [blame^] | 88 | crecp->uid = uid++; /* invalidate CNAMES pointing to this. */ |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 89 | |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 90 | if (cache_tail) |
| 91 | cache_tail->next = crecp; |
| 92 | else |
| 93 | cache_head = crecp; |
| 94 | crecp->prev = cache_tail; |
| 95 | crecp->next = NULL; |
| 96 | cache_tail = crecp; |
| 97 | |
| 98 | /* retrieve big name for further use. */ |
| 99 | if (crecp->flags & F_BIGNAME) |
| 100 | { |
| 101 | crecp->name.bname->next = big_free; |
| 102 | big_free = crecp->name.bname; |
| 103 | crecp->flags &= ~F_BIGNAME; |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | /* insert a new cache entry at the head of the list (youngest entry) */ |
| 108 | static void cache_link(struct crec *crecp) |
| 109 | { |
| 110 | if (cache_head) /* check needed for init code */ |
| 111 | cache_head->prev = crecp; |
| 112 | crecp->next = cache_head; |
| 113 | crecp->prev = NULL; |
| 114 | cache_head = crecp; |
| 115 | if (!cache_tail) |
| 116 | cache_tail = crecp; |
| 117 | } |
| 118 | |
| 119 | /* remove an arbitrary cache entry for promotion */ |
| 120 | static void cache_unlink (struct crec *crecp) |
| 121 | { |
| 122 | if (crecp->prev) |
| 123 | crecp->prev->next = crecp->next; |
| 124 | else |
| 125 | cache_head = crecp->next; |
| 126 | |
| 127 | if (crecp->next) |
| 128 | crecp->next->prev = crecp->prev; |
| 129 | else |
| 130 | cache_tail = crecp->prev; |
| 131 | } |
| 132 | |
| 133 | char *cache_get_name(struct crec *crecp) |
| 134 | { |
| 135 | if (crecp->flags & F_BIGNAME) |
| 136 | return crecp->name.bname->name; |
| 137 | else if (crecp->flags & F_DHCP) |
| 138 | return crecp->name.namep; |
| 139 | |
| 140 | return crecp->name.sname; |
| 141 | } |
| 142 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 143 | static int is_outdated_cname_pointer(struct crec *crecp) |
| 144 | { |
| 145 | struct crec *target = crecp->addr.cname.cache; |
| 146 | |
| 147 | if (!(crecp->flags & F_CNAME)) |
| 148 | return 0; |
| 149 | |
| 150 | if (!target) |
| 151 | return 1; |
| 152 | |
| 153 | if (crecp->addr.cname.uid == target->uid) |
| 154 | return 0; |
| 155 | |
| 156 | return 1; |
| 157 | } |
| 158 | |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 159 | static void cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags) |
| 160 | { |
| 161 | /* Scan and remove old entries. |
| 162 | If (flags & F_FORWARD) then remove any forward entries for name and any expired |
| 163 | entries but only in the same hash bucket as name. |
| 164 | If (flags & F_REVERSE) then remove any reverse entries for addr and any expired |
| 165 | entries in the whole cache. |
| 166 | If (flags == 0) remove any expired entries in the whole cache. */ |
| 167 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 168 | #define F_CACHESTATUS (F_HOSTS | F_DHCP | F_FORWARD | F_REVERSE | F_IPV4 | F_IPV6 | F_CNAME) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 169 | struct crec *crecp, **up; |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 170 | flags &= (F_FORWARD | F_REVERSE | F_IPV6 | F_IPV4 | F_CNAME); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 171 | |
| 172 | if (flags & F_FORWARD) |
| 173 | { |
| 174 | for (up = hash_bucket(name), crecp = *up; crecp; crecp = crecp->hash_next) |
| 175 | if ((!(crecp->flags & F_IMMORTAL) && difftime(now, crecp->ttd) > 0) || |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 176 | is_outdated_cname_pointer(crecp) || |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 177 | ((flags == (crecp->flags & F_CACHESTATUS)) && hostname_isequal(cache_get_name(crecp), name))) |
| 178 | { |
| 179 | *up = crecp->hash_next; |
| 180 | if (!(crecp->flags & (F_HOSTS | F_DHCP))) |
| 181 | { |
| 182 | cache_unlink(crecp); |
| 183 | cache_free(crecp); |
| 184 | } |
| 185 | } |
| 186 | else |
| 187 | up = &crecp->hash_next; |
| 188 | } |
| 189 | else |
| 190 | { |
| 191 | int i; |
| 192 | #ifdef HAVE_IPV6 |
| 193 | int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ; |
| 194 | #else |
| 195 | int addrlen = INADDRSZ; |
| 196 | #endif |
| 197 | for (i = 0; i < hash_size; i++) |
| 198 | for (crecp = hash_table[i], up = &hash_table[i]; crecp; crecp = crecp->hash_next) |
| 199 | if ((!(crecp->flags & F_IMMORTAL) && difftime(now, crecp->ttd) > 0) || |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 200 | ((flags == (crecp->flags & F_CACHESTATUS)) && memcmp(&crecp->addr.addr, addr, addrlen) == 0)) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 201 | { |
| 202 | *up = crecp->hash_next; |
| 203 | if (!(crecp->flags & (F_HOSTS | F_DHCP))) |
| 204 | { |
| 205 | cache_unlink(crecp); |
| 206 | cache_free(crecp); |
| 207 | } |
| 208 | } |
| 209 | else |
| 210 | up = &crecp->hash_next; |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | /* Note: The normal calling sequence is |
| 215 | cache_start_insert |
| 216 | cache_insert * n |
| 217 | cache_end_insert |
| 218 | |
| 219 | but an abort can cause the cache_end_insert to be missed |
| 220 | in which can the next cache_start_insert cleans things up. */ |
| 221 | |
| 222 | void cache_start_insert(void) |
| 223 | { |
| 224 | /* Free any entries which didn't get committed during the last |
| 225 | insert due to error. |
| 226 | */ |
| 227 | while (new_chain) |
| 228 | { |
| 229 | struct crec *tmp = new_chain->next; |
| 230 | cache_free(new_chain); |
| 231 | new_chain = tmp; |
| 232 | } |
| 233 | new_chain = NULL; |
| 234 | insert_error = 0; |
| 235 | } |
| 236 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 237 | struct crec *cache_insert(char *name, struct all_addr *addr, |
| 238 | time_t now, unsigned long ttl, unsigned short flags) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 239 | { |
| 240 | #ifdef HAVE_IPV6 |
| 241 | int addrlen = (flags & F_IPV6) ? IN6ADDRSZ : INADDRSZ; |
| 242 | #else |
| 243 | int addrlen = INADDRSZ; |
| 244 | #endif |
| 245 | struct crec *new; |
| 246 | union bigname *big_name = NULL; |
| 247 | int freed_all = flags & F_REVERSE; |
| 248 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 249 | log_query(flags | F_UPSTREAM, name, addr, 0, NULL, 0); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 250 | |
| 251 | /* name is needed as workspace by log_query in this case */ |
| 252 | if ((flags & F_NEG) && (flags & F_REVERSE)) |
| 253 | name = NULL; |
| 254 | |
| 255 | /* CONFIG bit no needed except for logging */ |
| 256 | flags &= ~F_CONFIG; |
| 257 | |
| 258 | /* if previous insertion failed give up now. */ |
| 259 | if (insert_error) |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 260 | return NULL; |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 261 | |
| 262 | /* First remove any expired entries and entries for the name/address we |
| 263 | are currently inserting. */ |
| 264 | cache_scan_free(name, addr, now, flags); |
| 265 | |
| 266 | /* Now get a cache entry from the end of the LRU list */ |
| 267 | while (1) { |
| 268 | if (!(new = cache_tail)) /* no entries left - cache is too small, bail */ |
| 269 | { |
| 270 | insert_error = 1; |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 271 | return NULL; |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 272 | } |
| 273 | |
| 274 | /* End of LRU list is still in use: if we didn't scan all the hash |
| 275 | chains for expired entries do that now. If we already tried that |
| 276 | then it's time to start spilling things. */ |
| 277 | |
| 278 | if (new->flags & (F_FORWARD | F_REVERSE)) |
| 279 | { |
| 280 | if (freed_all) |
| 281 | { |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 282 | cache_scan_free(cache_get_name(new), &new->addr.addr, now, new->flags); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 283 | cache_live_freed++; |
| 284 | } |
| 285 | else |
| 286 | { |
| 287 | cache_scan_free(NULL, NULL, now, 0); |
| 288 | freed_all = 1; |
| 289 | } |
| 290 | continue; |
| 291 | } |
| 292 | |
| 293 | /* Check if we need to and can allocate extra memory for a long name. |
| 294 | If that fails, give up now. */ |
| 295 | if (name && (strlen(name) > SMALLDNAME-1)) |
| 296 | { |
| 297 | if (big_free) |
| 298 | { |
| 299 | big_name = big_free; |
| 300 | big_free = big_free->next; |
| 301 | } |
| 302 | else if (!bignames_left || |
| 303 | !(big_name = (union bigname *)malloc(sizeof(union bigname)))) |
| 304 | { |
| 305 | insert_error = 1; |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 306 | return NULL; |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 307 | } |
| 308 | else |
| 309 | bignames_left--; |
| 310 | |
| 311 | } |
| 312 | |
| 313 | /* Got the rest: finally grab entry. */ |
| 314 | cache_unlink(new); |
| 315 | break; |
| 316 | } |
| 317 | |
| 318 | new->flags = flags; |
| 319 | if (big_name) |
| 320 | { |
| 321 | new->name.bname = big_name; |
| 322 | new->flags |= F_BIGNAME; |
| 323 | } |
| 324 | if (name) |
| 325 | strcpy(cache_get_name(new), name); |
| 326 | else |
| 327 | *cache_get_name(new) = 0; |
| 328 | if (addr) |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 329 | memcpy(&new->addr.addr, addr, addrlen); |
| 330 | else |
| 331 | new->addr.cname.cache = NULL; |
| 332 | |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 333 | new->ttd = now + (time_t)ttl; |
| 334 | new->next = new_chain; |
| 335 | new_chain = new; |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 336 | |
| 337 | return new; |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 338 | } |
| 339 | |
| 340 | /* after end of insertion, commit the new entries */ |
| 341 | void cache_end_insert(void) |
| 342 | { |
| 343 | if (insert_error) |
| 344 | return; |
| 345 | |
| 346 | while (new_chain) |
| 347 | { |
| 348 | struct crec *tmp = new_chain->next; |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 349 | /* drop CNAMEs which didn't find a target. */ |
| 350 | if (is_outdated_cname_pointer(new_chain)) |
| 351 | cache_free(new_chain); |
| 352 | else |
| 353 | { |
| 354 | cache_hash(new_chain); |
| 355 | cache_link(new_chain); |
| 356 | cache_inserted++; |
| 357 | } |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 358 | new_chain = tmp; |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 359 | } |
| 360 | new_chain = NULL; |
| 361 | } |
| 362 | |
| 363 | struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned short prot) |
| 364 | { |
| 365 | struct crec *ans; |
| 366 | |
| 367 | if (crecp) /* iterating */ |
| 368 | ans = crecp->next; |
| 369 | else |
| 370 | { |
| 371 | /* first search, look for relevant entries and push to top of list |
| 372 | also free anything which has expired */ |
| 373 | struct crec *next, **up, **insert = NULL, **chainp = &ans; |
| 374 | |
| 375 | for (up = hash_bucket(name), crecp = *up; crecp; crecp = next) |
| 376 | { |
| 377 | next = crecp->hash_next; |
| 378 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 379 | if (!is_outdated_cname_pointer(crecp) && |
| 380 | ((crecp->flags & F_IMMORTAL) || difftime(now, crecp->ttd) < 0)) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 381 | { |
| 382 | if ((crecp->flags & F_FORWARD) && |
| 383 | (crecp->flags & prot) && |
| 384 | hostname_isequal(cache_get_name(crecp), name)) |
| 385 | { |
| 386 | if (crecp->flags & (F_HOSTS | F_DHCP)) |
| 387 | { |
| 388 | *chainp = crecp; |
| 389 | chainp = &crecp->next; |
| 390 | } |
| 391 | else |
| 392 | { |
| 393 | cache_unlink(crecp); |
| 394 | cache_link(crecp); |
| 395 | } |
| 396 | |
| 397 | /* move all but the first entry up the hash chain |
| 398 | this implements round-robin */ |
| 399 | if (!insert) |
| 400 | { |
| 401 | insert = up; |
| 402 | up = &crecp->hash_next; |
| 403 | } |
| 404 | else |
| 405 | { |
| 406 | *up = crecp->hash_next; |
| 407 | crecp->hash_next = *insert; |
| 408 | *insert = crecp; |
| 409 | insert = &crecp->hash_next; |
| 410 | } |
| 411 | } |
| 412 | else |
| 413 | /* case : not expired, incorrect entry. */ |
| 414 | up = &crecp->hash_next; |
| 415 | } |
| 416 | else |
| 417 | { |
| 418 | /* expired entry, free it */ |
| 419 | *up = crecp->hash_next; |
| 420 | if (!(crecp->flags & (F_HOSTS | F_DHCP))) |
| 421 | { |
| 422 | cache_unlink(crecp); |
| 423 | cache_free(crecp); |
| 424 | } |
| 425 | } |
| 426 | } |
| 427 | |
| 428 | *chainp = cache_head; |
| 429 | } |
| 430 | |
| 431 | if (ans && |
| 432 | (ans->flags & F_FORWARD) && |
| 433 | (ans->flags & prot) && |
| 434 | hostname_isequal(cache_get_name(ans), name)) |
| 435 | return ans; |
| 436 | |
| 437 | return NULL; |
| 438 | } |
| 439 | |
| 440 | struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr, |
| 441 | time_t now, unsigned short prot) |
| 442 | { |
| 443 | struct crec *ans; |
| 444 | #ifdef HAVE_IPV6 |
| 445 | int addrlen = (prot == F_IPV6) ? IN6ADDRSZ : INADDRSZ; |
| 446 | #else |
| 447 | int addrlen = INADDRSZ; |
| 448 | #endif |
| 449 | |
| 450 | if (crecp) /* iterating */ |
| 451 | ans = crecp->next; |
| 452 | else |
| 453 | { |
| 454 | /* first search, look for relevant entries and push to top of list |
| 455 | also free anything which has expired */ |
| 456 | int i; |
| 457 | struct crec **up, **chainp = &ans; |
| 458 | |
| 459 | for(i=0; i<hash_size; i++) |
| 460 | for (crecp = hash_table[i], up = &hash_table[i]; crecp; crecp = crecp->hash_next) |
| 461 | if ((crecp->flags & F_IMMORTAL) || difftime(now, crecp->ttd) < 0) |
| 462 | { |
| 463 | if ((crecp->flags & F_REVERSE) && |
| 464 | (crecp->flags & prot) && |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 465 | memcmp(&crecp->addr.addr, addr, addrlen) == 0) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 466 | { |
| 467 | if (crecp->flags & (F_HOSTS | F_DHCP)) |
| 468 | { |
| 469 | *chainp = crecp; |
| 470 | chainp = &crecp->next; |
| 471 | } |
| 472 | else |
| 473 | { |
| 474 | cache_unlink(crecp); |
| 475 | cache_link(crecp); |
| 476 | } |
| 477 | } |
| 478 | up = &crecp->hash_next; |
| 479 | } |
| 480 | else |
| 481 | { |
| 482 | *up = crecp->hash_next; |
| 483 | if (!(crecp->flags & (F_HOSTS | F_DHCP))) |
| 484 | { |
| 485 | cache_unlink(crecp); |
| 486 | cache_free(crecp); |
| 487 | } |
| 488 | } |
| 489 | |
| 490 | *chainp = cache_head; |
| 491 | } |
| 492 | |
| 493 | if (ans && |
| 494 | (ans->flags & F_REVERSE) && |
| 495 | (ans->flags & prot) && |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 496 | memcmp(&ans->addr.addr, addr, addrlen) == 0) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 497 | return ans; |
| 498 | |
| 499 | return NULL; |
| 500 | } |
| 501 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 502 | static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen, |
| 503 | unsigned short flags, int index) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 504 | { |
| 505 | struct crec *lookup = cache_find_by_name(NULL, cache->name.sname, 0, flags & (F_IPV4 | F_IPV6)); |
| 506 | |
| 507 | /* Remove duplicates in hosts files. */ |
Simon Kelley | de37951 | 2004-06-22 20:23:33 +0100 | [diff] [blame] | 508 | if (lookup && (lookup->flags & F_HOSTS) && |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 509 | memcmp(&lookup->addr.addr, addr, addrlen) == 0) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 510 | free(cache); |
| 511 | else |
| 512 | { |
Simon Kelley | de37951 | 2004-06-22 20:23:33 +0100 | [diff] [blame] | 513 | /* Ensure there is only one address -> name mapping (first one trumps) */ |
| 514 | if (cache_find_by_addr(NULL, addr, 0, flags & (F_IPV4 | F_IPV6))) |
| 515 | flags &= ~F_REVERSE; |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 516 | cache->flags = flags; |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 517 | cache->uid = index; |
| 518 | memcpy(&cache->addr.addr, addr, addrlen); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 519 | cache_hash(cache); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 520 | } |
| 521 | } |
| 522 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 523 | static void read_hostsfile(char *filename, int opts, char *buff, char *domain_suffix, int index) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 524 | { |
| 525 | FILE *f = fopen(filename, "r"); |
| 526 | char *line; |
| 527 | int count = 0, lineno = 0; |
| 528 | |
| 529 | if (!f) |
| 530 | { |
| 531 | syslog(LOG_ERR, "failed to load names from %s: %m", filename); |
| 532 | return; |
| 533 | } |
| 534 | |
| 535 | while ((line = fgets(buff, MAXDNAME, f))) |
| 536 | { |
| 537 | struct all_addr addr; |
| 538 | char *token = strtok(line, " \t\n\r"); |
| 539 | int addrlen; |
| 540 | unsigned short flags; |
| 541 | |
| 542 | lineno++; |
| 543 | |
| 544 | if (!token || (*token == '#')) |
| 545 | continue; |
| 546 | |
| 547 | #ifdef HAVE_IPV6 |
| 548 | if (inet_pton(AF_INET, token, &addr) == 1) |
| 549 | { |
| 550 | flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4; |
| 551 | addrlen = INADDRSZ; |
| 552 | } |
| 553 | else if (inet_pton(AF_INET6, token, &addr) == 1) |
| 554 | { |
| 555 | flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6; |
| 556 | addrlen = IN6ADDRSZ; |
| 557 | } |
| 558 | #else |
| 559 | if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1) |
| 560 | { |
| 561 | flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4; |
| 562 | addrlen = INADDRSZ; |
| 563 | } |
| 564 | #endif |
| 565 | else |
| 566 | continue; |
| 567 | |
| 568 | while ((token = strtok(NULL, " \t\n\r")) && (*token != '#')) |
| 569 | { |
| 570 | struct crec *cache; |
| 571 | if (canonicalise(token)) |
| 572 | { |
| 573 | count++; |
| 574 | /* If set, add a version of the name with a default domain appended */ |
| 575 | if ((opts & OPT_EXPAND) && domain_suffix && !strchr(token, '.') && |
| 576 | (cache = malloc(sizeof(struct crec) + |
| 577 | strlen(token)+2+strlen(domain_suffix)-SMALLDNAME))) |
| 578 | { |
| 579 | strcpy(cache->name.sname, token); |
| 580 | strcat(cache->name.sname, "."); |
| 581 | strcat(cache->name.sname, domain_suffix); |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 582 | add_hosts_entry(cache, &addr, addrlen, flags, index); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 583 | } |
| 584 | if ((cache = malloc(sizeof(struct crec) + strlen(token)+1-SMALLDNAME))) |
| 585 | { |
| 586 | strcpy(cache->name.sname, token); |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 587 | add_hosts_entry(cache, &addr, addrlen, flags, index); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 588 | } |
| 589 | } |
| 590 | else |
| 591 | syslog(LOG_ERR, "bad name at %s line %d", filename, lineno); |
| 592 | } |
| 593 | } |
| 594 | |
| 595 | fclose(f); |
| 596 | |
| 597 | syslog(LOG_INFO, "read %s - %d addresses", filename, count); |
| 598 | } |
| 599 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 600 | void cache_reload(int opts, char *buff, char *domain_suffix, struct hostsfile *addn_hosts) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 601 | { |
| 602 | struct crec *cache, **up, *tmp; |
| 603 | int i; |
| 604 | |
| 605 | for (i=0; i<hash_size; i++) |
| 606 | for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp) |
| 607 | { |
| 608 | tmp = cache->hash_next; |
| 609 | if (cache->flags & F_HOSTS) |
| 610 | { |
| 611 | *up = cache->hash_next; |
| 612 | free(cache); |
| 613 | } |
| 614 | else if (!(cache->flags & F_DHCP)) |
| 615 | { |
| 616 | *up = cache->hash_next; |
| 617 | if (cache->flags & F_BIGNAME) |
| 618 | { |
| 619 | cache->name.bname->next = big_free; |
| 620 | big_free = cache->name.bname; |
| 621 | } |
| 622 | cache->flags = 0; |
| 623 | } |
| 624 | else |
| 625 | up = &cache->hash_next; |
| 626 | } |
| 627 | |
| 628 | if ((opts & OPT_NO_HOSTS) && !addn_hosts) |
| 629 | { |
| 630 | if (cache_size > 0) |
| 631 | syslog(LOG_INFO, "cleared cache"); |
| 632 | return; |
| 633 | } |
| 634 | |
| 635 | if (!(opts & OPT_NO_HOSTS)) |
| 636 | read_hostsfile(HOSTSFILE, opts, buff, domain_suffix, 0); |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 637 | while (addn_hosts) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 638 | { |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 639 | read_hostsfile(addn_hosts->fname, opts, buff, domain_suffix, addn_hosts->index); |
| 640 | addn_hosts = addn_hosts->next; |
| 641 | } |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 642 | } |
| 643 | |
| 644 | void cache_unhash_dhcp(void) |
| 645 | { |
| 646 | struct crec *tmp, *cache, **up; |
| 647 | int i; |
| 648 | |
| 649 | for (i=0; i<hash_size; i++) |
| 650 | for (cache = hash_table[i], up = &hash_table[i]; cache; cache = cache->hash_next) |
| 651 | if (cache->flags & F_DHCP) |
| 652 | *up = cache->hash_next; |
| 653 | else |
| 654 | up = &cache->hash_next; |
| 655 | |
| 656 | /* prev field links all dhcp entries */ |
| 657 | for (cache = dhcp_inuse; cache; cache = tmp) |
| 658 | { |
| 659 | tmp = cache->prev; |
| 660 | cache->prev = dhcp_spare; |
| 661 | dhcp_spare = cache; |
| 662 | } |
| 663 | |
| 664 | dhcp_inuse = NULL; |
| 665 | } |
| 666 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 667 | void cache_add_dhcp_entry(struct daemon *daemon, char *host_name, |
| 668 | struct in_addr *host_address, time_t ttd) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 669 | { |
| 670 | struct crec *crec; |
Simon Kelley | c1bb850 | 2004-08-11 18:40:17 +0100 | [diff] [blame] | 671 | unsigned short flags = F_DHCP | F_FORWARD | F_IPV4 | F_REVERSE; |
| 672 | |
Simon Kelley | 9c74ec0 | 2004-08-13 21:13:03 +0100 | [diff] [blame] | 673 | if (!host_name) |
| 674 | return; |
| 675 | |
Simon Kelley | 26128d2 | 2004-11-14 16:43:54 +0000 | [diff] [blame^] | 676 | if ((crec = cache_find_by_name(NULL, host_name, 0, F_IPV4 | F_CNAME))) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 677 | { |
| 678 | if (crec->flags & F_HOSTS) |
Simon Kelley | 1ab84e2 | 2004-01-29 16:48:35 +0000 | [diff] [blame] | 679 | { |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 680 | if (crec->addr.addr.addr.addr4.s_addr != host_address->s_addr) |
| 681 | { |
| 682 | strcpy(daemon->namebuff, inet_ntoa(crec->addr.addr.addr.addr4)); |
| 683 | syslog(LOG_WARNING, |
Simon Kelley | 26128d2 | 2004-11-14 16:43:54 +0000 | [diff] [blame^] | 684 | "not giving name %s to the DHCP lease of %s because " |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 685 | "the name exists in %s with address %s", |
| 686 | host_name, inet_ntoa(*host_address), |
| 687 | record_source(daemon->addn_hosts, crec->uid), daemon->namebuff); |
| 688 | } |
Simon Kelley | c1bb850 | 2004-08-11 18:40:17 +0100 | [diff] [blame] | 689 | return; |
Simon Kelley | 1ab84e2 | 2004-01-29 16:48:35 +0000 | [diff] [blame] | 690 | } |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 691 | else if (!(crec->flags & F_DHCP)) |
Simon Kelley | 26128d2 | 2004-11-14 16:43:54 +0000 | [diff] [blame^] | 692 | cache_scan_free(host_name, NULL, 0, crec->flags & (F_IPV4 | F_CNAME | F_FORWARD)); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 693 | } |
| 694 | |
Simon Kelley | c1bb850 | 2004-08-11 18:40:17 +0100 | [diff] [blame] | 695 | if ((crec = cache_find_by_addr(NULL, (struct all_addr *)host_address, 0, F_IPV4))) |
| 696 | { |
| 697 | if (crec->flags & F_NEG) |
| 698 | cache_scan_free(NULL, (struct all_addr *)host_address, 0, F_IPV4 | F_REVERSE); |
| 699 | else |
| 700 | /* avoid multiple reverse mappings */ |
| 701 | flags &= ~F_REVERSE; |
| 702 | } |
| 703 | |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 704 | if ((crec = dhcp_spare)) |
| 705 | dhcp_spare = dhcp_spare->prev; |
| 706 | else /* need new one */ |
| 707 | crec = malloc(sizeof(struct crec)); |
| 708 | |
| 709 | if (crec) /* malloc may fail */ |
| 710 | { |
Simon Kelley | c1bb850 | 2004-08-11 18:40:17 +0100 | [diff] [blame] | 711 | crec->flags = flags; |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 712 | if (ttd == 0) |
| 713 | crec->flags |= F_IMMORTAL; |
| 714 | else |
| 715 | crec->ttd = ttd; |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 716 | crec->addr.addr.addr.addr4 = *host_address; |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 717 | crec->name.namep = host_name; |
| 718 | crec->prev = dhcp_inuse; |
| 719 | dhcp_inuse = crec; |
| 720 | cache_hash(crec); |
| 721 | } |
| 722 | } |
| 723 | |
| 724 | |
| 725 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 726 | void dump_cache(struct daemon *daemon) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 727 | { |
Simon Kelley | 1cff166 | 2004-03-12 08:12:58 +0000 | [diff] [blame] | 728 | syslog(LOG_INFO, "cache size %d, %d/%d cache insertions re-used unexpired cache entries.", |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 729 | daemon->cachesize, cache_live_freed, cache_inserted); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 730 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 731 | if (daemon->options & (OPT_DEBUG | OPT_LOG)) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 732 | { |
| 733 | struct crec *cache ; |
| 734 | char addrbuff[ADDRSTRLEN]; |
| 735 | int i; |
| 736 | syslog(LOG_DEBUG, "Host Address Flags Expires\n"); |
| 737 | |
| 738 | for (i=0; i<hash_size; i++) |
| 739 | for (cache = hash_table[i]; cache; cache = cache->hash_next) |
| 740 | { |
| 741 | if ((cache->flags & F_NEG) && (cache->flags & F_FORWARD)) |
| 742 | addrbuff[0] = 0; |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 743 | else if (cache->flags & F_CNAME) |
| 744 | { |
| 745 | addrbuff[0] = 0; |
| 746 | addrbuff[ADDRSTRLEN-1] = 0; |
| 747 | if (!is_outdated_cname_pointer(cache)) |
| 748 | strncpy(addrbuff, cache_get_name(cache->addr.cname.cache), ADDRSTRLEN); |
| 749 | } |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 750 | #ifdef HAVE_IPV6 |
| 751 | else if (cache->flags & F_IPV4) |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 752 | inet_ntop(AF_INET, &cache->addr.addr, addrbuff, ADDRSTRLEN); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 753 | else if (cache->flags & F_IPV6) |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 754 | inet_ntop(AF_INET6, &cache->addr.addr, addrbuff, ADDRSTRLEN); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 755 | #else |
| 756 | else |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 757 | strcpy(addrbuff, inet_ntoa(cache->addr.addr.addr.addr4)); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 758 | #endif |
Simon Kelley | 44a2a31 | 2004-03-10 20:04:35 +0000 | [diff] [blame] | 759 | syslog(LOG_DEBUG, |
| 760 | #ifdef HAVE_BROKEN_RTC |
| 761 | "%-40.40s %-30.30s %s%s%s%s%s%s%s%s%s%s %ld\n", |
| 762 | #else |
| 763 | "%-40.40s %-30.30s %s%s%s%s%s%s%s%s%s%s %s", |
| 764 | #endif |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 765 | cache_get_name(cache), addrbuff, |
| 766 | cache->flags & F_IPV4 ? "4" : "", |
| 767 | cache->flags & F_IPV6 ? "6" : "", |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 768 | cache->flags & F_CNAME ? "C" : "", |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 769 | cache->flags & F_FORWARD ? "F" : " ", |
| 770 | cache->flags & F_REVERSE ? "R" : " ", |
| 771 | cache->flags & F_IMMORTAL ? "I" : " ", |
| 772 | cache->flags & F_DHCP ? "D" : " ", |
| 773 | cache->flags & F_NEG ? "N" : " ", |
| 774 | cache->flags & F_NXDOMAIN ? "X" : " ", |
| 775 | cache->flags & F_HOSTS ? "H" : " ", |
Simon Kelley | 44a2a31 | 2004-03-10 20:04:35 +0000 | [diff] [blame] | 776 | #ifdef HAVE_BROKEN_RTC |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 777 | cache->flags & F_IMMORTAL ? 0: (unsigned long)cache->ttd |
Simon Kelley | 44a2a31 | 2004-03-10 20:04:35 +0000 | [diff] [blame] | 778 | #else |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 779 | cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd)) |
Simon Kelley | 44a2a31 | 2004-03-10 20:04:35 +0000 | [diff] [blame] | 780 | #endif |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 781 | ); |
| 782 | } |
| 783 | } |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 784 | } |
| 785 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 786 | static char *record_source(struct hostsfile *addn_hosts, int index) |
| 787 | { |
| 788 | char *source = HOSTSFILE; |
| 789 | while (addn_hosts) |
| 790 | { |
| 791 | if (addn_hosts->index == index) |
| 792 | { |
| 793 | source = addn_hosts->fname; |
| 794 | break; |
| 795 | } |
| 796 | addn_hosts = addn_hosts->next; |
| 797 | } |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 798 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 799 | return source; |
| 800 | } |
Simon Kelley | c1bb850 | 2004-08-11 18:40:17 +0100 | [diff] [blame] | 801 | |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 802 | void log_query(unsigned short flags, char *name, struct all_addr *addr, |
| 803 | unsigned short type, struct hostsfile *addn_hosts, int index) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 804 | { |
| 805 | char *source; |
| 806 | char *verb = "is"; |
Simon Kelley | c1bb850 | 2004-08-11 18:40:17 +0100 | [diff] [blame] | 807 | char types[20]; |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 808 | char addrbuff[ADDRSTRLEN]; |
Simon Kelley | c1bb850 | 2004-08-11 18:40:17 +0100 | [diff] [blame] | 809 | |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 810 | if (!log_queries) |
| 811 | return; |
| 812 | |
Simon Kelley | c1bb850 | 2004-08-11 18:40:17 +0100 | [diff] [blame] | 813 | strcpy(types, " "); |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 814 | |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 815 | if (flags & F_NEG) |
| 816 | { |
| 817 | if (flags & F_REVERSE) |
| 818 | #ifdef HAVE_IPV6 |
| 819 | inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6, |
| 820 | addr, name, MAXDNAME); |
| 821 | #else |
| 822 | strcpy(name, inet_ntoa(addr->addr.addr4)); |
| 823 | #endif |
| 824 | |
| 825 | if (flags & F_NXDOMAIN) |
Simon Kelley | 44a2a31 | 2004-03-10 20:04:35 +0000 | [diff] [blame] | 826 | strcpy(addrbuff, "<NXDOMAIN>"); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 827 | else |
Simon Kelley | 44a2a31 | 2004-03-10 20:04:35 +0000 | [diff] [blame] | 828 | strcpy(addrbuff, "<NODATA>"); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 829 | |
| 830 | if (flags & F_IPV4) |
Simon Kelley | 44a2a31 | 2004-03-10 20:04:35 +0000 | [diff] [blame] | 831 | strcat(addrbuff, "-IPv4"); |
| 832 | else if (flags & F_IPV6) |
| 833 | strcat(addrbuff, "-IPv6"); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 834 | } |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 835 | else if (flags & F_CNAME) |
| 836 | strcpy(addrbuff, "<CNAME>"); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 837 | else |
| 838 | #ifdef HAVE_IPV6 |
| 839 | inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6, |
| 840 | addr, addrbuff, ADDRSTRLEN); |
| 841 | #else |
| 842 | strcpy(addrbuff, inet_ntoa(addr->addr.addr4)); |
| 843 | #endif |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 844 | |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 845 | if (flags & F_DHCP) |
| 846 | source = "DHCP"; |
| 847 | else if (flags & F_HOSTS) |
Simon Kelley | fd9fa48 | 2004-10-21 20:24:00 +0100 | [diff] [blame] | 848 | source = record_source(addn_hosts, index); |
| 849 | else if (flags & F_CONFIG) |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 850 | source = "config"; |
| 851 | else if (flags & F_UPSTREAM) |
| 852 | source = "reply"; |
| 853 | else if (flags & F_SERVER) |
| 854 | { |
| 855 | source = "forwarded"; |
| 856 | verb = "to"; |
| 857 | } |
| 858 | else if (flags & F_QUERY) |
| 859 | { |
Simon Kelley | c1bb850 | 2004-08-11 18:40:17 +0100 | [diff] [blame] | 860 | unsigned int i; |
| 861 | static struct { |
| 862 | unsigned int type; |
| 863 | char *name; |
| 864 | } typestr[] = { |
| 865 | { 1, "A" }, |
| 866 | { 2, "NS" }, |
| 867 | { 5, "CNAME" }, |
| 868 | { 6, "SOA" }, |
| 869 | { 10, "NULL" }, |
| 870 | { 11, "WKS" }, |
| 871 | { 12, "PTR" }, |
| 872 | { 13, "HINFO" }, |
| 873 | { 15, "MX" }, |
| 874 | { 16, "TXT" }, |
| 875 | { 22, "NSAP" }, |
| 876 | { 23, "NSAP_PTR" }, |
| 877 | { 24, "SIG" }, |
| 878 | { 25, "KEY" }, |
| 879 | { 28, "AAAA" }, |
| 880 | { 33, "SRV" }, |
| 881 | { 36, "KX" }, |
| 882 | { 37, "CERT" }, |
| 883 | { 38, "A6" }, |
| 884 | { 39, "DNAME" }, |
| 885 | { 41, "OPT" }, |
| 886 | { 250, "TSIG" }, |
| 887 | { 251, "IXFR" }, |
| 888 | { 252, "AXFR" }, |
| 889 | { 253, "MAILB" }, |
| 890 | { 254, "MAILA" }, |
| 891 | { 255, "ANY" } |
| 892 | }; |
| 893 | |
| 894 | if (type != 0) |
| 895 | { |
| 896 | sprintf(types, "[type=%d] ", type); |
| 897 | for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++) |
| 898 | if (typestr[i].type == type) |
| 899 | sprintf(types,"[%s] ", typestr[i].name); |
| 900 | } |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 901 | source = "query"; |
| 902 | verb = "from"; |
| 903 | } |
| 904 | else |
| 905 | source = "cached"; |
| 906 | |
| 907 | if ((flags & F_FORWARD) | (flags & F_NEG)) |
Simon Kelley | c1bb850 | 2004-08-11 18:40:17 +0100 | [diff] [blame] | 908 | syslog(LOG_DEBUG, "%s %s%s%s %s", source, name, types, verb, addrbuff); |
Simon Kelley | 9e4abcb | 2004-01-22 19:47:41 +0000 | [diff] [blame] | 909 | else if (flags & F_REVERSE) |
| 910 | syslog(LOG_DEBUG, "%s %s is %s", source, addrbuff, name); |
| 911 | } |
| 912 | |