4
# BEGIN COPYRIGHT BLOCK
5
# This Program is free software; you can redistribute it and/or modify it under
6
# the terms of the GNU General Public License as published by the Free Software
7
# Foundation; version 2 of the License.
9
# This Program is distributed in the hope that it will be useful, but WITHOUT
10
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License along with
14
# this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
# Place, Suite 330, Boston, MA 02111-1307 USA.
17
# In addition, as a special exception, Red Hat, Inc. gives You the additional
18
# right to link the code of this Program with code not covered under the GNU
19
# General Public License ("Non-GPL Code") and to distribute linked combinations
20
# including the two, subject to the limitations in this paragraph. Non-GPL Code
21
# permitted under this exception must only link to the code of this Program
22
# through those well defined interfaces identified in the file named EXCEPTION
23
# found in the source code files (the "Approved Interfaces"). The files of
24
# Non-GPL Code may instantiate templates or use macros or inline functions from
25
# the Approved Interfaces without causing the resulting work to be covered by
26
# the GNU General Public License. Only Red Hat, Inc. may make changes or
27
# additions to the list of Approved Interfaces. You must obey the GNU General
28
# Public License in all respects for all of the Program code and other code used
29
# in conjunction with the Program except the Non-GPL Code covered by this
30
# exception. If you modify this file, you may extend this exception to your
31
# version of the file, but you are not obligated to do so. If you do not wish to
32
# provide this exception without modification, you must delete this exception
33
# statement from your version and license this file solely under the GPL without
37
# Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
38
# Copyright (C) 2005 Red Hat, Inc.
39
# All rights reserved.
50
Getopt::Long::Configure ("bundling");
51
Getopt::Long::Configure ("permute");
57
#######################################
59
# parse commandline switches #
61
#######################################
72
$s_stats = new_stats_block( );
73
$m_stats = new_stats_block( );
76
'd|rootDN=s' => \$manager,
77
'v|version' => sub { print "Access Log Analyzer v$logversion\n"; exit (0); },
78
'V|verbose' => sub { $verb = "yes"; },
79
'X|excludeIP=s' => \$exclude[$xi++],
80
's|sizeLimit=s' => \$sizeCount,
81
'S|startTime=s' => \$startTime,
82
'E|endTime=s' => \$endTime,
83
'm|reportFileSecs=s' => sub { my ($opt,$value) = @_; $s_stats = new_stats_block($value); },
84
'M|reportFileMins=s' => sub { my ($opt,$value) = @_; $m_stats = new_stats_block($value); },
85
'h|help' => sub { displayUsage() },
86
# usage options '-efcibaltnxgjuiryp'
87
'e' => sub { $usage = $usage . "e"; },
88
'f' => sub { $usage = $usage . "f"; },
89
'c' => sub { $usage = $usage . "c"; },
90
'i' => sub { $usage = $usage . "i"; },
91
'b' => sub { $usage = $usage . "b"; },
92
'a' => sub { $usage = $usage . "a"; },
93
'l' => sub { $usage = $usage . "l"; },
94
't' => sub { $usage = $usage . "t"; },
95
'n' => sub { $usage = $usage . "n"; },
96
'x' => sub { $usage = $usage . "x"; },
97
'g' => sub { $usage = $usage . "g"; },
98
'j' => sub { $usage = $usage . "j"; },
99
'u' => sub { $usage = $usage . "u"; },
100
'r' => sub { $usage = $usage . "r"; },
101
'y' => sub { $usage = $usage . "y"; },
102
'p' => sub { $usage = $usage . "p"; }
106
# set the default root DN
109
$manager = "cn=directory manager";
115
while($sn <= $#ARGV){
116
$files[$fc] = $ARGV[$sn];
121
if ($sizeCount eq "all"){$sizeCount = "100000";}
123
#######################################
125
# Initialize Arrays and variables #
127
#######################################
129
print "\nAccess Log Analyzer $logversion\n";
130
print "\nCommand : logconv.pl @ARGV\n\n";
162
$sslClientBind = "0";
163
$sslClientFailed = "0";
198
$connectionCount = "0";
201
$maxsimConnection = 0;
205
$limit = "25000"; # number of lines processed to trigger output
207
$err[0] = "Successful Operations\n";
208
$err[1] = "Operations Error(s)\n";
209
$err[2] = "Protocal Errors\n";
210
$err[3] = "Time Limit Exceeded\n";
211
$err[4] = "Size Limit Exceeded\n";
212
$err[5] = "Compare False\n";
213
$err[6] = "Compare True\n";
214
$err[7] = "Strong Authentication Not Supported\n";
215
$err[8] = "Strong Authentication Required\n";
216
$err[9] = "Partial Results\n";
217
$err[10] = "Referral Received\n";
218
$err[11] = "Administrative Limit Exceeded (Look Through Limit)\n";
219
$err[12] = "Unavailable Critical Extension\n";
220
$err[13] = "Confidentiality Required\n";
221
$err[14] = "SASL Bind in Progress\n";
222
$err[16] = "No Such Attribute\n";
223
$err[17] = "Undefined Type\n";
224
$err[18] = "Inappropriate Matching\n";
225
$err[19] = "Constraint Violation\n";
226
$err[20] = "Type or Value Exists\n";
227
$err[21] = "Invalid Syntax\n";
228
$err[32] = "No Such Object\n";
229
$err[33] = "Alias Problem\n";
230
$err[34] = "Invalid DN Syntax\n";
231
$err[35] = "Is Leaf\n";
232
$err[36] = "Alias Deref Problem\n";
233
$err[48] = "Inappropriate Authentication (No password presented, etc)\n";
234
$err[49] = "Invalid Credentials (Bad Password)\n";
235
$err[50] = "Insufficent (write) Privledges\n";
237
$err[52] = "Unavailable\n";
238
$err[53] = "Unwilling To Perform\n";
239
$err[54] = "Loop Detected\n";
240
$err[60] = "Sort Control Missing\n";
241
$err[61] = "Index Range Error\n";
242
$err[64] = "Naming Violation\n";
243
$err[65] = "Objectclass Violation\n";
244
$err[66] = "Not Allowed on Non Leaf\n";
245
$err[67] = "Not Allowed on RDN\n";
246
$err[68] = "Already Exists\n";
247
$err[69] = "No Objectclass Mods\n";
248
$err[70] = "Results Too Large\n";
249
$err[71] = "Effect Multiple DSA's\n";
250
$err[80] = "Other :-)\n";
251
$err[81] = "Server Down\n";
252
$err[82] = "Local Error\n";
253
$err[83] = "Encoding Error\n";
254
$err[84] = "Decoding Error\n";
255
$err[85] = "Timeout\n";
256
$err[86] = "Authentication Unknown\n";
257
$err[87] = "Filter Error\n";
258
$err[88] = "User Canceled\n";
259
$err[89] = "Parameter Error\n";
260
$err[90] = "No Memory\n";
261
$err[91] = "Connect Error\n";
262
$err[92] = "Not Supported\n";
263
$err[93] = "Control Not Found\n";
264
$err[94] = "No Results Returned\n";
265
$err[95] = "More Results To Return\n";
266
$err[96] = "Client Loop\n";
267
$err[97] = "Referral Limit Exceeded\n";
282
$connmsg{"A1"} = "Client Aborted Connections";
283
$connmsg{"B1"} = "Bad Ber Tag Encountered";
284
$connmsg{"B4"} = "Server failed to flush data (response) back to Client";
285
$connmsg{"T1"} = "Idle Timeout Exceeded";
286
$connmsg{"T2"} = "IO Block Timeout Exceeded or NTSSL Timeout";
287
$connmsg{"B2"} = "Ber Too Big";
288
$connmsg{"B3"} = "Ber Peek";
289
$connmsg{"R1"} = "Revents";
290
$connmsg{"P1"} = "Plugin";
291
$connmsg{"P2"} = "Poll";
292
$connmsg{"U1"} = "Cleanly Closed Connections";
310
##########################################
312
# Parse Access Logs #
314
##########################################
316
if ($files[$#files] =~ m/access.rotationinfo/) { $fc--; }
318
print "Processing $fc Access Log(s)...\n\n";
320
print "Filename\t\t\t Total Lines\n";
321
print "--------------------------------------------------\n";
325
if ($fc > 1 && $files[0] =~ /\/access$/){
326
$files[$fc] = $files[0];
328
$skipFirstFile = "1";
331
for ($count=0; $count < $fc; $count++){
332
# we moved access to the end of the list, so if its the first file skip it
333
if($fc > 1 && $count == 0 && $skipFirstFile eq "1"){
337
$logsize = `wc -l $files[$count]`;
338
$logsize =~ /([0-9]+)/;
341
# add a zero for formatting purposes
342
$lc = "0" . $logCount;
346
print sprintf "[%s] %-30s %7s\n",$lc, $files[$count], $1;
348
open(LOG,"$files[$count]") || die "Error: Can't open file $infile: $!";
353
if ($firstline eq "yes"){
359
} elsif (/^\[/ && $firstline eq "no"){
363
$tline = $tline . $_;
370
print_stats_block( $s_stats );
371
print_stats_block( $m_stats );
373
if($ff => $limit){print sprintf " %10s Lines Processed\n\n",--$ff;}
376
print "\n\nTotal Log Lines Analysed: " . ($tlc - 1) . "\n";
378
$allOps = $search + $mod + $add + $delete + $modrdn + $bind + $extendedop;
380
##################################################################
382
# Calculate the total elapsed time of the processed access logs #
384
##################################################################
386
# if we are using startTime & endTime then we need to clean it up for our processing
389
if ($start =~ / *([0-9a-z:\/]+)/i){$start=$1;}
392
if ($end =~ / *([0-9a-z:\/]+)/i){$end =$1;}
396
# Get the start time in seconds
401
if ($logStart =~ / *([0-9A-Z\/]+)/i ){
403
@dateComps = split /\//, $logDate;
405
$timeMonth = 1 +$monthname{$dateComps[1]};
406
$timeMonth = $timeMonth * 3600 *24 * 30;
407
$timeDay= $dateComps[0] * 3600 *24;
408
$timeYear = $dateComps[2] *365 * 3600 * 24;
409
$dateTotal = $timeMonth + $timeDay + $timeYear;
412
if ($logStart =~ / *(:[0-9:]+)/i ){
414
@timeComps = split /:/, $logTime;
416
$timeHour = $timeComps[1] * 3600;
417
$timeMinute = $timeComps[2] *60;
418
$timeSecond = $timeComps[3];
419
$timeTotal = $timeHour + $timeMinute + $timeSecond;
422
$startTotal = $timeTotal + $dateTotal;
425
# Get the end time in seconds
430
if ($logEnd =~ / *([0-9A-Z\/]+)/i ){
432
@dateComps = split /\//, $logDate;
434
$endDay = $dateComps[0] *3600 * 24;
435
$endMonth = 1 + $monthname{$dateComps[1]};
436
$endMonth = $endMonth * 3600 * 24 * 30;
437
$endYear = $endTotal + $dateComps[2] *365 * 3600 * 24 ;
438
$dateTotal = $endDay + $endMonth + $endYear;
441
if ($logEnd =~ / *(:[0-9:]+)/i ){
443
@timeComps = split /:/, $logTime;
445
$endHour = $timeComps[1] * 3600;
446
$endMinute = $timeComps[2] *60;
447
$endSecond = $timeComps[3];
448
$timeTotal = $endHour + $endMinute + $endSecond;
451
$endTotal = $timeTotal + $dateTotal;
456
$totalTimeInSecs = $endTotal - $startTotal;
457
$remainingTimeInSecs = $totalTimeInSecs;
460
# Calculate the elapsed time
464
while(($remainingTimeInSecs - 86400) > 0){
466
$remainingTimeInSecs = $remainingTimeInSecs - 86400;
471
while(($remainingTimeInSecs - 3600) > 0){
473
$remainingTimeInSecs = $remainingTimeInSecs - 3600;
477
while($remainingTimeInSecs - 60 > 0){
479
$remainingTimeInSecs = $remainingTimeInSecs - 60;
483
$elapsedSeconds = $remainingTimeInSecs;
485
#####################################
487
# Display Basic Results #
489
#####################################
492
print "\n\n----------- Access Log Output ------------\n";
493
print "\nStart of Log: $start\n";
494
print "End of Log: $end\n\n";
495
if($elapsedDays eq "0"){
496
print "Processed Log Time: $elapsedHours Hours, $elapsedMinutes Minutes, $elapsedSeconds Seconds\n\n";
498
print "Processed Log Time: $elapsedDays Days, $elapsedHours Hours, $elapsedMinutes Minutes, $elapsedSeconds Seconds\n\n";
500
print "Restarts: $restarts\n";
501
print "Total Connections: $connectionCount\n";
502
print "SSL Connections: $sslconn\n";
503
print "Peak Concurrent Connections: $maxsimConnection\n";
504
print "Total Operations: $allOps\n";
505
print "Total Results: $allResults\n";
507
print sprintf "Overall Performance: %.1f%\n\n" , ($perf = ($tmp = ($allResults / $allOps)*100) > 100 ? 100.0 : $tmp) ;
510
print "Overall Performance: No Operations to evaluate\n\n";
513
$searchStat = sprintf "(%.2f/sec) (%.2f/min)\n",($search / $totalTimeInSecs), $search / ($totalTimeInSecs/60);
514
$modStat = sprintf "(%.2f/sec) (%.2f/min)\n",$mod / $totalTimeInSecs, $mod/($totalTimeInSecs/60);
515
$addStat = sprintf "(%.2f/sec) (%.2f/min)\n",$add/$totalTimeInSecs, $add/($totalTimeInSecs/60);
516
$deleteStat = sprintf "(%.2f/sec) (%.2f/min)\n",$delete/$totalTimeInSecs, $delete/($totalTimeInSecs/60);
517
$modrdnStat = sprintf "(%.2f/sec) (%.2f/min)\n",$modrdn/$totalTimeInSecs, $modrdn/($totalTimeInSecs/60);
518
$compareStat = sprintf "(%.2f/sec) (%.2f/min)\n",$compare/$totalTimeInSecs, $compare/($totalTimeInSecs/60);
519
$bindStat = sprintf "(%.2f/sec) (%.2f/min)\n",$bind/$totalTimeInSecs, $bind/($totalTimeInSecs/60);
522
Searches: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<
524
Modifications: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<
526
Adds: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<
528
Deletes: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<
530
Mod RDNs: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<
532
Compares: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<
533
$compare, $compareStat
534
Binds: @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<
540
print "Proxied Auth Operations: $proxiedAuth\n";
541
print "Persistent Searches: $persistent\n";
542
print "Internal Operations: $internal\n";
543
print "Entry Operations: $entryOp\n";
544
print "Extended Operations: $extendedop\n";
545
print "Abandoned Requests: $abandon\n";
546
print "Smart Referrals Received: $referral\n";
548
print "VLV Operations: $vlv\n";
549
print "VLV Unindexed Searches: $vlvnotes\n";
550
print "SORT Operations: $sortvlv\n";
552
print "Entire Search Base Queries: $objectclass\n";
553
print "Unindexed Searches: $notes\n";
554
if ($verb eq "yes" || $usage =~ /u/){
557
for ($n = 0; $n <= $#notesEtime; $n++){
559
print "\n Unindexed Search #".$ns."\n";
561
print " - Date/Time: $notesTime[$n]\n";
562
print " - Connection Number: $notesConn[$n]\n";
563
print " - Operation Number: $notesOp[$n]\n";
564
print " - Etime: $notesEtime[$n]\n";
565
print " - Nentries: $notesNentries[$n]\n";
566
print " - IP Address: $conn_hash{$notesConn[$n]}\n";
567
for ($nn = 0; $nn <= $bc; $nn++){
568
if ($notesConn[$n] eq $bindInfo[$nn][1]) {
570
## Here, we check if the bindDN is already printed.
571
## If not, we print it and push it to @alreadyseenDN.
572
## So, in the beginning, we iterate thru @alreadyseenDN
574
for ($j=0, $DNisThere=0; $j <=$#alreadyseenDN; $j++) {
575
if ($alreadyseenDN[$j] eq $bindInfo[$nn][0]) {
579
unless ($DNisThere) {
580
print " - Bind DN: $bindInfo[$nn][0]\n";
581
push @alreadyseenDN, $bindInfo[$nn][0];
585
for ($nnn = 0; $nnn <= $bcc; $nnn++){
586
if ($notesConn[$n] eq $baseInfo[$nnn][1] && $notesOp[$n] eq $baseInfo[$nnn][2]){
587
print " - Search Base: $baseInfo[$nnn][0]\n";
590
for ($nnn = 0; $nnn <= $scc; $nnn++){
591
if ($notesConn[$n] eq $scopeInfo[$nnn][1] && $notesOp[$n] eq $scopeInfo[$nnn][2]){
592
print " - Search Scope: $scopeInfo[$nnn][0]\n";
595
for ($nnn = 0; $nnn <= $fcc; $nnn++){
596
if ($notesConn[$n] eq $filterInfo[$nnn][1] && $notesOp[$n] eq $filterInfo[$nnn][2]){
597
print " - Search Filter: $filterInfo[$nnn][0]\n";
606
print "FDs Taken: $fdtake\n";
607
print "FDs Returned: $fdreturn\n";
608
print "Highest FD Taken: $highfd\n\n";
609
print "Broken Pipes: $broken\n";
611
foreach $key (sort { $rc{$b} <=> $rc{$a} } keys %rc) {
613
if ($conn{$key} eq ""){$conn{$key} = "** Unknown **";}
614
push @etext, sprintf " - %-4s (%2s) %-40s\n",$rc{$key},$conn{$key},$connmsg{$key
622
print "Connections Reset By Peer: $reset\n";
624
foreach $key (sort { $src{$b} <=> $src{$a} } keys %src) {
626
if ($conn{$key} eq ""){$conn{$key} = "** Unknown **";}
627
push @retext, sprintf " - %-4s (%2s) %-40s\n",$src{$key},$conn{$key},$connmsg{$key
635
print "Resource Unavailable: $resource\n";
637
foreach $key (sort { $rsrc{$b} <=> $rsrc{$a} } keys %rsrc) {
638
if ($rsrc{$key} > 0){
639
if ($conn{$key} eq ""){$conn{$key} = "** Resource Issue **";}
640
push @rtext, sprintf " - %-4s (%2s) %-40s\n",$rsrc{$key},$conn{$key},$connmsg{$key};
646
print "Binds: $bind\n";
647
print "Unbinds: $unbind\n";
648
print "\n LDAP v2 Binds: $version2\n";
649
print " LDAP v3 Binds: $version3\n";
650
print " SSL Client Binds: $sslClientBind\n";
651
print " Failed SSL Client Binds: $sslClientFailed\n";
652
print " SASL Binds: $sasl\n";
654
foreach $saslb ( sort {$saslmech{$b} <=> $saslmech{$a} } (keys %saslmech) ){
655
printf " %-4s %-12s\n",$saslmech{$saslb}, $saslb;
659
print "\n Directory Manager Binds: $dirmgr\n";
660
print " Anonymous Binds: $anony\n";
661
$other = $bind -($dirmgr + $anony);
662
print " Other Binds: $other";
664
if ($verb eq "yes" || $usage =~ /y/){
665
print "\n\n----- Connection Latency Details -----\n\n";
666
print " (in seconds)\t\t<=1\t2\t3\t4-5\t6-10\t11-15\t>15\n";
667
print " --------------------------------------------------------------------------\n";
668
print " (# of connections)\t";
669
for ($i=0; $i <=$#latency; $i++) {
670
print "$latency[$i]\t";
674
if ($verb eq "yes" || $usage =~ /p/){
675
print "\n\n----- Current Open Connection IDs ----- \n\n";
676
for ($i=0; $i <= $#openConnection ; $i++) {
677
if ($openConnection[$i]) {
683
###################################
685
# Display Error Codes #
687
###################################
689
if ($usage =~ /e/i || $verb eq "yes"){
690
print "\n\n----- Errors -----\n";
692
%er = sort( {$b <=> $a} %er);
693
for ($i = 0; $i<98; $i++){
694
if ($err[$i] ne "" && $er[$i] >0) {
695
push @errtext, sprintf "%-8s %12s %-25s","err=$i",$er[$i],$err[$i];
699
for ($i = 0; $i < $#errtext; $i++){
701
for ($ii = 0; $ii < $#errtext; $ii++){
704
while ($errtext[$ii] =~ /(\w+)\s/g){
708
while ($errtext[$ii+1] =~ /(\w+)\s/g){
709
$errornum2[$zz]="$1";
713
if ($errornum2[1] > $errornum[1]){
714
$tmp = $errtext[$ii];
715
$errtext[$ii] = $errtext[$ii+1];
716
$errtext[$ii+1] = $tmp;
721
for ($i = 0; $i <= $#errtext; $i++){
722
$errtext[$i] =~ s/\n//g;
723
print "\n" . $errtext[$i];
728
####################################
730
# Print Failed Logins #
732
####################################
734
if ($verb eq "yes" || $usage =~ /f/i ){
736
print "\n\n----- Top $sizeCount Failed Logins ------\n\n";
738
if ($ds6x eq "true"){
740
foreach $dsbp (sort { $ds6xbadpwd{$b} <=> $ds6xbadpwd{$a} } keys %ds6xbadpwd) {
741
if ($eloop > $sizeCount){ last; }
742
printf "%-4s %-40s\n", $ds6xbadpwd{$dsbp}, $dsbp;
746
for ($ii =0 ; $ii < $bpc; $ii++){
747
for ($i = 0; $i < $bc; $i++){
748
if ($badPasswordConn[$ii] eq $bindInfo[$i][1] && $badPasswordOp[$ii] eq $bindInfo[$i][2] ){
749
$badPassword{ "$bindInfo[$i][0]" } = $badPassword{ "$bindInfo[$i][0]" } + 1;
754
# sort the new list of $badPassword{}
758
foreach $badpw (sort {$badPassword{$b} <=> $badPassword{$a} } keys %badPassword){
759
if ($bpCount > $sizeCount){ last;}
761
$bpTotal = $bpTotal + $badPassword{"$badpw"};
762
printf "%-4s %-40s\n", $badPassword{"$badpw"}, $badpw;
765
print "\nFrom the IP address(s) :\n\n";
766
for ($i=0; $i<$bpi; $i++) {
767
print "\t\t$badPasswordIp[$i]\n";
770
if ($bpTotal > $bpc){
771
print "\n** Warning : Wrongly reported failed login attempts : ". ($bpTotal - $bpc) . "\n";
773
} # this ends the if $ds6x = true
780
####################################
782
# Print Connection Codes #
784
####################################
788
if ($usage =~ /c/i || $verb eq "yes"){
789
print "\n\n----- Total Connection Codes -----\n\n";
791
foreach $key (sort { $conncount{$b} <=> $conncount{$a} } keys %conncount) {
792
if ($conncount{$key} > 0){
793
push @conntext, sprintf "%-4s %6s %-40s\n",$conn{ $key },$conncount{$key},$connmsg{ $key };
801
########################################
803
# Gather and Process all unique IPs #
805
########################################
807
if ($usage =~ /i/i || $verb eq "yes"){
808
@ipkeys = keys %ip_hash;
809
@exxCount = keys %exCount;
810
$ip_count = ($#ipkeys + 1)-($#exxCount + 1);
812
print "\n\n----- Top $sizeCount Clients -----\n\n";
813
print "Number of Clients: $ip_count\n\n";
815
foreach $key (sort { $ip_hash{$b}{"count"} <=> $ip_hash{$a}{"count"} } keys %ip_hash) {
817
if ($ccount > $sizeCount){ last;}
819
for ($xxx =0; $xxx <= $#exclude; $xxx++){
820
if ($exclude[$xxx] eq $key){$exc = "yes";}
823
if ($ip_hash{ $key }{"count"} eq ""){$ip_hash{ $key }{"count"} = "*";}
824
printf "%-6s %-17s\n", $ip_hash{ $key }{"count"}, $key;
828
foreach $code (sort { $ip_hash{ $key }{$b} <=> $ip_hash{ $key }{$a} } keys %{$ip_hash{ $key }}) {
829
if ($code eq 'count' ) { next; }
830
printf "\t\t %6s - %3s %s\n", $ip_hash{ $key }{ $code }, $code, $connmsg{ $code };
834
if ($exc ne "yes"){ print "\n";}
841
###################################
843
# Gather All unique Bind DN's #
845
###################################
847
if ($usage =~ /b/i || $verb eq "yes"){
848
@bindkeys = keys %bindlist;
849
$bind_count = $#bindkeys + 1;
850
if ($bind_count > 0){
851
print "\n----- Top $sizeCount Bind DN's -----\n\n";
852
print "Number of Unique Bind DN's: $bind_count\n\n";
856
foreach $dn (sort { $bindlist{$b} <=> $bindlist{$a} } keys %bindlist) {
857
if ($bindcount < $sizeCount){
858
printf "%-8s %-40s\n", $bindlist{ $dn },$dn;
867
#########################################
869
# Gather and process search bases #
871
#########################################
873
if ($usage =~ /a/i || $verb eq "yes"){
874
@basekeys = keys %base;
875
$base_count = $#basekeys + 1;
876
if ($base_count > 0){
877
print "\n\n----- Top $sizeCount Search Bases -----\n\n";
878
print "Number of Unique Search Bases: $base_count\n\n";
882
foreach $bas (sort { $base{$b} <=> $base{$a} } keys %base) {
883
if ($basecount < $sizeCount){
884
printf "%-8s %-40s\n", $base{ $bas },$bas;
892
#########################################
894
# Gather and process search filters #
896
#########################################
898
if ($usage =~ /l/ || $verb eq "yes"){
900
@filterkeys = keys %filter;
901
$filter_count = $#filterkeys + 1;
902
if ($filter_count > 0){
903
print "\n\n----- Top $sizeCount Search Filters -----\n";
904
print "\nNumber of Unique Search Filters: $filter_count\n\n";
908
foreach $filt (sort { $filter{$b} <=> $filter{$a} } keys %filter){
909
if ($filtercount < $sizeCount){
910
printf "%-8s %-40s\n", $filter{$filt}, $filt;
918
#########################################
920
# Gather and Process the unique etimes #
922
#########################################
926
# print most often etimes
929
if ($usage =~ /t/i || $verb eq "yes"){
930
print "\n\n----- Top $sizeCount Most Frequent etimes -----\n\n";
932
foreach $et (sort { $etime{$b} <=> $etime{$a} } keys %etime) {
933
if ($eloop == $sizeCount) { last; }
938
printf "%-8s %-12s\n", $etime{ $et }, "etime=$et";
943
# print longest etimes
946
print "\n\n----- Top $sizeCount Longest etimes -----\n\n";
948
foreach $et (sort { $b <=> $a } (keys %etime)) {
949
if ($eloop == $sizeCount) { last; }
950
printf "%-12s %-10s\n","etime=$et",$etime{ $et };
956
#######################################
958
# Gather and Process unique nentries #
960
#######################################
963
if ($usage =~ /n/i || $verb eq "yes"){
964
print "\n\n----- Top $sizeCount Largest nentries -----\n\n";
966
foreach $nentry (sort { $b <=> $a } (keys %nentries)){
967
if ($eloop == $sizeCount) { last; }
968
printf "%-18s %12s\n","nentries=$nentry", $nentries{ $nentry };
972
print "\n\n----- Top $sizeCount Most returned nentries -----\n\n";
974
foreach $nentry (sort { $nentries{$b} <=> $nentries{$a} } (keys %nentries)){
975
if ($eloop == $sizeCount) { last; }
976
printf "%-12s %-14s\n", $nentries{ $nentry }, "nentries=$nentry";
984
##########################################
986
# Gather and process extended operations #
988
##########################################
990
if ($usage =~ /x/i || $verb eq "yes"){
992
if ($extendedop > 0){
993
print "\n\n----- Extended Operations -----\n\n";
994
foreach $oids (sort { $oid{$b} <=> $oid{$a} } (keys %oid) ){
996
if ($oids eq "2.16.840.1.113730.3.5.1"){ $oidmessage = "Transaction Request"}
997
elsif ($oids eq "2.16.840.1.113730.3.5.2"){ $oidmessage = "Transaction Response"}
998
elsif ($oids eq "2.16.840.1.113730.3.5.3"){ $oidmessage = "Start Replication Request (incremental update)"}
999
elsif ($oids eq "2.16.840.1.113730.3.5.4"){ $oidmessage = "Replication Response"}
1000
elsif ($oids eq "2.16.840.1.113730.3.5.5"){ $oidmessage = "End Replication Request (incremental update)"}
1001
elsif ($oids eq "2.16.840.1.113730.3.5.6"){ $oidmessage = "Replication Entry Request"}
1002
elsif ($oids eq "2.16.840.1.113730.3.5.7"){ $oidmessage = "Start Bulk Import"}
1003
elsif ($oids eq "2.16.840.1.113730.3.5.8"){ $oidmessage = "Finished Bulk Import"}
1004
elsif ($oids eq "2.16.840.1.113730.3.6.1"){ $oidmessage = "Incremental Update Replication Protocol"}
1005
elsif ($oids eq "2.16.840.1.113730.3.6.2"){ $oidmessage = "Total Update Replication Protocol (Initialization)"}
1006
elsif ($oids eq "2.16.840.1.113730.3.5.9"){ $oidmessage = "Digest Authentication"}
1007
else {$oidmessage = "Other"}
1009
printf "%-6s %-23s %-60s\n", $oid{ $oids }, $oids, $oidmessage;
1015
############################################
1017
# Print most commonly requested attributes
1019
############################################
1021
if ($usage =~ /r/i || $verb eq "yes"){
1023
print "\n\n----- Top $sizeCount Most Requested Attributes -----\n\n";
1025
foreach $mostAttr (sort { $attr{$b} <=> $attr{$a} } (keys %attr) ){
1026
if ($eloop eq $sizeCount){ last; }
1027
printf "%-10s %-19s\n", $attr{$mostAttr}, $mostAttr;
1034
#################################
1036
# abandoned operation stats
1038
#################################
1040
if ($usage =~ /g/i || $verb eq "yes"){
1041
$acTotal = $sconn + $dconn + $mconn + $aconn + $mdconn + $bconn + $ubconn + $econn + $mddconn + $cconn;
1042
if ($verb eq "yes" && $ac > 0 && $acTotal > 0){
1044
print "\n\n----- Abandon Request Stats -----\n\n";
1046
for ($g = 0; $g < $ac; $g++){
1047
for ($sc = 0; $sc < $sconn; $sc++){
1048
if ($srchConn[$sc] eq $targetConn[$g] && $srchOp[$sc] eq $targetOp[$g] ){
1049
print " - SRCH conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n";
1052
for ($dc = 0; $dc < $dconn; $dc++){
1053
if ($delConn[$dc] eq $targetConn[$g] && $delOp[$dc] eq $targetOp[$g]){
1054
print " - DEL conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n";
1057
for ($adc = 0; $adc < $aconn; $adc++){
1058
if ($addConn[$adc] eq $targetConn[$g] && $addOp[$adc] eq $targetOp[$g]){
1059
print " - ADD conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n";
1062
for ($mc = 0; $mc < $mconn; $mc++){
1063
if ($modConn[$mc] eq $targetConn[$g] && $modOp[$mc] eq $targetOp[$g]){
1064
print " - MOD conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n";
1067
for ($mddc = 0; $mddc < $mddconn; $mddc++){
1068
if ($moddnConn[$mdc] eq $targetConn[$g] && $moddnOp[$mdc] eq $targetOp[$g]){
1069
print " - MODDN conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n";
1072
for ($cc = 0; $cc < $cconn; $cc++){
1073
if ($compConn[$mdc] eq $targetConn[$g] && $compOp[$mdc] eq $targetOp[$g]){
1074
print " - CMP conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n";
1077
for ($mdc = 0; $mdc < $mdconn; $mdc++){
1078
if ($modrdnConn[$mdc] eq $targetConn[$g] && $modrdnOp[$mdc] eq $targetOp[$g]){
1079
print " - MODRDN conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n";
1082
for ($bcb = 0; $bcb < $bconn; $bcb++){
1083
if ($bindConn[$bcb] eq $targetConn[$g] && $bindOp[$bcb] eq $targetOp[$g]){
1084
print " - BIND conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n";
1087
for ($ubc = 0; $ubc < $ubconn; $ubc++){
1088
if ($unbindConn[$ubc] eq $targetConn[$g] && $unbindOp[$ubc] eq $targetOp[$g]){
1089
print " - UNBIND conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n";
1092
for ($ec = 0; $ec < $econn; $ec++){
1093
if ($extConn[$ec] eq $targetConn[$g] && $extOp[$ec] eq $targetOp[$g]){
1094
print " - EXT conn=$targetConn[$g] op=$targetOp[$g] msgid=$msgid[$g] client=$conn_hash{$targetConn[$g]}\n";
1108
#######################################
1112
#######################################
1114
if ($usage =~ /j/i || $verb eq "yes"){
1115
print "\n----- Recommendations -----\n";
1118
print "\n $recCount. You have unindexed searches, this can be caused from a search on an unindexed attribute, or your returned results exceeded the allidsthreshold. Unindexed searches are not recommended. To refuse unindexed searches, switch \'nsslapd-require-index\' to \'on\' under your database entry (e.g. cn=UserRoot,cn=ldbm database,cn=plugins,cn=config).\n";
1122
if ($conncount{"T1"} > 0){
1123
print "\n $recCount. You have some connections that are are being closed by the idletimeout setting. You may want to increase the idletimeout if it is set low.\n";
1127
if ($conncount{"T2"} > 0){
1128
print "\n $recCount. You have some coonections that are being closed by the ioblocktimeout setting. You may want to increase the ioblocktimeout.\n";
1132
# compare binds to unbinds, if the difference is more than 30% of the binds, then report a issue
1134
if (($bind - $unbind) > ($bind*.3)){
1135
print "\n $recCount. You have a significant difference between binds and unbinds. You may want to investigate this difference.\n";
1139
# compare fds taken and return, if the difference is more than 30% report a issue
1141
if (($fdtaken -$fdreturn) > ($fdtaken*.3)){
1142
print "\n $recCount. You have a significant difference between file descriptors taken and file descriptors returned. You may want to investigate this difference.\n";
1146
if ($dirmgr > ($bind *.2)){
1147
print "\n $recCount. You have a high number of Directory Manager binds. The Directory Manager account should only be used under certain circumstances. Avoid using this account for client applications.\n";
1151
if ($errorck > $errorsucc){
1152
print "\n $recCount. You have more unsuccessful operations than successful operations. You should investigate this difference.\n";
1156
if ($conncount{"U1"} < ($concount - $conncount{"U1"})){
1157
print "\n $recCount. You have more abnormal connection codes than cleanly closed connections. You may want to investigate this difference.\n";
1162
print "\n $recCount. You have a majority of etimes that are greater than zero, you may want to investigate this performance problem.\n";
1166
if ($objectclass > ($search *.25)){
1167
print "\n $recCount. You have a high number of searches that query the entire search base. Although this is not necessarily bad, it could be resource intensive if the search base contains many entries.\n";
1171
if ($recCount == 1){
1184
print " ./logconv.pl [-h] [-d|--rootdn <rootDN>] [-s|--sizeLimit <size limit>] [-v|verison] [-Vi|verbose]\n";
1185
print " [-S|--startTime <start time>] [-E|--endTime <end time>] \n";
1186
print " [-efcibaltnxrgjuyp] [ access log ... ... ]\n\n";
1188
print "- Commandline Switches:\n\n";
1190
print " -h, --help help/usage\n";
1191
print " -d, --rootDN <Directory Managers DN> DEFAULT -> cn=directory manager\n";
1192
print " -s, --sizeLimit <Number of results to return per catagory> DEFAULT -> 20\n";
1193
print " -X, --excludeIP <IP address to exclude from connection stats> E.g. Load balancers\n";
1194
print " -v, --version show version of tool\n";
1195
print " -S, --startTime <time to begin analyzing logfile from>\n";
1196
print " E.g. \"[28/Mar/2002:13:14:22 -0800]\"\n";
1197
print " -E, --endTime <time to stop analyzing logfile>\n";
1198
print " E.g. \"[28/Mar/2002:13:24:62 -0800]\"\n";
1199
print " -m, --reportFileSecs <CSV output file - per second stats>\n";
1200
print " -M, --reportFileMins <CSV output file - per minute stats>\n";
1201
print " -V, --verbose <enable verbose output - includes all stats listed below>\n";
1202
print " -[efcibaltnxrgjuyp]\n\n";
1204
print " e Error Code stats\n";
1205
print " f Failed Login Stats\n";
1206
print " c Connection Code Stats\n";
1207
print " i Client Stats\n";
1208
print " b Bind Stats\n";
1209
print " a Search Base Stats\n";
1210
print " l Search Filter Stats\n";
1211
print " t Etime Stats\n";
1212
print " n Nentries Stats\n";
1213
print " x Extended Operations\n";
1214
print " r Most Requested Attribute Stats\n";
1215
print " g Abandoned Operation Stats\n";
1216
print " j Recommendations\n";
1217
print " u Unindexed Search Stats\n";
1218
print " y Connection Latency Stats\n";
1219
print " p Open Connection ID Stats\n\n";
1221
print " Examples:\n\n";
1223
print " ./logconv.pl -s 10 -V /logs/access*\n\n";
1225
print " ./logconv.pl --rootDN cn=dm /logs/access*\n\n";
1227
print " ./logconv.pl --sizeLimit 50 -ibgju /logs/access*\n\n";
1229
print " ./logconv.pl -S \"\[28/Mar/2002:13:14:22 -0800\]\" --endTime \"\[28/Mar/2002:13:50:05 -0800\]\" -e /logs/access*\n\n";
1230
print " ./logconv.pl -m log-minute-stats-csv.out /logs/access*\n\n";
1235
######################################################
1237
# Parsing Routine That Does The Actual Parsing Work
1239
######################################################
1244
# lines starting blank are restart
1245
return if $_ =~ /^\s/;
1247
if($firstFile eq "1" && $_ =~ /^\[/){
1248
# if we are using startTime & endTime, this will get overwritten, which is ok
1250
if ($start =~ / *([0-9a-z:\/]+)/i){$start=$1;}
1254
if ($endFlag != 1 && $_ =~ /^\[/ && $_ =~ / *([0-9a-z:\/]+)/i){$end =$1;}
1256
if ($startTime && !$startFlag) {
1257
if (index($_, $startTime) == 0) {
1259
($start) = $startTime =~ /\D*(\S*)/;
1265
if ($endTime && !$endFlag) {
1266
if (index($_, $endTime) == 0) {
1268
($end) = $endTime =~ /\D*(\S*)/;
1274
if ($iff >= $limit){ print STDERR sprintf" %10s Lines Processed\n",$ff; $iff="0";}
1276
# Additional performance stats
1277
($time, $tzone) = split (' ', $_);
1278
if ($time ne $last_tm)
1285
if($tzone ne $lastzone)
1289
($sign,$hr,$min) = $tzone =~ m/(?)(\d\d)(\d\d)/;
1290
$tzoff = $hr*3600 + $min*60;
1293
# to be subtracted from converted values.
1296
($date, $hr, $min, $sec) = split (':', $time);
1297
($day, $mon, $yr) = split ('/', $date);
1298
$newmin = timegm(0, $min, $hours, $day, $monthname{$mon}, $yr) - $tzoff;
1299
$gmtime = $newmin + $sec;
1300
print_stats_block( $s_stats );
1301
reset_stats_block( $s_stats, $gmtime, $time.' '.$tzone );
1302
if ($newmin != $last_min)
1304
print_stats_block( $m_stats );
1305
$time =~ s/\d\d$/00/;
1306
reset_stats_block( $m_stats, $newmin, $time.' '.$tzone );
1307
$last_min = $newmin;
1311
if (m/ RESULT err/){$allResults++;inc_stats('results',$s_stats,$m_stats);}
1314
inc_stats('srch',$s_stats,$m_stats);
1315
if ($_ =~ / attrs=\"(.*)\"/i){
1318
while ($attrs =~ /(\S+)\s/g){
1323
$attr{"All Attributes"}++;
1327
if ($verb eq "yes"){
1328
if ($_ =~ /conn= *([0-9]+)/i){ $srchConn[$sconn] = $1;}
1329
if ($_ =~ /op= *([0-9]+)/i){ $srchOp[$sconn] = $1;}
1335
inc_stats('del',$s_stats,$m_stats);
1336
if ($verb eq "yes"){
1337
if ($_ =~ /conn= *([0-9]+)/i){ $delConn[$dconn] = $1;}
1338
if ($_ =~ /op= *([0-9]+)/i){ $delOp[$dconn] = $1;}
1344
inc_stats('mod',$s_stats,$m_stats);
1345
if ($verb eq "yes"){
1346
if ($_ =~ /conn= *([0-9]+)/i){ $modConn[$mconn] = $1;}
1347
if ($_ =~ /op= *([0-9]+)/i){ $modOp[$mconn] = $1; }
1353
inc_stats('moddn',$s_stats,$m_stats);
1354
if ($verb eq "yes"){
1355
if ($_ =~ /conn= *([0-9]+)/i){ $moddnConn[$mconn] = $1;}
1356
if ($_ =~ /op= *([0-9]+)/i){ $moddnOp[$mconn] = $1; }
1362
inc_stats('add',$s_stats,$m_stats);
1363
if ($verb eq "yes"){
1364
if ($_ =~ /conn= *([0-9]+)/i){ $addConn[$aconn] = $1; }
1365
if ($_ =~ /op= *([0-9]+)/i){ $addOp[$aconn] = $1; }
1371
inc_stats('modrdn',$s_stats,$m_stats);
1372
if ($verb eq "yes"){
1373
if ($_ =~ /conn= *([0-9]+)/i){ $modrdnConn[$mdconn] = $1; }
1374
if ($_ =~ /op= *([0-9]+)/i){ $modrdnOp[$mdconn] = $1; }
1380
inc_stats('cmp',$s_stats,$m_stats);
1381
if ($verb eq "yes" || $usage =~ /g/i){
1382
if ($_ =~ /conn= *([0-9]+)/i){ $compConn[$dconn] = $1;}
1383
if ($_ =~ /op= *([0-9]+)/i){ $compOp[$dconn] = $1;}
1389
inc_stats('abandon',$s_stats,$m_stats);
1391
if ($_ =~ /targetop= *([0-9a-zA-Z]+)/i ){
1392
$targetOp[$ac] = $1;
1393
if ($_ =~ /conn= *([0-9]+)/i){ $targetConn[$ac] = $1; }
1394
if ($_ =~ /msgid= *([0-9]+)/i){ $msgid[$ac] = $1;}
1399
if ($_ =~ /conn= *([0-9]+)/i){ $vlvconn[$vlv] = $1;}
1400
if ($_ =~ /op= *([0-9]+)/i){ $vlvop[$vlv] = $1;}
1406
if (m/ SORT /){$sortvlv++}
1407
if (m/ version=2/){$version2++}
1408
if (m/ version=3/){$version3++}
1409
if (m/ conn=1 fd=/){$restarts++}
1410
if (m/ SSL connection from/){$sslconn++;}
1411
if (m/ connection from/){
1413
if ($_ =~ /connection from *([0-9\.]+)/i ){
1414
for ($xxx =0; $xxx <= $#exclude; $xxx++){
1415
if ($exclude[$xxx] eq $1){$exc = "yes";}
1417
if ($exc ne "yes"){ $connectionCount++;}
1420
if ($simConnection > $maxsimConnection) {
1421
$maxsimConnection = $simConnection;
1424
($connID) = $_ =~ /conn=(\d*)\s/;
1425
$openConnection[$connID]++;
1426
($time, $tzone) = split (' ', $_);
1427
($date, $hr, $min, $sec) = split (':', $time);
1428
($day, $mon, $yr) = split ('/', $date);
1430
$start_time_of_connection[$connID] = timegm($sec, $min, $hours, $day, $monthname{$mon}, $yr);
1433
if (m/ SSL client bound as /){$sslClientBind++;}
1434
if (m/ SSL failed to map client certificate to LDAP DN/){$sslClientFailed++;}
1435
if (m/ fd=/ && m/slot=/){$fdtake++}
1436
if (m/ fd=/ && m/closed/){
1440
($connID) = $_ =~ /conn=(\d*)\s/;
1441
$openConnection[$connID]--;
1442
$end_time_of_connection[$connID] = $gmtime;
1443
$diff = $end_time_of_connection[$connID] - $start_time_of_connection[$connID];
1444
$start_time_of_connection[$connID] = $end_time_of_connection[$connID] = 0;
1445
if ($diff <= 1) { $latency[0]++;}
1446
if ($diff == 2) { $latency[1]++;}
1447
if ($diff == 3) { $latency[2]++;}
1448
if ($diff >= 4 && $diff <=5 ) { $latency[3]++;}
1449
if ($diff >= 6 && $diff <=10 ) { $latency[4]++;}
1450
if ($diff >= 11 && $diff <=15 ) { $latency[5]++;}
1451
if ($diff >= 16) { $latency[6] ++;}
1455
inc_stats('bind',$s_stats,$m_stats);
1456
if ($verb eq "yes"){
1457
if ($_ =~ /conn= *([0-9]+)/i){ $bindConn[$bconn] = $1; }
1458
if ($_ =~ /op= *([0-9]+)/i){ $bindOp[$bconn] = $1; }
1462
if (m/ BIND/ && m/$manager/i){$dirmgr++}
1463
if (m/ BIND/ && m/dn=""/){$anony++; $bindlist{"Anonymous Binds"}++;inc_stats('anonbind',$s_stats,$m_stats);}
1466
if ($verb eq "yes"){
1467
if ($_ =~ /conn= *([0-9]+)/i){ $unbindConn[$ubconn] = $1; }
1468
if ($_ =~ /op= *([0-9]+)/i){ $unbindOp[$ubconn] = $1; }
1473
if ($_ =~ /conn= *([0-9]+)/i){
1475
if ($_ =~ /op= *([0-9]+)/i){ $op = $1;}
1477
for ($i=0; $i <= $vlv;$i++){
1478
if ($vlvconn[$i] eq $con && $vlvop[$i] eq $op){ $vlvnotes++; $v="1";}
1481
# We don't want to record vlv unindexed searches for our regular "bad"
1482
# unindexed search stat, as VLV unindexed searches aren't that bad
1484
inc_stats('notesu',$s_stats,$m_stats);
1486
if ($usage =~ /u/ || $verb eq "yes"){
1488
if ($_ =~ /etime= *([0-9]+)/i ) {
1489
$notesEtime[$vet]=$1;
1492
if ($_ =~ /conn= *([0-9]+)/i){
1496
if ($_ =~ /op= *([0-9]+)/i){
1500
if ($_ =~ / *([0-9a-z:\/]+)/i){
1501
$notesTime[$nt] = $1;
1505
if ($_ =~ /nentries= *([0-9]+)/i ){
1506
$notesNentries[$nent] = $1;
1513
if (m/ closed error 32/){
1515
if (m/- T1/){ $rc{"T1"}++ }
1516
elsif (m/- T2/){ $rc{"T2"}++ }
1517
elsif (m/- A1/){ $rc{"A1"}++ }
1518
elsif (m/- B1/){ $rc{"B1"}++ }
1519
elsif (m/- B4/){ $rc{"B4"}++ }
1520
elsif (m/- B2/){ $rc{"B2"}++ }
1521
elsif (m/- B3/){ $rc{"B3"}++ }
1522
elsif (m/- R1/){ $rc{"R1"}++ }
1523
elsif (m/- P1/){ $rc{"P1"}++ }
1524
elsif (m/- P1/){ $rc{"P2"}++ }
1525
elsif (m/- U1/){ $rc{"U1"}++ }
1526
else { $rc{"other"}++; }
1528
if (m/ closed error 131/ || m/ closed error -5961/){
1530
if (m/- T1/){ $src{"T1"}++ }
1531
elsif (m/- T2/){ $src{"T2"}++ }
1532
elsif (m/- A1/){ $src{"A1"}++ }
1533
elsif (m/- B1/){ $src{"B1"}++ }
1534
elsif (m/- B4/){ $src{"B4"}++ }
1535
elsif (m/- B2/){ $src{"B2"}++ }
1536
elsif (m/- B3/){ $src{"B3"}++ }
1537
elsif (m/- R1/){ $src{"R1"}++ }
1538
elsif (m/- P1/){ $src{"P1"}++ }
1539
elsif (m/- P1/){ $src{"P2"}++ }
1540
elsif (m/- U1/){ $src{"U1"}++ }
1541
else { $src{"other"}++ }
1544
if (m/ closed error 11/){
1546
if (m/- T1/){ $rsrc{"T1"}++ }
1547
elsif (m/- T2/){ $rsrc{"T2"}++ }
1548
elsif (m/- A1/){ $rsrc{"A1"}++ }
1549
elsif (m/- B1/){ $rsrc{"B1"}++ }
1550
elsif (m/- B4/){ $rsrc{"B4"}++ }
1551
elsif (m/- B2/){ $rsrc{"B2"}++ }
1552
elsif (m/- B3/){ $rsrc{"B3"}++ }
1553
elsif (m/- R1/){ $rsrc{"R1"}++ }
1554
elsif (m/- P1/){ $rsrc{"P1"}++ }
1555
elsif (m/- P1/){ $rsrc{"P2"}++ }
1556
elsif (m/- U1/){ $rsrc{"U1"}++ }
1557
else { $rsrc{"other"}++ }
1560
if ($usage =~ /g/ || $usage =~ /c/ || $usage =~ /i/ || $verb eq "yes"){
1564
if ($_ =~ /connection from *([0-9\.]+)/i ) {
1565
for ($xxx = 0; $xxx <= $#exclude; $xxx++){
1566
if ($1 eq $exclude[$xxx]){
1572
$ip_hash{$ip}{"count"}++;
1573
if ($_ =~ /conn= *([0-9]+)/i ){
1574
if ($exc ne "yes"){ $ip_hash2{$ip} = sprintf "%-12s %18s\n",$1,$ip;}
1575
$conn_hash{$1} = $ip;
1581
if ($_ =~ /conn= *([0-9]+)/i) {
1583
$ip = $conn_hash{$1};
1584
if ($ip eq ""){$ip = "Unknown Host";}
1585
for ($xxx = 0; $xxx <= $#exclude; $xxx++){
1586
if ($ip eq $exclude[$xxx]){$exc = "yes";}
1589
$ip_hash{$ip}{"A1"}++;
1596
if ($_ =~ /conn= *([0-9]+)/i) {
1598
$ip = $conn_hash{$1};
1599
if ($ip eq ""){$ip = "Unknown Host";}
1600
for ($xxx = 0; $xxx <= $#exclude; $xxx++){
1601
if ($ip eq $exclude[$xxx]){$exc = "yes";}
1604
$ip_hash{$ip}{"B1"}++;
1611
if ($_ =~ /conn= *([0-9]+)/i) {
1613
$ip = $conn_hash{$1};
1614
if ($ip eq ""){$ip = "Unknown Host";}
1615
for ($xxx = 0; $xxx <= $#exclude; $xxx++){
1616
if ($ip eq $exclude[$xxx]){$exc = "yes";}
1619
$ip_hash{$ip}{"B4"}++;
1626
if ($_ =~ /conn= *([0-9]+)/i) {
1628
$ip = $conn_hash{$1};
1629
if ($ip eq ""){$ip = "Unknown Host";}
1630
for ($xxx = 0; $xxx <= $#exclude; $xxx++){
1631
if ($ip eq $exclude[$xxx]){$exc = "yes";}
1634
$ip_hash{$ip}{"T1"}++;
1641
if ($_ =~ /conn= *([0-9]+)/i) {
1643
$ip = $conn_hash{$1};
1644
if ($ip eq ""){$ip = "Unknown Host";}
1645
for ($xxx = 0; $xxx <= $#exclude; $xxx++){
1646
if ($ip eq $exclude[$xxx]){$exc = "yes";}
1649
$ip_hash{$ip}{"T2"}++;
1656
if ($_ =~ /conn= *([0-9]+)/i) {
1658
$ip = $conn_hash{$1};
1659
if ($ip eq ""){$ip = "Unknown Host";}
1660
for ($xxx = 0; $xxx <= $#exclude; $xxx++){
1661
if ($ip eq $exclude[$xxx]){$exc = "yes";}
1664
$ip_hash{$ip}{"B2"}++;
1671
if ($_ =~ /conn= *([0-9]+)/i) {
1673
$ip = $conn_hash{$1};
1674
if ($ip eq ""){$ip = "Unknown Host";}
1675
for ($xxx = 0; $xxx <= $#exclude; $xxx++){
1676
if ($ip eq $exclude[$xxx]){$exc = "yes";}
1679
$ip_hash{$ip}{"B2"}++;
1686
if ($_ =~ /conn= *([0-9]+)/i) {
1688
$ip = $conn_hash{$1};
1689
if ($ip eq ""){$ip = "Unknown Host";}
1690
for ($xxx = 0; $xxx <= $#exclude; $xxx++){
1691
if ($ip eq $exclude[$xxx]){$exc = "yes";}
1694
$ip_hash{$ip}{"B3"}++;
1701
if ($_ =~ /conn= *([0-9]+)/i) {
1703
$ip = $conn_hash{$1};
1704
if ($ip eq ""){$ip = "Unknown Host";}
1705
for ($xxx = 0; $xxx <= $#exclude; $xxx++){
1706
if ($ip eq $exclude[$xxx]){$exc = "yes";}
1709
$ip_hash{$ip}{"R1"}++;
1716
if ($_ =~ /conn= *([0-9]+)/i) {
1718
$ip = $conn_hash{$1};
1719
if ($ip eq ""){$ip = "Unknown Host";}
1720
for ($xxx = 0; $xxx <= $#exclude; $xxx++){
1721
if ($ip eq $exclude[$xxx]){$exc = "yes";}
1724
$ip_hash{$ip}{"P1"}++;
1731
if ($_ =~ /conn= *([0-9]+)/i) {
1733
$ip = $conn_hash{$1};
1734
if ($ip eq ""){$ip = "Unknown Host";}
1735
for ($xxx = 0; $xxx <= $#exclude; $xxx++){
1736
if ($ip eq $exclude[$xxx]){$exc = "yes";}
1739
$ip_hash{$ip}{"P2"}++;
1746
if ($_ =~ /conn= *([0-9]+)/i) {
1748
$ip = $conn_hash{$1};
1749
if ($ip eq ""){$ip = "Unknown Host";}
1750
for ($xxx = 0; $xxx <= $#exclude; $xxx++){
1751
if ($ip eq $exclude[$xxx]){$exc = "yes";}
1754
$ip_hash{$ip}{"U1"}++;
1763
if ($_ =~ /err= *([0-9]+)/i){
1765
if ($1 ne "0"){ $errorck++;}
1766
else { $errorsucc++;}
1768
if ($_ =~ /etime= *([0-9]+)/i ) { $etime{$1}++;}
1769
if ($_ =~ / tag=101 nentries= *([0-9]+)/i ) {$nentries{$1}++}
1770
if ($_ =~ / tag=111 nentries= *([0-9]+)/i ) {$nentries{$1}++}
1771
if ($_ =~ / tag=100 nentries= *([0-9]+)/i ) {$nentries{$1}++}
1772
if ($_ =~ / tag=115 nentries= *([0-9]+)/i ) {$nentries{$1}++}
1773
if (m/objectclass=\*/i || m/objectclass=top/i ){
1774
if (m/ scope=2 /){ $objectclass++;}
1779
if ($_ =~ /oid=\" *([0-9\.]+)/i ){ $oid{$1}++; }
1780
if ($verb eq "yes"){
1781
if ($_ =~ /conn= *([0-9]+)/i){ $extConn[$econn] = $1; }
1782
if ($_ =~ /op= *([0-9]+)/i){ $extOp[$econn] = $1; }
1787
if (m/ BIND/ && $_ =~ /dn=\"(.*)\" method/i ){
1790
$tmpp =~ tr/A-Z/a-z/;
1791
$bindlist{$tmpp} = $bindlist{$tmpp} + 1;
1793
$bindInfo[$bc][0] = $tmpp;
1794
if ($_ =~ /conn= *([0-9]+)/i) { $bindInfo[$bc][1] = $1; }
1795
if ($_ =~ /op= *([0-9]+)/i) { $bindInfo[$bc][2] = $1; }
1800
if ($usage =~ /l/ || $verb eq "yes"){
1801
if (/ SRCH / && / attrs=/ && $_ =~ /filter=\"(.*)\" /i ){
1803
$tmpp =~ tr/A-Z/a-z/;
1804
$tmpp =~ s/\\22/\"/g;
1805
$filter{$tmpp} = $filter{$tmpp} + 1;
1806
$filterInfo[$fcc][0] = $tmpp;
1807
if ($_ =~ /conn= *([0-9]+)/i) { $filterInfo[$fcc][1] = $1; }
1808
if ($_ =~ /op= *([0-9]+)/i) { $filterInfo[$fcc][2] = $1; }
1810
} elsif (/ SRCH / && $_ =~ /filter=\"(.*)\"/i){
1812
$tmpp =~ tr/A-Z/a-z/;
1813
$tmpp =~ s/\\22/\"/g;
1814
$filter{$tmpp} = $filter{$tmpp} + 1;
1815
$filterInfo[$fcc][0] = $tmpp;
1816
if ($_ =~ /conn= *([0-9]+)/i) { $filterInfo[$fcc][1] = $1; }
1817
if ($_ =~ /op= *([0-9]+)/i) { $filterInfo[$fcc][2] = $1; }
1822
if ($usage =~ /a/ || $verb eq "yes"){
1823
if (/ SRCH / && $_ =~ /base=\"(.*)\" scope/i ){
1829
$tmpp =~ tr/A-Z/a-z/;
1830
$base{$tmpp} = $base{$tmpp} + 1;
1833
# grab the search bases & scope for potential unindexed searches
1835
$baseInfo[$bcc][0] = $tmpp;
1836
if ($_ =~ /scope= *([0-9]+)/i) {
1837
$scopeInfo[$scc][0] = $1;
1839
if ($_ =~ /conn= *([0-9]+)/i) {
1840
$baseInfo[$bcc][1] = $1;
1841
$scopeInfo[$scc][1] = $1;
1843
if ($_ =~ /op= *([0-9]+)/i) {
1844
$baseInfo[$bcc][2] = $1;
1845
$scopeInfo[$scc][2] = $1;
1853
if ($_ =~ /fd= *([0-9]+)/i ) {
1855
if ($fds[$fdds] > $highfd) {$highfd = $fds[$fdds];}
1860
if ($usage =~ /f/ || $verb eq "yes"){
1861
if (/ err=49 tag=/ && / dn=\"/){
1862
if ($_ =~ /dn=\"(.*)\"/i ){
1868
} elsif (/ err=49 tag=/ ){
1869
if ($_ =~ /conn= *([0-9]+)/i ){
1870
$badPasswordConn[$bpc] = $1;
1873
if ($_ =~ /op= *([0-9]+)/i ){
1874
$badPasswordOp[$bpo] = $1;
1877
$badPasswordIp[$bpi] = $ip;
1882
if (/ BIND / && /method=sasl/i){
1884
if ($_ =~ /mech=(.*)/i ){
1889
if (/ conn=Internal op=-1 / && !/ RESULT err=/){ $internal++; }
1891
if (/ ENTRY dn=/ ){ $entryOp++; }
1893
if (/ conn=/ && /op=/ && / REFERRAL/){ $referral++; }
1895
if (/ options=persistent/){$persistent++;}
1899
#######################################
1901
# +# CSV Helper Routines #
1903
#######################################
1905
# To convert the CSV to chart in OO #
1907
# * Select active rows and columns #
1908
# * Insert -> Chart #
1909
# * Chart type "XY (Scatter)" #
1910
# * sub-type "Lines Only" #
1911
# * select "Sort by X values" #
1913
# * select "Data series in columns" #
1914
# * select "First row as label" #
1915
# * select "First column as label" #
1920
#######################################
1927
$stats->{'last'} = shift || 0;
1928
$stats->{'last_str'} = shift || '';
1930
$stats->{'results'}=0;
1934
$stats->{'modrdn'}=0;
1935
$stats->{'moddn'}=0;
1938
$stats->{'abandon'}=0;
1939
$stats->{'conns'}=0;
1940
$stats->{'sslconns'}=0;
1942
$stats->{'anonbind'}=0;
1943
$stats->{'unbind'}=0;
1944
$stats->{'notesu'}=0;
1951
my $name = shift || '';
1958
$stats->{'filename'} = $name;
1959
$stats->{'fh'} = new IO::File;
1960
$stats->{'active'} = open($stats->{'fh'},">$name");
1963
reset_stats_block( $stats );
1970
foreach my $stats( @_ )
1972
if ($stats->{'active'})
1974
if ($stats->{'last'})
1976
$stats->{'fh'}->print(
1978
$stats->{'last_str'},
1980
$stats->{'results'},
1988
$stats->{'abandon'},
1990
$stats->{'sslconns'},
1992
$stats->{'anonbind'},
1994
$stats->{'notesu'} ),
1998
$stats->{'fh'}->print(
1999
"Time,time_t,Results,Search,Add,Mod,Modrdn,Delete,Abandon,".
2000
"Connections,SSL Conns,Bind,Anon Bind,Unbind,Unindexed\n"
2020
#######################################
2024
#######################################