#!/usr/bin/perl # # Name: ldapconnresponse.pl # Author: Lionel Bartlett # Copyright: Novell PTY LTD # Modified: - # Modified date: 14 May 2009 # Purpose: Determines the elapsed time for each LDAP connection # Version: 2.1 ######################################################################################### # History: # Date Modifier Description # # LIMITATION: Script does not permit multiple DATES! Ensure dates are for same day. # # 27 Sept 08 LB Tested with NetWare, Linux and Solaris # NW does not provide millisec timing # Solaris adds text to start and end of each line # which might need to be deleted prior to using script # 10 Oct 08 LB Check for timestamps in log file added. Abort processing if missing. # Added additional help screen information # 13 Oct 08 LB Fixed OPS statis overview display symbols, was not displaying correct symbol # Added Abandon operation trigger # Note: When I get an abandon, I don't look for the UnBind! # 14 Oct 08 LB Fixed spelling mistake # 23 Feb 09 LB Added check for wrapped log files. Don't crash when it's wrapped # Added support for DoExtended... used with nmas for eDir updates # 20 Mar 09 LB Corrected -d statement in help screen # 20 Mar 09 LB Added check for Failed bind and Invalid Context during Bind # 25 Mar 09 LB Fixed visual display bug - added newline # 26 Mar 09 LB Added check for expired passwords # 2 Apr 09 LB Put the CSV columns for Failed Bind and Invalid Context in the correct order # 7 Apr 09 LB Added code to report missing IP and Port in traces # 14 Apr 09 LB Refined check for missing IP and Port in traces # Made response times higher precision in reports ######################################################################################### $VERSION = "2.2"; # Response time precision. If required this can be made an command-line parameter in a later version $mSec="%0.2f"; use warnings; use Switch; use Getopt::Std; sub gettime($); sub getipaddress($); sub getthread($); sub getportnumber($); sub getLDAPdata($); sub gettimer($); sub resetConn($); sub printResults($$$$$$$$$); sub getLdapOp($$); sub countLDAP($$) ; sub addUpOps($); sub gettimesector($); sub useLDAPData($$$$$); sub getcurrentuser($); sub isLdapOp($); sub legend($); sub getdatetime($); sub getmsgid($); sub usage(); sub verbose_usage(); %options=(); getopts("x-:d:b:n:",\%options); if (defined $options{"-"}) { if ($options{"-"} =~ /help/) { verbose_usage(); } else { usage(); } } if (defined $options{x}) { $makecsv = 1; } else { $makecsv = 0; } if (defined $options{d}) { $ldapdelay = $options{d}; # LDAP response time (delay) $showuser=1; } else { $ldapdelay = 0; $showuser=0; } if (defined $options{b}) { $binduser = $options{b}; # Bind username. Relates to LDAP reponse time delay. } else { $binduser=""; } if (defined $options{n}) { $condelayresponses = $options{n}; # Consecutive bind delay responses } else { $condelayresponses=3; } if (@ARGV == 1) { $in = $ARGV[0]; } else { usage(); } # Read the entire file into an array open (IN, $in) || die "Can't open $in\n"; @trace = ; $len = @trace; #------------------------------------- # Variables $logtimer=0; $tracetime=""; $totalConnections=0; $traceStart=0; $traceStartLong=0; $traceEnd=0; $traceEndLong=0; $ldapOpName=""; $totalLDAPops=0; $currentuser=""; $userdelaytotal=0; $ldaptype=""; $consecbindtotal=0; $consecbindmatched=0; $consecbindStart=""; $consecbindEnd=""; $consectimetotal=0; $failedBindPwd=0; $failedContextInvalid=0; $failedPwdExpired=0; $IPandPortMissing=0; my @matchedusersec = (); my @responsetime = (); my @ldapconndata = ([],[]); my @trackLDAPoperations = (); #------------------------------------- $trackLDAPoperations[0][0]="Search "; $trackLDAPoperations[1][0]="Modify "; $trackLDAPoperations[2][0]="Add "; $trackLDAPoperations[3][0]="Delete "; $trackLDAPoperations[4][0]="Bind "; $trackLDAPoperations[5][0]="ModRDN "; $trackLDAPoperations[6][0]="Abandon "; $trackLDAPoperations[7][0]="Extended"; $trackLDAPoperations[8][0]="Compare "; if ( $showuser ) { $csvtitle="Object Name";} else { $csvtitle="Operation"; $unbind_data="UNBIND"; } if ($makecsv) {print "$csvtitle,Port #,IP Address,Thread #,New Start Time,Sent #,Invalid Context,Failed Bind,Password Expired,New to Bind Delay,New to Sent Delay,New to UnBind Delay,Bind to Sent Delay,Bind to UnBind Delay,New Failed Delay,Sector Time,Sector Number,LDAP Operations\n";} for ($c1 = 0; $c1 < $len; $c1++) { #------------------------------------- # New Code if ( getportnumber($trace[$c1]) ne "" ) { $ldapOpName = getLdapOp($trace[$c1],$ldapOpName); if ( isLdapOp ($trace[$c1]) ) { $ldaptype = countLDAP(0,$ldapOpName); $portnumber=getportnumber($trace[$c1]); if ( defined($ldapconndata{$portnumber}[5] && $ldaptype eq "B") ) { # # No unbind/abandon on conn! # if ( $ldapconndata{$portnumber}[12] =~ /B/ ) { # $ldapconndata{$portnumber}[12]=$ldapconndata{$portnumber}[12]."!"; # } $ldapconndata{$portnumber}[12]=$ldapconndata{$portnumber}[12].$ldaptype; $ldapconndata{$portnumber}[11]=$ldaptype; } } if ($trace[$c1] =~ /New TLS connection|New cleartext connection/) { getLDAPdata($trace[$c1]); $ldapconndata{$portnumber}[1]=$portnumber; # portnumber $ldapconndata{$portnumber}[2]=$ipaddress; # IP Address $ldapconndata{$portnumber}[3]=$threadnumber; # Thread/Connection number $ldapconndata{$portnumber}[4]=$tracetime; # TLS time $ldapconndata{$portnumber}[5]=$logtimer; # TLS Timer $ldapconndata{$portnumber}[6]=$logtimer; # Bind Timer $ldapconndata{$portnumber}[7]=$logtimer; # Send Timer $ldapconndata{$portnumber}[8]=0; # Send Count $ldapconndata{$portnumber}[9]=$logtimer; # Unbind Timer $ldapconndata{$portnumber}[10]=0; # Connection Duration $ldapconndata{$portnumber}[11]=""; # Last Op $ldapconndata{$portnumber}[12]=""; # All Ops $ldapconndata{$portnumber}[13]=""; # Binduser $ldapconndata{$portnumber}[14]=""; # Context Invalid $ldapconndata{$portnumber}[15]=""; # Failed Bind $ldapconndata{$portnumber}[16]=""; # Password Expired } else { if ($trace[$c1] =~ /TLS handshake failed/) { getLDAPdata($trace[$c1]); if ( defined($ldapconndata{$portnumber}[5]) ) { #$tls_tlsFaileddelay=sprintf($mSec,$logtimer - $ldapconndata{$portnumber}[5]); resetConn($portnumber); } } else { if ($trace[$c1] =~ / Bind name:/) { getLDAPdata($trace[$c1]); #if ( defined($ldapconndata{$portnumber}[5]) ) { # means there was no unbind/abandon on connection # $tls_unbinddelay=sprintf($mSec,$logtimer - $ldapconndata{$portnumber}[5]); #if ( exists($responsetime[$tls_unbinddelay][2]) && $ldapconndata{$portnumber}[12] ne "" ) { # $responsetime[$tls_unbinddelay][2]=$responsetime[$tls_unbinddelay][2]+1; # $responsetime[$tls_unbinddelay][3] =~ s/z/Z/i; #} #} if ( defined($ldapconndata{$portnumber}[5]) ) { $currentuser=getcurrentuser($trace[$c1]); $tls_binddelay=sprintf($mSec,$logtimer - $ldapconndata{$portnumber}[5]); $ldapconndata{$portnumber}[6]=$logtimer; $ldapconndata{$portnumber}[13]=$currentuser; } } else { if ($trace[$c1] =~ /Sending operation result/) { getLDAPdata($trace[$c1]); if ( exists($ldapconndata{$portnumber}[5]) ) { $bind_sentdelay=sprintf($mSec,$logtimer - $ldapconndata{$portnumber}[5]); $ldapconndata{$portnumber}[7]=$logtimer; $ldapconndata{$portnumber}[8]=$ldapconndata{$portnumber}[8]+1; #$ldapconndata{$portnumber}[11]="SENT"; } $ldaptype = countLDAP(1,$ldapOpName); if ( $trace[$c1] =~ /NDS error. password expired/) { $failedPwdExpired++; if ( exists($ldapconndata{$portnumber}[5]) ) { $ldapconndata{$portnumber}[16]="PX"; } } } else { if ($trace[$c1] =~ / DoUnbind | DoAbandon /) { getLDAPdata($trace[$c1]); if ( exists($ldapconndata{$portnumber}[5]) ) { $tls_binddelay=sprintf($mSec,$ldapconndata{$portnumber}[6] - $ldapconndata{$portnumber}[5]); $tls_sentdelay=sprintf($mSec,$ldapconndata{$portnumber}[7] - $ldapconndata{$portnumber}[5]); $tls_unbinddelay=sprintf($mSec,$logtimer - $ldapconndata{$portnumber}[5]); if ( $tls_unbinddelay > -1 ) { $bind_sentdelay=sprintf($mSec,$ldapconndata{$portnumber}[7] - $ldapconndata{$portnumber}[6]); $bind_unbinddelay=sprintf($mSec,$logtimer - $ldapconndata{$portnumber}[6]); $ldapconndata{$portnumber}[9]=$logtimer; $timesector=gettimesector($ldapconndata{$portnumber}[4]); if ( $showuser ) { $unbind_data=$ldapconndata{$portnumber}[13];} if ( useLDAPData($tls_unbinddelay,$ldapdelay,$binduser,$portnumber,$tls_unbinddelay) && $makecsv) { printResults($unbind_data,$tls_binddelay,$tls_sentdelay,$tls_unbinddelay,$bind_sentdelay,$bind_unbinddelay,"",$timesector,$ldapconndata{$portnumber}[12]); } $responsetime[$tls_unbinddelay][1]=$tls_unbinddelay; $ldaptype=$ldapconndata{$portnumber}[11]; if ( exists($responsetime[$tls_unbinddelay][2])) { $responsetime[$tls_unbinddelay][2]=$responsetime[$tls_unbinddelay][2]+1; $responsetime[$tls_unbinddelay][3] =~ s/$ldaptype/$ldaptype/i; } else { $responsetime[$tls_unbinddelay][2]=1; $responsetime[$tls_unbinddelay][3]="smadbrxezc"; $responsetime[$tls_unbinddelay][3] =~ s/$ldaptype/$ldaptype/i; $responsetime[$tls_unbinddelay][4]=$ldapconndata{$portnumber}[8]; } if ($ldapconndata{$portnumber}[8] > $responsetime[$tls_unbinddelay][4] ) { $responsetime[$tls_unbinddelay][4] = $ldapconndata{$portnumber}[8]; } if ($traceStart==0) { $traceStart=$logtimer; $traceStartLong=$ldapconndata{$portnumber}[4];} $traceEnd=$logtimer; $traceEndLong=getdatetime($trace[$c1]); $totalConnections++; resetConn($threadnumber); } } # IF } else { if ($trace[$c1] =~ /Failed to resolve full context/) { $failedContextInvalid++; getLDAPdata($trace[$c1]); if ( exists($ldapconndata{$portnumber}[5]) ) { $ldapconndata{$portnumber}[14]="IC"; } } elsif ($trace[$c1] =~ /Failed to authenticate full context|Failed to authenticate local on connection/) { $failedBindPwd++; getLDAPdata($trace[$c1]); if ( exists($ldapconndata{$portnumber}[5]) ) { $ldapconndata{$portnumber}[15]="FB"; } }# IF else } # IF else } # IF else } # IF else } # IF } # IF } # FOR #------------------------------------- } if (! $makecsv) { $traceLen=sprintf($mSec,$traceEnd-$traceStart); $traceLenMin=sprintf("%0.2f",$traceLen/60); $connPerSec="?"; if ($traceLen != 0) {$connPerSec=sprintf("%0.3f",$totalConnections/$traceLen);} if ( $showuser ) { if ($binduser eq "") { $binduser="All Objects" ;} $conntitle ="\t\t$binduser\t Percent\n"; $tmp=$binduser; $tmp=~s/./-/g; $conntitleunder="\t\t$tmp\t -------\n"; } else { $conntitle="\n"; $conntitleunder="\n"; } print "\n** Statistics View **\nConnection times are from 'New Connection' until 'UnBind'\n\n"; print "Filename: $in\n"; print "Log Time: $traceStartLong to $traceEndLong\n\n"; print "Trace Length: $traceLen seconds \t[ $traceLenMin Minutes ]\n"; if ($traceLen < 0 ) { print "\t\t\t\t(A negative number means the trace has wrapped!)\n"; } print "Total Connections: $totalConnections\n"; print "Connections per Second: $connPerSec\n"; if ( $failedBindPwd != 0 ) { print "Total Failed Binds (FB): $failedBindPwd\n"; } if ( $failedContextInvalid != 0 ) { print "Total Invalid Contexts (IC): $failedContextInvalid\n"; } if ( $failedPwdExpired !=0 ) { print "Total Password Expired (PX): $failedPwdExpired\n"; } if ( $showuser ) { print "\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"; print "Focus on Bind user: $binduser\n"; print "Delay value: $ldapdelay\n"; $percentOfTotal=sprintf("%6.2f",($userdelaytotal/$totalConnections)*100); print "Total delays matched: $userdelaytotal\t\[$percentOfTotal% of total connections\ ]\n"; print "Maximum consecutive delays: $consecbindmatched [ Maximum Required: $condelayresponses ]\n"; $consec_duration=sprintf("%0.1f",$consectimetotal); if ($consecbindmatched) { print "Slow response duration: $consec_duration seconds [ Between $consecbindStart - $consecbindEnd ]\n"; } print "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"; } print "\n\tSeconds\tTotal\t Percent\tOPs\t\tMax Ops$conntitle"; print "\t-------\t-----\t -------\t---\t\t-------$conntitleunder"; $exceededLimit=0; foreach my $ldapresponse (0..$#responsetime) { if ( exists($responsetime[$ldapresponse][1])) { $percentOfTotal=sprintf("%10.2f",($responsetime[$ldapresponse][2]/$totalConnections)*100); $responsetime[$ldapresponse][3] =~ s/[a-z]/ /g; print "\t$responsetime[$ldapresponse][1]\t$responsetime[$ldapresponse][2]\t$percentOfTotal%\t$responsetime[$ldapresponse][3]\t$responsetime[$ldapresponse][4]"; if ( $showuser && exists $matchedusersec[$ldapresponse] ) { $percentOfTotal=sprintf("%10.2f",($matchedusersec[$ldapresponse]/$totalConnections)*100); print "\t\t$matchedusersec[$ldapresponse]\t\t$percentOfTotal%\n"; $exceededLimit=$exceededLimit+$percentOfTotal; } else { print "\n"; } } else { #if ( $showuser && exists $matchedusersec[$ldapresponse] ) { # $percentOfTotal=sprintf("%10.1f",($matchedusersec[$ldapresponse]/$totalConnections)*100); # print "\t\t\t\t\t$matchedusersec[$ldapresponse]\t\t$percentOfTotal%\n"; #} } } if ( $showuser ) { print "\n\tPercentage exceeding time response limit $ldapdelay for '$binduser': $exceededLimit%\n"; } print "\n"; legend(0); $connPerSec="?"; if ($traceLen != 0) {$connPerSec=sprintf("%0.3f",$totalLDAPops/$traceLen);} print "LDAP Operation Distribution:\n\n"; print "Total LDAP Operations: $totalLDAPops\n"; print "LDAP Operations per Second: $connPerSec\n\n"; print "\tName\t\tTotal\t Percent\n"; print "\t----\t\t-----\t -------\n"; foreach my $ldapresponse (0..$#trackLDAPoperations) { if ( exists $trackLDAPoperations[$ldapresponse][1] ) { $percentOfTotal=sprintf("%10.2f",($trackLDAPoperations[$ldapresponse][1]/$totalLDAPops)*100); print "\t$trackLDAPoperations[$ldapresponse][0]\t$trackLDAPoperations[$ldapresponse][1]\t$percentOfTotal%\n"; } } print "\n\n"; } ################################################################################################################# # Start of Sub-Functions # ################################################################################################################# sub getcurrentuser($) { my ($parm1) = @_; if ( $parm1=~ m/Bind name:\w+(?:=|)(\w+)/ ) { return $1; } else { return ""; } } sub useLDAPData($$$$$) { ($tls_unbinddelay,$ldapdelay,$bindname,$portnumber,$tls_unbinddelay) = @_; $currentuser=$ldapconndata{$portnumber}[13]; $tlsstarttime=$ldapconndata{$portnumber}[4]; if ( $currentuser eq "" ) {return 0;} #if ( ! $ldapdelay ) {return 1;} if ( $bindname eq "" || $bindname eq $currentuser ) { if ( $tls_unbinddelay >= $ldapdelay ) { if ( exists $matchedusersec[$tls_unbinddelay]) { $matchedusersec[$tls_unbinddelay]=$matchedusersec[$tls_unbinddelay]+1; } else { $matchedusersec[$tls_unbinddelay]=1; } $userdelaytotal++; $consecbindtotal++; if ( $consecbindmatched < $condelayresponses && $consecbindmatched < $consecbindtotal) { $consecbindmatched=$consecbindtotal; if ($consecbindtotal == 1) {$consecbindStart=$tlsstarttime;} $consecbindtotal=0; $consecbindEnd=$tlsstarttime; $consectimetotal=gettimer($tlsstarttime)-gettimer($consecbindStart); } return 1; } else { $consecbindtotal=0 } } else { return 0; } } sub addUpOps($) { my ($opPosition) = @_; if ( exists $trackLDAPoperations[$opPosition][1] ) { $trackLDAPoperations[$opPosition][1]=$trackLDAPoperations[$opPosition][1]+1; } else { $trackLDAPoperations[$opPosition][1]=1; } $totalLDAPops++; } sub countLDAP($$) { my ($countldap,$ldapOpName) = @_; # Parameter values: 0 | 1 switch ($ldapOpName) { case " DoSearch" {if ($countldap) {addUpOps(0);} return "S";last } case " DoModify" {if ($countldap) {addUpOps(1);} return "M";last } case " DoAdd" {if ($countldap) {addUpOps(2);} return "A";last } case " DoDelete" {if ($countldap) {addUpOps(3);} return "D";last } case " DoBind" {if ($countldap) {addUpOps(4);} return"B";last } case " DoModRDN" {if ($countldap) {addUpOps(5);} return "R";last } case " DoAbandon" {if ($countldap) {addUpOps(6);} return "X";last } case " DoExtended " {if ($countldap) {addUpOps(7);} return "E";last } case " DoCompare " {if ($countldap) {addUpOps(8);} return "C";last } } } sub getLdapOp($$) { my ($ldapmessage,$oldop) = @_; if ( $ldapmessage =~ m/ DoSearch| DoModify| DoAdd| DoDelete| DoBind| DoModRDN| DoAbandon| DoExtended | DoCompare / ) { return $&; } return $oldop; } sub isLdapOp($) { my ($ldapmessage) = @_; if ( $ldapmessage =~ m/ DoSearch| DoModify| DoAdd| DoDelete| DoBind| DoModRDN| DoAbandon| DoExtended | DoCompare / ) { return 1; } return 0; } sub printResults($$$$$$$$$) { ($message_section,$tls_bind,$tls_sent,$tls_unbind,$bind_sent,$bind_unbind,$tls_failed,$time_sector,$ldap_ops) = @_; print "$message_section,"; print "$ldapconndata{$portnumber}[1],"; # port print "$ldapconndata{$portnumber}[2],"; # ip print "$ldapconndata{$portnumber}[3],"; # thread print "$ldapconndata{$portnumber}[4],"; # TLS start time print "$ldapconndata{$portnumber}[8],"; # Sent count print "$ldapconndata{$portnumber}[14],"; # Failed Login print "$ldapconndata{$portnumber}[15],"; # Invalid Context print "$ldapconndata{$portnumber}[16],"; # Password Expired print "$tls_bind,"; # Time from TLS start to Bind message print "$tls_sent,"; # Time from TLS start to last 'Sending operation result' relating to data (not unbind) print "$tls_unbind,"; # Time from TLS start to unbind message print "$bind_sent,"; # Time from Bind message to last 'Sending operation result' relating to data (not unbind) print "$bind_unbind,"; # Time from Bind to Unbind message print "$tls_failed,"; # TLS connection failed print "$time_sector,"; # 10 sec intervals print "$ldap_ops\n"; # All LDAP Ops } sub resetConn($) { my ($parm1) = @_; delete $ldapconndata{$portnumber}; } sub getLDAPdata($) { my ($parm1) = @_; $portnumber=getportnumber($trace[$c1]); $ipaddress=getipaddress($trace[$c1]); $threadnumber=getthread($trace[$c1]); $tracetime=gettime($trace[$c1]); $logtimer=gettimer($trace[$c1]); } sub getportnumber($) { my ($parm1) = @_; if ($parm1=~ m/\d+\.\d+\.\d+\.\d+:(\d+)(?:,| |\))/ ) { return $1; } else { if ( ! $parm1 =~ " 0x" && ! $IPandPortMissing ) { print "\n* Problem Detected *\n"; print " This trace does not contain the IP address and Port number\n"; print " Please enable additional screen options on the LDAP server\n"; print " Statistics will be limited due to missing information.\n\n"; print "$parm1\n"; $IPandPortMissing=1; } return 0; } } sub getipaddress($) { my ($parm1) = @_; if ($parm1 =~ m/(\d+\.\d+\.\d+\.\d+)/ ) { return $1; } } sub getthread($) { my ($parm1) = @_; if ( $parm1 =~ m/0x([a-f0-9]{6,8})/ ) { return $1; } else { return "-1" ; } } sub gettime($) { my ($parm1) = @_; $tmp=""; if ( $parm1 =~ m/(.{1,2}:..:..\.\d+|.{1,2}:..:..)/ ) { $tmp=$1; $tmp=~s/ //; return $tmp; } else { return 0; #die "Function gettime: can't find valid time string in $parm1\n"; } } sub getdatetime($) { my ($parm1) = @_; if ($parm1 =~ /(\d+.\d+.\d+ .{1,2}:..:..)/) { return $1; } else { return "?"; #die "Function gettime: can't find valid time string in $parm1\n"; } } sub gettimesector($) { my ($parm1) = @_; if ($parm1 =~ /(.{1,2}:..:.)/) { $tmp=$1; $tmp=~s/:/_/; $tmp=~s/:/,S/; $tmp=~s/ //; return $tmp; } else { return 0; #die "Function gettime: can't find valid time string in $parm1\n"; } } sub gettimer($) { my ($parm1) = @_; $ht=0;$mt=0;$st=0; $milsec="000"; if ($parm1 =~ /(.{1,2}):(..):(..)\.(\d+)/) { $ht=($1*60)*60; $mt=($2*60); $st=($3); $milsec="00$4"; if ( $milsec=~/(.{3}$)/ ) {$milsec="0.$1";} } else { if ($parm1 =~ /(.{1,2}):(..):(..)/) { $ht=($1*60)*60; $mt=($2*60); $st=($3); } else { print "This log file does not contain timestamps, which are required to perform certain calculations.\n"; exit; } } $tmptime=$ht+$mt+$st+$milsec; return $tmptime; } sub legend ($) { my ($parm1) = @_; print "\t*- Legend -*\n\tIdentifies last LDAP operation performed on a connection:\n"; print "\t\tS = Search M = Modify A = Add D = Delete\n"; print "\t\tB = Bind R = ModRDN X = Abandon E = Extended\n\n"; print "\tIn Statistics View the symbols only provide some indication\n\tof (primary) operation Type verse Response:\n"; print "\t e.g. 'B' means only a Bind & Unbind occurred on a connection\n"; print "\t e.g. 'M' means a Modify occurred (many other ops could have preceded it)\n\n"; if ($parm1) {print "\tIn CSV output the symbols indicate all operations for a specific connection!\n";} print "\n\tNote: An Abandon operation is seen as a result of a failed Bind or when an\n"; print "\t LDAP operation response times exceeds the maximum time (passed to the\n"; print "\t operation as a parameter)\n\n"; } ##################################################################################################################### sub verbose_usage() { print "\nVersion: $VERSION\n\nldapconnresponse.pl [options] tracefile\n\n"; print "Purpose: Measure total connection time, from 'New Connection to UnBind'\n"; print " and also measure times between connection start and other LDAP operations.\n\n"; print " .. Options:\n\n\tWhen no switches are supplied statistics are reported.\n\n"; print "\t-x\tCSV output\n"; print "\t\tThe CSV column 'New to UnBind' reports total connection time\n\n"; print "\t-d\tTotal connection time is is equal or greater than this x seconds (0 displays all)\n\n"; print "\t-b\tobject RDN (e.g. bsmith or \"\")\n\n"; print "\t-n\tConsecutive delayed connection responses (default 3)\n"; print "\t\ti.e. Based on value '-d', when do we see '-n' consecutive responses?\n\n"; print "\tOptions -d -b [-n] should be used together\n\n"; legend(1); print "\n .. Enable these LDAP Server Screen Options for trace analysis:\n"; print "\t* Critical Error Message\n"; print "\t* Non-critical Error Messages\n"; print "\t* Informational Error Messages\n"; print "\t* Connection Information\n"; print "\t* Additional connection and operation information in (hex format)\n\n"; print " .. Enable these DSTRACE filters:\n"; print "\t+time +tags +ldap\n\n"; exit; } sub usage() { die "\nUsage: ldapconnresponse.pl -x [-d #] [-b object_name] [-n #] tracefile\n\nOr ...\n\nUsage: ldapconnresponse.pl --help\n\n"; }