1
2########################################################
3# Please file all bug reports, patches, and feature
4# requests under:
5#      https://sourceforge.net/p/logwatch/_list/tickets
6# Help requests and discusion can be filed under:
7#      https://sourceforge.net/p/logwatch/discussion/
8########################################################
9
10#####################################################
11## Copyright (c) 2008 Kirk Bauer
12## Covered under the included MIT/X-Consortium License:
13##    http://www.opensource.org/licenses/mit-license.php
14## All modifications and contributions by other persons to
15## this script are assumed to have been donated to the
16## Logwatch project and thus assume the above copyright
17## and licensing terms.  If you want to make contributions
18## under your own copyright or a different license this
19## must be explicitly stated in the contribution an the
20## Logwatch project reserves the right to not accept such
21## contributions.  If you have made significant
22## contributions to this script and want to claim
23## copyright please contact logwatch-devel@lists.sourceforge.net.
24#########################################################
25
26use Logwatch ':ip';
27
28
29#$DoLookup = ValueOrDefault($ENV{'named_ip_lookup'}, 0);
30$Debug = ValueOrDefault($ENV{'LOGWATCH_DEBUG'}, 0);
31$Detail = ValueOrDefault($ENV{'LOGWATCH_DETAIL_LEVEL'}, 0);
32
33# Avoid "Use of uninitialized value" warning messages.
34sub ValueOrDefault {
35    my ($value, $default) = @_;
36    return ($value ? $value : $default);
37}
38
39if ( $Debug >= 5 ) {
40    print STDERR "\n\nDEBUG: Inside NAMED Filter \n\n";
41    $DebugCounter = 1;
42}
43
44
45while (defined($ThisLine = <STDIN>)) {
46 if ( $Debug >= 30 ) {
47        print STDERR "DEBUG($DebugCounter): $ThisLine";
48        $DebugCounter++;
49    }
50
51   if (
52      ($ThisLine =~ /RR negative cache entry/) or
53      ($ThisLine =~ /ns_....: .* NS points to CNAME/) or
54      ($ThisLine =~ /accept: connection reset by peer/) or
55      ($ThisLine =~ /Connection reset by peer/) or
56      # typo fixed in 2004 release
57      ($ThisLine =~ /transfer(r)?ed serial/) or
58      ($ThisLine =~ /There may be a name server already running/) or
59      ($ThisLine =~ /exiting/) or
60      ($ThisLine =~ /running/) or
61      ($ThisLine =~ /NSTATS /) or
62      ($ThisLine =~ /Cleaned cache of \d+ RRs/) or
63      ($ThisLine =~ /USAGE \d+ \d+ CPU=\d+.*/) or
64      ($ThisLine =~ /XSTATS /) or
65      ($ThisLine =~ /Ready to answer queries/) or
66      ($ThisLine =~ /Forwarding source address is/) or
67      ($ThisLine =~ /bad referral/) or
68      ($ThisLine =~ /prerequisite not satisfied/) or
69      ($ThisLine =~ /(rcvd|Sent) NOTIFY/) or
70      ($ThisLine =~ /ns_resp: TCP truncated/) or
71      ($ThisLine =~ /No possible A RRs/) or
72      ($ThisLine =~ /points to a CNAME/) or
73      ($ThisLine =~ /dangling CNAME pointer/) or
74      ($ThisLine =~ /listening on/) or
75      ($ThisLine =~ /unrelated additional info/) or
76      ($ThisLine =~ /Response from unexpected source/) or
77      ($ThisLine =~ /No root nameservers for class IN/) or
78      ($ThisLine =~ /recvfrom: No route to host/) or
79      # Be sure to catch: transfer of 'zone' from IP#53: failed to connect: timed out
80      # not exact just triggers a full transfer
81      ($ThisLine =~ /transfer of .*: (IXFR|AXFR(|-style IXFR) (started|ended)|connected using|failed while receiving responses: not exact)/) or
82      ($ThisLine =~ /Transfer status: success/) or
83      ($ThisLine =~ /using \d+ CPU/) or
84      ($ThisLine =~ /loading configuration/) or
85      ($ThisLine =~ /command channel listening/) or
86      ($ThisLine =~ /configuring command channel from/) or
87      ($ThisLine =~ /interface ignored/) or
88      ($ThisLine =~ /no IPv6 interfaces found/) or
89      ($ThisLine =~ /using \d+ UDP listeners per interface/) or
90      ($ThisLine =~ /^running/) or
91      ($ThisLine =~ /^exiting/) or
92      ($ThisLine =~ /no longer listening/) or
93      ($ThisLine =~ /the default for the .* option is now/) or
94      ($ThisLine =~ /stopping command channel on \S+/) or
95      ($ThisLine =~ /Malformed response from/) or
96      ($ThisLine =~ /client .* response from Internet for .*/) or
97#      ($ThisLine =~ /client .+ query \(cache\) '.*' denied/) or
98      ($ThisLine =~ /client .+(?: \([^)]+\))?: query:/) or
99      # Do we really want to ignore these?
100      #($ThisLine =~ /unknown logging category/) or
101      ($ThisLine =~ /could not open entropy source/) or
102      ($ThisLine =~ /\/etc\/rndc.key: file not found/) or
103      ($ThisLine =~ /sending notifies/) or
104      # file syntax error get reported twice and are already caught below
105      ($ThisLine =~ /loading master file/) or
106      ($ThisLine =~ /^ succeeded$/) or
107      ($ThisLine =~ /\*\*\* POKED TIMER \*\*\*/) or
108      # The message about the end of transfer is the interesting one
109      ($ThisLine =~ /: Transfer started./) or
110      ($ThisLine =~ /D-BUS service (disabled|enabled)./) or
111      ($ThisLine =~ /D-BUS dhcdbd subscription disabled./) or
112      ($ThisLine =~ /automatic empty zone/) or
113      ($ThisLine =~ /binding TCP socket: address in use/) or
114      ($ThisLine =~ /dbus_mgr initialization failed. D-BUS service is disabled./) or
115      ($ThisLine =~ /dbus_svc_add_filter failed/) or
116      ($ThisLine =~ /isc_log_open 'named.run' failed: permission denied/) or
117      ($ThisLine =~ /weak RSASHA1 \(5\) key found \(exponent=3\)/) or
118      ($ThisLine =~ /Bad file descriptor/) or
119      ($ThisLine =~ /open: .*: file not found/) or
120      ($ThisLine =~ /queries: client [\.0-9a-fA-F#:]* view localhost_resolver: query: .* IN .*/) or
121      ($ThisLine =~ /zone .*: NS '.*' is a CNAME \(illegal\)/) or
122      ($ThisLine =~ /skipping nameserver '.*' because it is a CNAME,/) or
123      ($ThisLine =~ /zone .*: zone serial unchanged. zone may fail to transfer to slaves/) or
124      ($ThisLine =~ /zone .*: loading from master file .* failed/) or
125      ($ThisLine =~ /zone .*: NS '.*' has no address records/) or
126      ($ThisLine =~ /.*: not a valid number$/) or
127      ($ThisLine =~ /^(.*: )?unexpected end of input/) or
128      ($ThisLine =~ /too many timeouts resolving '.*' .*: disabling EDNS/) or
129      ($ThisLine =~ /too many timeouts resolving '.*' .*: reducing the advertised EDNS UDP packet size to .* octets/) or
130      ($ThisLine =~ /reloading zones succeeded/) or
131      ($ThisLine =~ /generating session key/) or
132      ($ThisLine =~ /success resolving '.*' \(in '.*'?\) after disabling EDNS/) or
133      ($ThisLine =~ /success resolving '.*' \(in '.*'?\) after reducing the advertised EDNS UDP packet size to 512 octets/) or
134      ($ThisLine =~ /the working directory is not writable/) or
135      ($ThisLine =~ /using default UDP\/IPv[46] port range: \[[0-9]*, [0-9]*\]/) or
136      ($ThisLine =~ /adjusted limit on open files from [0-9]* to [0-9]*/) or
137      ($ThisLine =~ /using up to [0-9]* sockets/) or
138      ($ThisLine =~ /built with/) or
139      ($ThisLine =~ /compiled (by|with)/) or
140      ($ThisLine =~ /linked to/) or
141      ($ThisLine =~ /threads support is /) or
142      ($ThisLine =~ /TTL differs in rdataset, adjusting [0-9]* -> [0-9]*/) or
143      ($ThisLine =~ /max open files \([0-9]*\) is smaller than max sockets \([0-9]*\)/) or
144      ($ThisLine =~ /clients-per-query (?:de|in)creased to .*/) or
145      ($ThisLine =~ /^must-be-secure resolving '.*': .*/) or
146      ($ThisLine =~ /^(error \()?no valid (DS|KEY|RRSIG)\)? resolving '.*': .*/) or
147      ($ThisLine =~ /^not insecure resolving '.*': .*/) or
148      ($ThisLine =~ /^validating \@0x[[:xdigit:]]+: .* DS: must be secure failure/) or
149      ($ThisLine =~ /^(error \()?broken trust chain\)? resolving '.*': .*/) or
150      ($ThisLine =~ /journal file [^ ]* does not exist, creating it/) or
151      ($ThisLine =~ /serial number \(\d+\) received from master/) or
152      ($ThisLine =~ /zone .*: notify from .*: serial \d+/) or
153      ($ThisLine =~ /zone is up to date/) or
154      ($ThisLine =~ /refresh in progress, refresh check queued/) or
155      ($ThisLine =~ /refresh: NODATA response from master/) or
156      ($ThisLine =~ /update with no effect/) or
157      ($ThisLine =~ /reading built-in trusted keys from file/) or
158      ($ThisLine =~ /reading built-in trust anchors from file/) or
159      ($ThisLine =~ /using built-in trusted-keys/) or
160      ($ThisLine =~ /set up managed keys zone/) or
161      ($ThisLine =~ /managed-keys-zone.*key now trusted/) or
162      ($ThisLine =~ /dhcpupdate: forwarding update for zone/) or
163      ($ThisLine =~ /forwarded dynamic update: master [^ ]* returned: (NXRRSET|YXDOMAIN)/) or
164      ($ThisLine =~ /using .* as GeoIP directory/) or
165      ($ThisLine =~ /GEO-.* Build/) or
166      ($ThisLine =~ /initializing GeoIP /) or
167      # the following seems okay since it says "success"
168      ($ThisLine =~ /managed-keys-zone.*: No DNSKEY RRSIGs found for '.*': success/) or
169      ($ThisLine =~ /managed-keys-zone.*: Unable to fetch DNSKEY set '.*': timed out/) or
170      ($ThisLine =~ /^sizing zone task pool based on \d+ zones/) or
171      ($ThisLine =~ /^BIND \d+ is maintained by Internet Systems Consortium/) or
172      ($ThisLine =~ /a non-profit 501/) or
173      ($ThisLine =~ /corporation.  Support and training for BIND \d+ are/) or
174      ($ThisLine =~ /available at https:\/\/www.isc.org\/support/) or
175      ($ThisLine =~ /----------------------------------------------------/) or
176      ($ThisLine =~ /next key event: /) or
177      ($ThisLine =~ /reconfiguring zone keys/) or
178      ($ThisLine =~ /using built-in DLV key/) or
179#      ($ThisLine =~ /reading built-in trusted keys from file/) or
180      ($ThisLine =~ /all zones loaded/) or
181      ($ThisLine =~ /resolver priming query complete/) or
182      ($ThisLine =~ /client .* signer .* approved/) or
183      ($ThisLine =~ /stop limiting/) or
184      # ignore this line because the following line describes the error
185      ($ThisLine =~ /unexpected error/)
186   ) {
187      # Don't care about these...
188   } elsif (
189      ($ThisLine =~ /starting\..*named/) or
190      ($ThisLine =~ /starting BIND/) or
191      ($ThisLine =~ /named startup succeeded/)
192   ) {
193      $StartNamed++;
194   } elsif ( $ThisLine =~ /(reloading nameserver|named reload succeeded)/ ) {
195      $ReloadNamed++;
196   } elsif (
197      ($ThisLine =~ /shutting down/) or
198      ($ThisLine =~ /named shutting down/ ) or
199      ($ThisLine =~ /named shutdown succeeded/ )
200   ) {
201      $ShutdownNamed++;
202   } elsif ( $ThisLine =~ /named shutdown failed/ ) {
203      $ShutdownNamedFail++;
204   } elsif ( (($Host, $Zone) = ( $ThisLine =~ /client ([^\#]+)#[^\:]+: (?:view \w+: )?zone transfer '(.+)' denied/ )) or
205             (($Host, $Zone) = ( $ThisLine =~ /client ([^\#]+)#[^\:]+: (?:view \w+: )?bad zone transfer request: '(.+)':/ )) ) {
206      $DeniedZoneTransfers{$Host}{$Zone}++;
207   } elsif ( ($Zone) = ( $ThisLine =~ /zone (.+) zone transfer deferred due to quota/ ) ) {
208      $DeferredZoneTransfers{$Zone}++;
209   } elsif ( ($Zone, $Host) = ( $ThisLine =~ /transfer of '(.+)' from ([^\#]+)#[^\:]+: (failed|(Transfer status|giving up): ((network|host) unreachable|timed out|connection refused))/ ) ) {
210      $FailedZoneTransfers{$Host}{$Zone}++;
211   } elsif ( ($Zone) = ( $ThisLine =~ /cache zone \"(.*)\" loaded/ ) ) {
212      $ZoneLoaded{"cache $Zone"}++;
213   } elsif ( ($Zone) = ( $ThisLine =~ /cache zone \"(.*)\" .* loaded/ ) ) {
214      $ZoneLoaded{"cache $Zone"}++;
215   } elsif ( ($Zone) = ( $ThisLine =~ /automatic empty zone: (.*)/ ) ) {
216      $ZoneLoaded{"automatic empty zone $Zone"}++;
217   } elsif ( ($Zone) = ( $ThisLine =~ /primary zone \"(.+)\" loaded/ ) ) {
218      $ZoneLoaded{$Zone}++;
219   } elsif ( ($Zone) = ( $ThisLine =~ /master zone \"(.+)\" .* loaded/ ) ) {
220      $ZoneLoaded{$Zone}++;
221   } elsif ( ($Zone) = ( $ThisLine =~ /secondary zone \"(.+)\" loaded/ ) ) {
222      $ZoneLoaded{"secondary $Zone"}++;
223   } elsif ( ($Zone) = ( $ThisLine =~ /slave zone \"(.+)\" .* loaded/ ) ) {
224      $ZoneLoaded{"secondary $Zone"}++;
225   } elsif ( ($Zone) = ( $ThisLine =~ /zone (.+): expired/ ) ) {
226      $ZoneExpired{$Zone}++;
227   } elsif ( ($Zone) = ( $ThisLine =~ /zone (.+): loaded serial/ ) ) {
228      $ZoneLoaded{$Zone}++;
229   } elsif ( ($Zone) = ( $ThisLine =~ /(managed-keys-zone.*): loaded serial/ ) ) {
230      $ZoneLoaded{$Zone}++;
231   } elsif ( (undef,$Addr,$Server) = ( $ThisLine =~ /(C|c)onnection refused\)? resolving '(.+)': (.+)/ ) ) {
232      $ConnectionRefused{$Addr}{$Server}++;
233   } elsif ( (undef,$Addr,undef,$Server) = ( $ThisLine =~ /ame server (on|resolving) '(.+)' \(in .+\):\s+(\[.+\]\.\d+)?\s*'?(.+)'?:?/ ) ) {
234      $LameServer{$Addr}{$Server}++;
235   } elsif ( (($Zone) = ( $ThisLine =~ /Zone \"(.+)\" was removed/ )) or
236             (($Zone) = ( $ThisLine =~ /zone (.+): \(.*\) removed/ )) ) {
237      $ZoneRemoved{$Zone}++;
238   } elsif ( ($Zone) = ( $ThisLine =~ /received notify for zone '(.*)'/ ) ) {
239      $ZoneReceivedNotify{$Zone}++;
240   } elsif ( ($Zone) = ( $ThisLine =~ /zone (.+): refused notify from non-master/ ) ) {
241      $ZoneRefusedNotify{$Zone}++;
242#   } elsif ( ($Rhost,$Ldom,$Reason) = ( $ThisLine =~ /client ([\d\.a-fA-F:]+) bad zone transfer request: '(.+)': (.+)$/ ) ) {
243   } elsif ( ($Rhost,$Ldom,$Reason) = ( $ThisLine =~ /client ([\.0-9a-fA-F:]+)#\d+: bad zone transfer request: '(.+)': (.+)/ ) ) {
244      $BadZone{$Reason}{"$Rhost ($Ldom)"}++;
245   } elsif ( ($Host) = ( $ThisLine =~ /([^ ]+) has CNAME and other data \(invalid\)/ ) ) {
246      push @CNAMEAndOther, $Host;
247   } elsif ( ($File,$Line,$Entry,$Error) = ( $ThisLine =~ /dns_master_load: ([^:]+):(\d+): ([^ ]+): (.+)$/ ) ) {
248      $ZoneFileErrors{$File}{"$Entry: $Error"}++;
249   } elsif ( ($File,$Line,$Entry,$Error) = ( $ThisLine =~ /warning: ([^:]+):(\d+): (.+)$/ ) ) {
250      $ZoneFileErrors{$File}{"file does not end with newline: $Error"}++;
251   } elsif ( ($Way,$Host) = ( $ThisLine =~ /([^ ]+): sendto\(\[([^ ]+)\].+\): Network is unreachable/ ) ) {
252      $FullHost = LookupIP ($Host);
253      $NetworkUnreachable{$Way}{$FullHost}++;
254   } elsif ( ($Host,$Way) = ( $ThisLine =~ /client (?:\@0x[0-9a-fA-F]+ )?(.*)#\d+(?: \(.*\))?: (?:view \w+: )?error ([^ ]+) response: network unreachable/ ) ) {
255      $FullHost = LookupIP ($Host);
256      $NetworkUnreachable{$Way}{$FullHost}++;
257   } elsif ( ($Zone,$Message) = ( $ThisLine =~ /client [^\#]+#[^\:]+: (?:view \w+: )?updating zone '([^\:]+)': (.*)$/ ) ) {
258      $ZoneUpdates{$Zone}{$Message}++;
259   } elsif ( ($Zone,$Source) = ( $ThisLine =~ /transfer of '([^\']+)' (from [^\#]+)#[^\:]+: Transfer completed: / ) ) {
260      $ZoneUpdates{$Zone}{$Source}++;
261   } elsif ( ($Host,$Zone) = ( $ThisLine =~ /approved AXFR from \[(.+)\]\..+ for \"(.+)\"/ ) ) {
262      $FullHost = LookupIP ($Host);
263      $AXFR{$Zone}{$FullHost}++;
264   } elsif ( ($Client) = ( $ThisLine =~ /warning: client (.*) no more TCP clients/ ) ) {
265      $FullClient = LookupIP ($Client);
266      $DeniedTCPClient{$FullClient}++;
267   } elsif ( ($Client) = ( $ThisLine =~ /client (?:\@0x[0-9a-fA-F]+ )?(.*)#\d+(?: \(.*\))?: (?:view \w+: )?query \(cache\) (?:'.*' )?denied/ ) ) {
268      $FullClient = LookupIP ($Client);
269      $DeniedQuery{$FullClient}++;
270   } elsif ( ($Client) = ( $ThisLine =~ /client (?:\@0x[0-9a-fA-F]+ )?([^#]*)(#\d+)?(?: \(.*\))?: query '.*' denied/ ) ) {
271      $FullClient = LookupIP ($Client);
272      $DeniedQueryNoCache{$FullClient}++;
273   } elsif ( ($Rhost, $ViewName, $Ldom) = ($ThisLine =~ /client (?:\@0x[0-9a-fA-F]+ )?([\.0-9a-fA-F:]+)#\d+: (?:view (\w+): )?update '(.*)' denied/)) {
274      $ViewName = ($ViewName ? "/$ViewName" : "");
275      $UpdateDenied{"$Rhost ($Ldom$ViewName)"}++;
276   } elsif ( ($Rhost, $Ldom) = ($ThisLine =~ /client ([\d\.]+)#\d+: update forwarding '(.*)' denied/)) {
277      $UpdateForwardingDenied{"$Rhost ($Ldom)"}++;
278   } elsif ( ($Zone) = ($ThisLine =~ /zone '([0-9a-zA-Z.-]+)' allows updates by IP address, which is insecure/)) {
279      $InsecUpdate{$Zone}++;
280   } elsif ( ($Zone) = ($ThisLine =~ /zone ([0-9a-zA-Z.\/-]+): journal rollforward failed: journal out of sync with zone/)) {
281      $JournalFail{$Zone}++;
282   } elsif ( ($Zone) = ($ThisLine =~ /(managed-keys-zone.*): journal file is out of date: removing journal file/)) {
283      $JournalFail{$Zone}++;
284   } elsif ( ($Channel,$Reason) = ($ThisLine =~ /couldn't add command channel (.+#\d+): (.*)$/)) {
285      $ChannelAddFail{$Channel}{$Reason}++;
286   } elsif ( ($Zone,$Host,undef,$Reason) = ($ThisLine =~ /zone ([^ ]*): refresh: failure trying master ([^ ]*)#\d+( \(source .*\))?: (.*)/) ) {
287      $MasterFailure{"$Zone from $Host"}{$Reason}++;
288   } elsif ( ($Zone,$Reason,$Host) = ($ThisLine =~ /zone ([^ ]*): refresh: unexpected rcode \((.*)\) from master ([^ ]*)#\d+/) ) {
289      $MasterFailure{"$Zone from $Host"}{$Reason}++;
290   } elsif ( ($Zone) = ($ThisLine =~ /zone ([^\/]+)\/.+: refresh: non-authoritative answer from master/)) {
291      $NonAuthoritative{$Zone}++;
292   } elsif ( ($Zone) = ($ThisLine =~ /zone ([^\/]+)\/.+: refresh: retry limit for master \S+ exceeded/) ) {
293      $RetryLimit{$Zone}++;
294   } elsif ( ($Rcode, $Zone, $Host) = ($ThisLine =~ /(?:error \()?unexpected RCODE\)? \(?(.*?)\)? resolving '(.*)': (.*)$/) ){
295      $UnexpRCODE{$Rcode}{$Zone}{$Host}++;
296   } elsif ( ($Rcode, $Zone, $Host) = ($ThisLine =~ /(.*) unexpected RCODE resolving '(.*)': (.*)$/) ){
297      $UnexpRCODE{$Rcode}{$Zone}{$Host}++;
298   } elsif ( ($ThisLine =~ /(?:error \()?FORMERR\)? resolving '[^ ]+: [.0-9a-fA-F:#]+/) or
299             ($ThisLine =~ /DNS format error from [^ ]+ resolving [^ ]+( for client [^ ]+)?: .*/) ) {
300      chomp($ThisLine);
301      $FormErr{$ThisLine}++;
302   } elsif ( ($ThisLine =~ /found [0-9]* CPU(s)?, using [0-9]* worker thread(s)?/) ) {
303      chomp($ThisLine);
304      $StartLog{$ThisLine}++;
305   } elsif ( (($File,$Line,$Problem) = ($ThisLine =~ /\/etc\/(rndc.key|named.conf):([0-9]+): (unknown option '[^ ]*')/)) or
306	     (($File,$Line,$Problem) = ($ThisLine =~ /\/etc\/(rndc.key|named.conf):([0-9]+): ('[^ ]' expected near end of file)/)) or
307	     (($File,$Line,$Problem) = ($ThisLine =~ /\/etc\/(named.*.conf):([0-9]+): (.*)/)) or
308	     (($File,$Line,$Problem) = ($ThisLine =~ /()()(could not configure root hints from '.*': file not found)/))) {
309       $ConfProb{$File}{"$Line,$Problem"}++;
310   } elsif ( (($ErrorText) = ($ThisLine =~ /^(RUNTIME_CHECK.*)/))or
311	     (($ErrorText) = ($ThisLine =~ /^(.* REQUIRE.* failed.*)$/)) or
312	     (($ErrorText) = ($ThisLine =~ /(.*: fatal error)/)) or
313	     (($ErrorText) = ($ThisLine =~ /(.*: out of memory)/)) ) {
314      $NError{$ErrorText}++;
315   } elsif ( (($ErrorText) = ($ThisLine =~ /^(GeoIP .* DB not available)/)) ) {
316      $GeoIPError{$ErrorText}++;
317   } elsif ( (($ErrorText) = ($ThisLine =~ /^(internal_accept: fcntl\(\) failed: Too many open files)/)) or
318             (($ErrorText) = ($ThisLine =~ /^(socket: too many open file descriptors)/)) ) {
319      $ErrOpenFiles{$ErrorText}++;
320   } elsif ( ($From,$Log) = ($ThisLine =~ /invalid command from ([\.0-9a-fA-F:]*)#[0-9]*: (.*)/) ) {
321      $CCMessages{"$From,$Log"}++;
322   } elsif ( (($Log) = ($ThisLine =~ /(freezing .*zone.*)/)) or
323	     (($Log) = ($ThisLine =~ /(thawing .*zone.*)/)) ) {
324      $CCMessages2{$Log}++;
325   } elsif (($CCC) = ($ThisLine =~ /unknown control channel command '(.*)'/)) {
326      $UnknownCCCommands{$CCC}++;
327   } elsif (($CCC) = ($ThisLine =~ /received control channel command '(.*)'/)) {
328      $CCCommands{$CCC}++;
329   } elsif (($Name,$Address) = ($ThisLine =~ /(?:error \()?network unreachable\)? resolving '(.*)': (.*)/)) {
330      $NUR{$Name}{$Address}++;
331   } elsif (($Name,$Address) = ($ThisLine =~ /(?:error \()?host unreachable\)? resolving '(.*)': (.*)/)) {
332      $HUR{$Name}{$Address}++;
333   } elsif (($Client) = ($ThisLine =~ /client ([\da-fA-F.:]+)(?:#\d*:)? notify question section contains no SOA/)) {
334      $NoSOA{$Client}++;
335   } elsif (($Hint) = ($ThisLine =~ /checkhints: (.*)/) ) {
336      $Hints{$Hint}++;
337   } elsif (($Response,$Net,$Zone) = ($ThisLine =~/limit (.+) responses to (\S+)(?: for (.+) \()?/)) {
338      $Zone = "None" unless defined($Zone);
339      $Limit{$Zone}{$Response}{$Net}++;
340   } elsif (($Client,$Response,$Net,$Zone) = ($ThisLine =~/client ([^#]+)(?:#\d+)? \(.*\): (?:view \w+: )?rate limit drop (.+) response to (\S+)(?: for (\S+))?/)) {
341      $Zone = "None" unless defined($Zone);
342      $LimitDrop{$Zone}{$Response}{$Net}{$Client}++;
343   } elsif (($Client,$Response,$Net,$Zone) = ($ThisLine =~/client ([^#]+)(?:#\d+)? \(.*\): (?:view \w+: )?rate limit slip (.+) response to (\S+)(?: for (\S+))?/)) {
344      $Zone = "None" unless defined($Zone);
345      $LimitSlip{$Zone}{$Response}{$Net}{$Client}++;
346   } elsif (($Net,$Zone,$Response) = ($ThisLine =~/limit responses to (\S+)(?: for (\S+))? (.*) +\(/)) {
347      $Zone = "None" unless defined($Zone);
348      $Limit{$Zone}{$Response}{$Net}++;
349   } elsif (($Client,$Net,$Zone,$Response) = ($ThisLine =~/client ([^#]+)(?:#\d+)? \(.*\): (?:view \w+: )?rate limit drop response to (\S+)(?: for (\S+))? (.*) +\(/)) {
350      $Zone = "None" unless defined($Zone);
351      $LimitDrop{$Zone}{$Response}{$Net}{$Client}++;
352   } elsif (($Client,$Net,$Zone,$Response) = ($ThisLine =~/client ([^#]+)(?:#\d+)? \(.*\): (?:view \w+: )?rate limit slip response to (\S+)(?: for (\S+))? (.*) +\(/)) {
353      $Zone = "None" unless defined($Zone);
354      $LimitSlip{$Zone}{$Response}{$Net}{$Client}++;
355   } elsif (($Zone,$RR) = ($ThisLine =~ /^\s*validating \@0x[[:xdigit:]]+: (.*) (\w+): got insecure response; parent indicates it should be secure/)) {
356      $DNSSECInsec{'__Total__'}++;
357      $DNSSECInsec{$Zone}{$RR}++;
358   } elsif (($Zone,$RR) = ($ThisLine =~ /^\s*validating \@0x[[:xdigit:]]+: (.*) (\w+): no valid signature found/)) {
359      $DNSSECInvalid{'__Total__'}++;
360      $DNSSECInvalid{$Zone}{$RR}++;
361   } elsif (($Zone,$RR) = ($ThisLine =~ /^\s*validating \@0x[[:xdigit:]]+: (.*) (\w+): bad cache hit/)) {
362      $DNSSECBadCache{'__Total__'}++;
363      $DNSSECBadCache{$Zone}{$RR}++;
364   } elsif (($Zone,$RR) = ($ThisLine =~ /^\s*validating \@0x[[:xdigit:]]+: (.*) (\w+): verify failed due to bad signature/)) {
365      $DNSSECInvalid{'__Total__'}++;
366      $DNSSECInvalid{$Zone}{$RR}++;
367   } elsif (($Zone,$RR) = ($ThisLine =~ /^\s*validating ([^\/]*)\/(\w+): got insecure response; parent indicates it should be secure/)) {
368      $DNSSECInsec{'__Total__'}++;
369      $DNSSECInsec{$Zone}{$RR}++;
370   } elsif (($Zone,$RR) = ($ThisLine =~ /^\s*validating ([^\/]*)\/(\w+): no valid signature found/)) {
371      $DNSSECInvalid{'__Total__'}++;
372      $DNSSECInvalid{$Zone}{$RR}++;
373   } elsif (($Zone,$RR) = ($ThisLine =~ /^\s*validating ([^\/]*)\/(\w+): verify failed due to bad signature/)) {
374      $DNSSECInvalid{'__Total__'}++;
375      $DNSSECInvalid{$Zone}{$RR}++;
376   } elsif (($Zone,$RR) = ($ThisLine =~ /^\s*validating ([^\/]*)\/(\w+): bad cache hit/)) {
377      $DNSSECBadCache{'__Total__'}++;
378      $DNSSECBadCache{$Zone}{$RR}++;
379   } elsif (($Error,$Host) = ($ThisLine =~ /^(?:error \()?(.*)\)? resolving '([^']+)':/)) {
380      $DNSSECError{$Error}{'__Total__'}++;
381      $DNSSECError{$Error}{$Host}++;
382   } elsif ($ThisLine =~ /^samba_dlz:/) {
383      if ( ($Rhost, $Error) = ($ThisLine =~ /disallowing update of signer=.* name=(.*) type=.* error=(.*)/ )) {
384            $UpdateDenied{"$Rhost ($Error)"}++;
385      }
386      # ignore rest of samba4 dlz entries for now
387   } else {
388      # Report any unmatched entries...
389      # remove PID from named messages
390      $ThisLine =~ s/(client [\.0-9a-fA-F:]+)\S+/$1/;
391      chomp($ThisLine);
392      $OtherList{$ThisLine}++;
393   }
394}
395
396#######################################
397
398if ( keys %ZoneExpired ) {
399   print "\nZones expired:\n";
400   foreach $ThisOne (sort {$a cmp $b} keys %ZoneExpired) {
401      print "   $ThisOne: $ZoneExpired{$ThisOne} Time(s)\n";
402   }
403}
404
405if ( keys %FailedZoneTransfers ) {
406   print "\nFailed Zone Transfers:\n";
407   foreach my $Host (keys %FailedZoneTransfers) {
408      print "   $Host:\n";
409      foreach my $Zone (keys %{$FailedZoneTransfers{$Host}}) {
410         print "      $Zone: $FailedZoneTransfers{$Host}{$Zone} Time(s)\n";
411      }
412   }
413}
414
415if ( keys %DeniedZoneTransfers ) {
416   print "\nDenied Zone Transfers:\n";
417   foreach my $Host (keys %DeniedZoneTransfers) {
418      print "   $Host:\n";
419      foreach my $Zone (keys %{$DeniedZoneTransfers{$Host}}) {
420         print "      $Zone: $DeniedZoneTransfers{$Host}{$Zone} Time(s)\n";
421      }
422   }
423}
424
425if ( keys %UpdateDenied ) {
426   print "\nZone update refused:\n";
427   foreach $ThisOne (sort {$a cmp $b} keys %UpdateDenied) {
428      print "   $ThisOne: $UpdateDenied{$ThisOne} Time(s)\n";
429   }
430}
431
432if ( keys %UpdateForwardingDenied ) {
433   print "\nZone update forwarding refused:\n";
434   foreach $ThisOne (sort {$a cmp $b} keys %UpdateForwardingDenied) {
435      print "   $ThisOne: $UpdateForwardingDenied{$ThisOne} Time(s)\n";
436   }
437}
438
439if ( keys %InsecUpdate ) {
440   print "\nInsecure zones (dynamic update allowed by IP address):\n";
441   foreach $ThisOne (sort {$a cmp $b} keys %InsecUpdate) {
442      print "   " . $ThisOne . ": " . $InsecUpdate{$ThisOne} . " Time(s)\n";
443   }
444}
445
446if ( keys %JournalFail ) {
447   print "\nJournal update failed:\n";
448   foreach $ThisOne (sort {$a cmp $b} keys %JournalFail) {
449      print "   " . $ThisOne . ": " . $JournalFail{$ThisOne} . " Time(s)\n";
450   }
451}
452
453if (keys %ConfProb) {
454   print "\nErrors in configuration files\n";
455   foreach $File (sort keys %ConfProb) {
456      if ($File =~ /.+/) {
457        print "   file " . $File . "\n";
458        foreach (keys %{$ConfProb{$File}}) {
459           ($Line,$Problem) = split ",";
460           print "      " . $File . ":" . "$Line" . ": " . $Problem . ": " . $ConfProb{$File}{"$Line,$Problem"} . " Time(s)\n";
461        }
462      }
463      else {
464        foreach (keys %{$ConfProb{$File}}) {
465           ($Line,$Problem) = split ",";
466            print "   " . $Problem . ": " . $ConfProb{$File}{"$Line,$Problem"} . " Time(s)\n";
467        }
468      }
469   }
470}
471
472if (keys %NError) {
473   print "\nErrors:\n";
474   foreach $ThisOne (keys %NError) {
475      print "   " . $ThisOne . ": " . $NError{$ThisOne} . " Time(s)\n";
476   }
477}
478
479if (keys %ErrOpenFiles) {
480   print "\nThe following seams to be caused by the patches for CVE-2008-1447.";
481   print "\nPlease update your bind.\n";
482   foreach $ThisOne (keys %ErrOpenFiles) {
483      print "   " . $ThisOne . ": " . $ErrOpenFiles{$ThisOne} . " Time(s)\n";
484   }
485}
486
487if (keys %Limit) {
488   print "\nRate Limiting occurred for:\n";
489   foreach $Zone (keys %Limit) {
490      print "   $Zone:\n";
491      foreach $Response (keys %{$Limit{$Zone}}) {
492         print "      $Response:\n";
493         foreach $Net (keys %{$Limit{$Zone}{$Response}}) {
494            print "         $Net: $Limit{$Zone}{$Response}{$Net} Time(s)\n";
495            foreach $Client (keys %{$LimitDrop{$Zone}{$Response}{$Net}}) {
496               print "            Dropped $Client: $LimitDrop{$Zone}{$Response}{$Net}{$Client} Time(s)\n";
497            }
498            foreach $Client (keys %{$LimitSlip{$Zone}{$Response}{$Net}}) {
499               print "            Slipped $Client: $LimitSlip{$Zone}{$Response}{$Net}{$Client} Time(s)\n";
500            }
501         }
502      }
503   }
504}
505
506if ( ( $Detail >= 5 ) and (keys %GeoIPError) ) {
507   print "\nGeoIP Errors:\n";
508   foreach $ThisOne (keys %GeoIPError) {
509      print "   " . $ThisOne . ": " . $GeoIPError{$ThisOne} . " Time(s)\n";
510   }
511}
512
513if ((keys %CCMessages) or (keys %CCMessages2)){
514   print "\nMessages from control channel\n";
515   foreach (keys %CCMessages) {
516      ($From,$Log) = split ",";
517      print "   " . $From . ": " . $Log . ": " . $CCMessages{"$From,$Log"} . " Time(s)\n";
518   }
519   foreach $ThisOne (keys %CCMessages2) {
520      print "   " . $ThisOne . ": " . $CCMessages2{$ThisOne} . " Time(s)\n";
521   }
522}
523
524if ( ( $Detail >= 5 ) and ($StartNamed) ) {
525   print "\nNamed started: $StartNamed Time(s)\n";
526}
527
528if ( ( $Detail >= 5 ) and ($ReloadNamed) ) {
529   print "Named reloaded: $ReloadNamed Time(s)\n";
530}
531
532if ( ( $Detail >= 5 ) and ($ShutdownNamed) ) {
533   print "Named shutdown: $ShutdownNamed Time(s)\n";
534}
535
536if ( ( $Detail >= 5 ) and ($ShutdownNamedFail) ) {
537   print "Named shutdown failed: $ShutdownNamedFail Time(s)\n";
538}
539
540if ( ( $Detail >= 5 ) and (keys %ZoneLoaded) ) {
541   print "\nLoaded Zones:\n";
542   foreach $ThisOne (sort {$a cmp $b} keys %ZoneLoaded) {
543      print "   $ThisOne: $ZoneLoaded{$ThisOne} Time(s)\n";
544   }
545}
546
547if ( ( $Detail >= 5 ) and (keys %ZoneReceivedNotify) ) {
548   print "\nZones receiving notify:\n";
549   foreach $ThisOne (sort {$a cmp $b} keys %ZoneReceivedNotify) {
550      print "   $ThisOne: $ZoneReceivedNotify{$ThisOne} Time(s)\n";
551   }
552}
553
554if ( ( $Detail >= 5 ) and (keys %ZoneRefusedNotify) ) {
555   print "\nZones refused notify:\n";
556   foreach $ThisOne (sort {$a cmp $b} keys %ZoneRefusedNotify) {
557      print "   $ThisOne: $ZoneRefusedNotify{$ThisOne} Time(s)\n";
558   }
559}
560
561if ( ($Detail >= 5) and (keys %ChannelAddFail) ) {
562   print "\nCan't add command channel:\n";
563   foreach $Channel (sort {$a cmp $b} keys %ChannelAddFail) {
564      print "   $Channel:\n";
565      foreach $Reason (sort {$a cmp $b} keys %{$ChannelAddFail{$Channel}}) {
566         print "      $Reason: $ChannelAddFail{$Channel}{$Reason} Time(s)\n";
567      }
568   }
569}
570
571if ( ($Detail >= 5) and (keys %MasterFailure) ) {
572   print "\nFailure trying to refresh zone:\n";
573   foreach $Zone (sort {$a cmp $b} keys %MasterFailure) {
574      print "   $Zone:\n";
575      foreach $Reason (sort {$a cmp $b} keys %{$MasterFailure{$Zone}}) {
576         print "      $Reason: $MasterFailure{$Zone}{$Reason} Time(s)\n";
577      }
578   }
579}
580
581if ( ( $Detail >= 5 ) and (keys %DeferredZoneTransfers) ) {
582   print "\nDeferred Zone Transfers:\n";
583   foreach my $Zone (keys %DeferredZoneTransfers) {
584      print "   $Zone: $DeferredZoneTransfers{$Zone} Time(s)\n";
585   }
586}
587
588if ( ( $Detail >= 5 ) and (keys %ZoneRemoved) ) {
589   print "\nRemoved Zones:\n";
590   foreach $ThisOne (sort {$a cmp $b} keys %ZoneRemoved) {
591      print "   $ThisOne: $ZoneRemoved{$ThisOne} Time(s)\n";
592   }
593}
594
595if ( ( $Detail >= 5 ) and (keys %AXFR) ) {
596   print "\nZone Transfers:\n";
597   foreach $ThisOne (keys %AXFR) {
598      print "   Zone: $ThisOne\n";
599      foreach $Temp (keys %{$AXFR{$ThisOne}}) {
600         print "      by $Temp: $AXFR{$ThisOne}{$Temp} Time(s)\n";
601      }
602   }
603}
604
605if ( ( $Detail >= 10 ) and (keys %BadZone) ) {
606   print "\nBad Zone Transfer Request:\n";
607   foreach $Reason (keys %BadZone) {
608      print "   Reason: $Reason\n";
609      foreach $ThisOne (sort {$a cmp $b} (keys %{$BadZone{$Reason}}) ) {
610         print "      $ThisOne: $BadZone{$Reason}{$ThisOne} Time(s)\n";
611      }
612   }
613}
614
615if ( ( $Detail >= 5 ) and (keys %DeniedTCPClient) ) {
616   print "\nno more TCP clients warning:\n";
617   foreach $ThisOne (keys %DeniedTCPClient) {
618      print "   from $ThisOne: $DeniedTCPClient{$ThisOne} Time(s)\n";
619   }
620}
621
622if ( ( $Detail >= 5 ) and (keys %DeniedQuery) ) {
623   print "\nQueries (cached) that were denied:\n";
624   foreach $ThisOne (keys %DeniedQuery) {
625      print "   from $ThisOne: $DeniedQuery{$ThisOne} Time(s)\n";
626   }
627}
628
629if ( ( $Detail >= 10 ) and (keys %DeniedQueryNoCache) ) {
630   print "\nQueries (not cached) that were denied:\n";
631   foreach $ThisOne (sort {$a cmp $b} keys %DeniedQueryNoCache) {
632      print "   from $ThisOne: $DeniedQueryNoCache{$ThisOne} Time(s)\n";
633   }
634}
635
636if ( ( $Detail >= 10 ) and (@CNAMEAndOther) ) {
637   print "\nThese hosts have CNAME and other data (invalid):\n";
638   foreach $ThisOne (@CNAMEAndOther) {
639      print "   $ThisOne\n";
640   }
641}
642
643if ( ( $Detail >= 5 ) and (keys %ZoneFileErrors) ) {
644   print "\nSyntax errors in zone files:\n";
645   for $File (keys %ZoneFileErrors) {
646      print "   $File\n";
647      for $Error ( keys %{$ZoneFileErrors{$File}} ) {
648         print "      \"$Error\" " . $ZoneFileErrors{$File}{$Error} . " Time(s)\n";
649      }
650   }
651}
652
653if ( ( $Detail >= 10 ) and (keys %ConnectionRefused) ) {
654   print "\nConnection refused resolving:\n";
655   foreach $Addr (sort keys %ConnectionRefused) {
656      print "   $Addr:\n";
657      foreach $Server (sort SortIP keys %{$ConnectionRefused{$Addr}}) {
658         print "      $Server: $ConnectionRefused{$Addr}{$Server} Time(s)\n";
659      }
660   }
661}
662
663if ( ( $Detail >= 10 ) and (keys %LameServer) ) {
664   print "\nThese addresses had lame server references:\n";
665   foreach $Addr (sort keys %LameServer) {
666      print "   $Addr:\n";
667      foreach $Server (sort SortIP keys %{$LameServer{$Addr}}) {
668         print "      $Server: $LameServer{$Addr}{$Server} Time(s)\n";
669      }
670   }
671}
672
673if ( ( $Detail >= 10 ) and (keys %NonAuthoritative) ) {
674   print "\nNon-authoritative answer from master for these zones:\n";
675   foreach $ThisOne (keys %NonAuthoritative) {
676      print "   " . $ThisOne . ": " . $NonAuthoritative{$ThisOne} . " Time(s)\n";
677   }
678}
679
680if ( ($Detail >= 10) and (keys %RetryLimit) ) {
681   print "\nRetry limit exceeded for these zones:\n";
682   foreach $Zone (sort {$a cmp $b} keys %RetryLimit) {
683      print "   $Zone: $RetryLimit{$Zone} Time(s)\n";
684   }
685}
686
687if ( ($Detail >= 10) and (keys %NoSOA) ) {
688   print "\nNotify question sections of these clients contained no SOA:\n";
689   foreach $Client (sort {$a cmp $b} keys %NoSOA) {
690      print "   $Client: $NoSOA{$Client} Time(s)\n";
691   }
692}
693
694if ( ( $Detail >= 10 ) and (keys %NetworkUnreachable) ) {
695   print "\nNetwork is unreachable for:\n";
696   foreach $ThisOne (sort {$a cmp $b} keys %NetworkUnreachable) {
697      print "   $ThisOne:\n";
698      foreach $Host (sort {$a cmp $b} keys %{$NetworkUnreachable{$ThisOne}}) {
699         print "      $Host: $NetworkUnreachable{$ThisOne}{$Host} Time(s)\n";
700      }
701   }
702}
703
704if ( ( $Detail >= 10 ) and (keys %NUR) ) {
705   print "\nNetwork unreachable resolving for:\n";
706   foreach $ThisOne (sort {$a cmp $b} keys %NUR) {
707      print "   $ThisOne:\n";
708      foreach $Host (sort {$a cmp $b} keys %{$NUR{$ThisOne}}) {
709         print "      $Host: $NUR{$ThisOne}{$Host} Time(s)\n";
710      }
711   }
712}
713
714if ( ( $Detail >= 10 ) and (keys %HUR) ) {
715   print "\nHost unreachable resolving for:\n";
716   foreach $ThisOne (sort {$a cmp $b} keys %HUR) {
717       print "   $ThisOne:\n";
718       foreach $Host (sort {$a cmp $b} keys %{$HUR{$ThisOne}}) {
719          print "      $Host: $HUR{$ThisOne}{$Host} Time(s)\n";
720       }
721   }
722}
723
724if ( ( $Detail >= 10 ) and (keys %ZoneUpdates) ) {
725   print "\nZone Updates:\n";
726   foreach $ThisOne (sort {$a cmp $b} keys %ZoneUpdates) {
727      print "   $ThisOne:\n";
728      foreach $Message (sort {$a cmp $b} keys %{$ZoneUpdates{$ThisOne}}) {
729         print "      $Message: $ZoneUpdates{$ThisOne}{$Message} Time(s)\n";
730      }
731   }
732}
733
734if (($Detail >= 5) and (keys %UnexpRCODE)) {
735   print "\nUnexpected DNS RCODEs:\n";
736   foreach $ThisOne (sort {$a cmp $b} keys %UnexpRCODE) {
737      print "   " . $ThisOne . ":\n";
738      foreach $Zone (sort {$a cmp $b} keys %{$UnexpRCODE{$ThisOne}}) {
739         print "     " . $Zone . ":\n";
740         foreach $Host (sort SortIP keys %{$UnexpRCODE{$ThisOne}{$Zone}}) {
741            print "         " . $Host . ": " . $UnexpRCODE{$ThisOne}{$Zone}{$Host} . " Time(s)\n";
742         }
743      }
744   }
745}
746
747if (($Detail >= 5) and (keys %FormErr)) {
748   print "\nIncorrect response format:\n";
749   foreach $ThisOne (keys %FormErr) {
750      print "   " . $ThisOne . ": " . $FormErr{$ThisOne} . " Time(s)\n";
751   }
752}
753
754if (($Detail >= 10) and (keys %StartLog)) {
755   print "\nNamed startup logs:\n";
756   foreach $ThisOne (keys %StartLog) {
757      print "   " . $ThisOne . ": " . $StartLog{$ThisOne} . " Time(s)\n";
758   }
759}
760
761if (($Detail and (keys %CCCommands)) or (keys %UnknownCCCommands)) {
762   print "\nReceived control channel commands\n";
763   foreach $ThisOne (keys %CCCommands) {
764      print "   " . $ThisOne . ": " . $CCCommands{$ThisOne} . " Time(s)\n";
765   }
766   foreach $ThisOne (keys %UnknownCCCommands) {
767      print "   " . $ThisOne . "(unknown command): " . $CCCommands{$ThisOne} . " Time(s)\n";
768   }
769}
770
771if (keys %Hints) {
772   print "\nCheckhints:\n";
773   foreach $ThisOne (sort {$a cmp $b} keys %Hints) {
774      print "   " .$ThisOne .": $Hints{$ThisOne} Time(s)\n";
775   }
776}
777
778if (($Detail >= 5) and (keys %DNSSECInsec)) {
779   print "\nDNSSEC Insecure Responses: " . $DNSSECInsec{'__Total__'} . " Time(s)\n";
780   foreach $Zone (sort keys %DNSSECInsec) {
781      if (($Detail >= 10) and ($Zone =~ /.+/) and ($Zone ne '__Total__')) {
782        foreach $RR (sort keys %{$DNSSECInsec{$Zone}}) {
783           print "   " . "$Zone/$RR: " . $DNSSECInsec{$Zone}{$RR} . " Time(s)\n";
784        }
785      }
786   }
787}
788
789if (($Detail >= 5) and (keys %DNSSECInvalid)) {
790   print "\nDNSSEC No Valid Signature: " . $DNSSECInvalid{'__Total__'} . " Time(s)\n";
791   foreach $Zone (sort keys %DNSSECInvalid) {
792      if (($Detail >= 10) and ($Zone =~ /.+/) and ($Zone ne '__Total__')) {
793        foreach $RR (sort keys %{$DNSSECInvalid{$Zone}}) {
794           print "   " . "$Zone/$RR: " . $DNSSECInvalid{$Zone}{$RR} . " Time(s)\n";
795        }
796      }
797   }
798}
799
800if (($Detail >= 5) and (keys %DNSSECBadCache)) {
801   print "\nDNSSEC Bad Cache hit: " . $DNSSECBadCache{'__Total__'} . " Time(s)\n";
802   foreach $Zone (sort keys %DNSSECBadCache) {
803      if (($Detail >= 10) and ($Zone =~ /.+/) and ($Zone ne '__Total__')) {
804        foreach $RR (sort keys %{$DNSSECBadCache{$Zone}}) {
805           print "   " . "$Zone/$RR: " . $DNSSECBadCache{$Zone}{$RR} . " Time(s)\n";
806        }
807      }
808   }
809}
810
811if (($Detail >= 5) and (keys %DNSSECError)) {
812   print "\nDNSSEC Errors:\n";
813   foreach $Error (sort keys %DNSSECError) {
814      print "   $Error: " . $DNSSECError{$Error}{'__Total__'} . " Time(s)\n";
815      if ($Detail >= 10) {
816         foreach $Host (sort keys %{$DNSSECError{$Error}}) {
817            print "     " . "$Host: " . $DNSSECError{$Error}{$Host} . " Time(s)\n" unless ($Host eq '__Total__');
818         }
819      }
820   }
821}
822
823if (keys %OtherList) {
824   print "\n**Unmatched Entries**\n";
825   foreach $line (sort {$a cmp $b} keys %OtherList) {
826      print "   $line: $OtherList{$line} Time(s)\n";
827   }
828}
829
830exit(0);
831
832# vi: shiftwidth=3 tabstop=3 syntax=perl et
833# Local Variables:
834# mode: perl
835# perl-indent-level: 3
836# indent-tabs-mode: nil
837# End:
838