/* * * dumpcache-expire v0.3 * * quick and dirty hacked tool to expire an entry in djbdns dnscache's cache * by setting expiration time to 0. * needs the dumpcache-patch from http://www.efge.org/djbdns/ * * http://plonk.de/sw/djb/dumpcache-expire.c * (C) 2003 Jakob Hirsch (dumpcache@plonk.de) * * Changes in 0.3: * - cleanups, stability and speed improvements * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * [http://www.fsf.org/licenses/gpl.txt] * */ #include #include #include #include #include #include #include #include #include /* wait for dnscache to dump **************************************/ void dumpandwait(const char *dumpcache) { struct stat st; time_t mtime; int count; stat(dumpcache, &st); mtime = st.st_mtime; system("svc -a /service/dnscache"); for (count = 0; count < 10; ++count) { usleep(100000); /* sleep 100ms */ stat(dumpcache, &st); if (mtime != st.st_mtime) return; } printf("timeout waiting for dnscache dump\n"); exit(-1); } /* convert fqdns to dnscache cachedump format ********************* e.g.: host.example.com -> <4>host<7>example<3>com<0> */ char ** convert_hostnames(int hosts, char* host[]) { int i; char *ps, *pd; size_t size, size_all; char ** hostname; if ((hostname = malloc(hosts * sizeof(char*))) == NULL) { printf("malloc failed (line %i)\n", __LINE__); exit(EXIT_FAILURE); } /* get accumulated length of fqdns */ size_all = strlen(host[0]) + 2; for(i = 0; i < hosts; ++i) { /* add one char for start length and one for terminating 0 */ hostname[i] = malloc((strlen(host[i]) + 2) * sizeof(char)); if (hostname[i] == NULL) { printf("malloc failed (line %i)\n", __LINE__); exit(EXIT_FAILURE); } } for(i = 0; i < hosts; ++i) { ps = host[i]; pd = hostname[i]; while(*ps != 0) { size = strcspn(ps, "."); /* stop on . or \000 */ *pd = (char) size; memcpy(pd + 1, ps, size); pd += size + 1; if (*(ps + size) == 0) break; ps += size + 1; } *pd = 0; } return hostname; } /* compare cachedump formatted hostnames ************************/ int hostnames_equal(char * h1, char * h2) { while(*h1 && *h2) if (*(h1++) != *(h2++)) return 0; return 1; } /* main ********************************************************/ int main(int argc, char *argv[]) { /* the path to your dnscache dumpfile */ const char dumpcache[] = "/service/dnscache/root/dump/dumpcache"; /* expiration time (seconds since 1970-1-1) */ const char expiration[8] = "\000\000\000\000\000\000\000\000"; int fd; struct stat st; char *start, *end, *p; char **hostname; int i, count = 0; if (argc<2) { printf("Usage: dumpcache-expire [records...]\n"); exit(EXIT_FAILURE); } dumpandwait(dumpcache); hostname = convert_hostnames(argc-1, argv+1); fd = open(dumpcache, O_RDWR); if (fd == -1) { printf("open %s: %s\n", dumpcache, strerror(errno)); exit(EXIT_FAILURE); } if (fstat(fd, &st) < 0) { printf("fstat %s: %s\n", dumpcache, strerror(errno)); exit(EXIT_FAILURE); } start = mmap(0, st.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (start == MAP_FAILED) { printf("mmap: %s\n", strerror(errno)); exit(EXIT_FAILURE); } end = start + st.st_size; for (p = start; p < end; p += *((int*)p) + *((int*)p+1) + 16) { for (i = 0; i < (argc - 1); ++i) if (hostnames_equal(p + 18, hostname[i])) { memcpy(p + 8, expiration, 8); ++count; } } munmap(start, st.st_size); close(fd); if (count) system("svc -h /service/dnscache"); printf("%i records expired\n", count); exit(count); }