#!/usr/bin/perl -w # # dumpcache-expire.pl v0.1 # (C) 2003 Jakob Hirsch (dumpcache@plonk.de) # http://plonk.de/sw/djb/dumpcache-expire.pl # # History: # 2003-04-20 created v0.1 # # expire a entry in dnscache's cache (by setting expiry to 0) # needs the dumpcache-patch from http://www.efge.org/djbdns/ # based on prettycache.pl from this site # # # Licenced under the GPL (http://www.fsf.org/licenses/gpl.txt) # # Specify your dumpcache file here $f = "/service/dnscache/root/dump/dumpcache"; # $expires = "\000\000\000\000\000\000\000\000"; ####### # if ($#ARGV < 0) { print STDERR "usage: dumpcache-expire.pl record1 record2 ...\n"; exit 0; } # dump the cache system "svc -a /service/dnscache"; # we sleep for one second so dnscache can dump # if you have a large cache you may have to increase the time # or rewrite this to wait for the "dump" log line sleep 1; open (FILE, "+<$f") or die "$f: $!"; my $count = 0; while (!eof(FILE)) { my $pos = tell FILE; my ($buf, $len); my ($keylen, $datalen); my ($key, $data, $expire); my ($type, $d, $s); # read length of key, data and the expiration time $len = read (FILE, $buf, 16); return 0 unless ($len == 16); ($keylen, $datalen, $expire) = unpack ("VVH16", $buf); return 0 if ($keylen > 10000); # buggy input, don't eat all mem # read key and data $len = read (FILE, $buf, $keylen + $datalen); return 0 unless ($len == $keylen + $datalen); $key = substr ($buf, 0, $keylen); (undef, $d) = unpack ("na*", $key); foreach (@ARGV) { if (name($d) eq $_.".") { #print "\@".$expire."00000000 ".$pos."\n"; $count++; seek FILE, $pos + 8, 0 or die "$f: $!"; print FILE $expires or die "$f: $!"; seek FILE, $pos + 16 + $keylen + $datalen, 0 or die "$f: $!"; } } } close(FILE); # restart dnscache to load the cachedump system "svc -h /service/dnscache"; # return the number of expired entries exit $count; # convert name to readable format sub nextname { my ($q) = @_; my ($buf, $len, $dc); ($len, $q) = unpack ("Ca*", $q); return (".", $q) if ($len == 0); $buf = ""; do { ($dc, $q) = unpack ("a$len"."a*", $q); # quote nonprinting, dot and backslash $dc =~ s/([\000-\040\056\134\200-\377])/sprintf("\\%03o",ord($1))/ge; $dc = lc ($dc); # lowercase $buf .= $dc."."; ($len, $q) = unpack ("Ca*", $q); } while ($len); return ($buf, $q); } sub names { my ($q) = @_; my $name; my @names = (); while ($q ne "") { ($name, $q) = nextname ($q); push (@names, $name); } return @names; } sub name { my ($q) = @_; my $name; ($name, $q) = nextname ($q); return $name; } #