@@ -29,6 +29,7 @@ public static void TextReport(NetworkTrace Trace)
2929 if ( Program . outputConversationList ) DisplaySucessfulLoginReport ( Trace ) ; // optional section; must be explicitly requested
3030 DisplayResetConnections ( Trace ) ;
3131 DisplayServerClosedConnections ( Trace ) ;
32+ DisplayZeroWindowConnections ( Trace ) ;
3233 DisplayPktmonDrops ( Trace ) ;
3334 DisplayBadConnections ( Trace ) ;
3435 DisplayLoginErrors ( Trace ) ;
@@ -987,6 +988,196 @@ private static void DisplayServerClosedConnections(NetworkTrace Trace)
987988 }
988989 }
989990
991+ private static void DisplayZeroWindowConnections ( NetworkTrace Trace )
992+ {
993+ bool hasError = false ;
994+
995+ long firstTick = 0 ;
996+ long lastTick = 0 ;
997+
998+ if ( Trace . frames != null && Trace . frames . Count > 0 )
999+ {
1000+ firstTick = ( ( FrameData ) Trace . frames [ 0 ] ) . ticks ;
1001+ lastTick = ( ( FrameData ) Trace . frames [ Trace . frames . Count - 1 ] ) . ticks ;
1002+ }
1003+
1004+ foreach ( SQLServer s in Trace . sqlServers )
1005+ {
1006+ if ( s . hasZeroWindow )
1007+ {
1008+ hasError = true ;
1009+ List < ZeroWindowData > ZeroWindowRecords = new List < ZeroWindowData > ( ) ;
1010+
1011+ // initialize graph object
1012+ TextGraph g = new TextGraph ( ) ;
1013+ g . startTime = new DateTime ( firstTick ) ;
1014+ g . endTime = new DateTime ( lastTick ) ;
1015+ g . SetGraphWidth ( 150 ) ;
1016+ g . fAbsoluteScale = true ;
1017+ g . SetCutoffValues ( 1 , 3 , 9 , 27 , 81 ) ;
1018+
1019+ string sqlIP = ( s . isIPV6 ) ? utility . FormatIPV6Address ( s . sqlIPHi , s . sqlIPLo ) : utility . FormatIPV4Address ( s . sqlIP ) ;
1020+
1021+ foreach ( ConversationData c in s . conversations )
1022+ {
1023+ if ( c . hasClientZeroWindow || c . hasServerZeroWindow )
1024+ {
1025+ ZeroWindowData zwd = new ZeroWindowData ( ) ;
1026+
1027+ zwd . clientIP = ( c . isIPV6 ) ? utility . FormatIPV6Address ( c . sourceIPHi , c . sourceIPLo ) : utility . FormatIPV4Address ( c . sourceIP ) ;
1028+ zwd . sourcePort = c . sourcePort ;
1029+ zwd . isIPV6 = c . isIPV6 ;
1030+ zwd . frames = c . frames . Count ;
1031+ zwd . zwFrame = 0 ;
1032+ zwd . zwFile = 0 ;
1033+ zwd . zwFromClient = c . hasClientZeroWindow ;
1034+ zwd . zwFromServer = c . hasServerZeroWindow ;
1035+ zwd . zwCount = c . zeroWindowCount ;
1036+ zwd . firstFile = Trace . files . IndexOf ( ( ( FrameData ) ( c . frames [ 0 ] ) ) . file ) ;
1037+ zwd . lastFile = Trace . files . IndexOf ( ( ( FrameData ) ( c . frames [ c . frames . Count - 1 ] ) ) . file ) ;
1038+ zwd . startOffset = ( ( FrameData ) c . frames [ 0 ] ) . ticks - firstTick ;
1039+ zwd . endTicks = ( ( FrameData ) c . frames [ c . frames . Count - 1 ] ) . ticks ;
1040+ zwd . endOffset = zwd . endTicks - firstTick ;
1041+ zwd . duration = zwd . endOffset - zwd . startOffset ;
1042+ zwd . endFrames = c . GetLastPacketList ( 20 ) ;
1043+
1044+ for ( int i = c . frames . Count - 1 ; i >= 0 ; i -- ) // search for the last Zero Window frame
1045+ {
1046+ FrameData f = ( FrameData ) c . frames [ i ] ;
1047+
1048+ if ( f . isZeroWindowPacket )
1049+ {
1050+ zwd . zwFrame = f . frameNo ;
1051+ zwd . zwFile = Trace . files . IndexOf ( f . file ) ;
1052+ g . AddData ( new DateTime ( f . ticks ) , 1.0 ) ; // for graphing
1053+ break ;
1054+ }
1055+ }
1056+
1057+ ZeroWindowRecords . Add ( zwd ) ;
1058+ }
1059+ }
1060+
1061+ if ( ZeroWindowRecords . Count > 0 )
1062+ {
1063+ Program . logMessage ( "The following conversations with SQL Server " + sqlIP + " on port " + s . sqlPort + " had conversations with a Zero Window record:\r \n " ) ;
1064+ ReportFormatter rf = new ReportFormatter ( ) ;
1065+ switch ( Program . filterFormat )
1066+ {
1067+ case "N" :
1068+ {
1069+ rf . SetColumnNames ( "NETMON Filter (Client conv.):L" , "Files:R" , "ZW File:R" , "ZW Frame:R" , "ZW Count:R" , "ZW Client:R" , "ZW Server:R" , "Start Offset:R" , "End Offset:R" , "End Time:R" , "Frames:R" , "Duration:R" , "End Frames:L" ) ;
1070+ break ;
1071+ }
1072+ case "W" :
1073+ {
1074+ rf . SetColumnNames ( "WireShark Filter (Client conv.):L" , "Files:R" , "ZW File:R" , "ZW Frame:R" , "ZW Count:R" , "ZW Client:R" , "ZW Server:R" , "Start Offset:R" , "End Offset:R" , "End Time:R" , "Frames:R" , "Duration:R" , "End Frames:L" ) ;
1075+ break ;
1076+ }
1077+ default :
1078+ {
1079+ rf . SetColumnNames ( "Client Address:L" , "Port:R" , "Files:R" , "ZW File:R" , "ZW Frame:R" , "ZW Count:R" , "ZW Client:R" , "ZW Server:R" , "Start Offset:R" , "End Offset:R" , "End Time:R" , "Frames:R" , "Duration:R" , "End Frames:L" ) ;
1080+ break ;
1081+ }
1082+ }
1083+
1084+ var OrderedRows = from row in ZeroWindowRecords orderby row . endOffset ascending select row ;
1085+
1086+ foreach ( var row in OrderedRows )
1087+ {
1088+ switch ( Program . filterFormat )
1089+ {
1090+ case "N" : // list client IP and port as a NETMON filter string
1091+ {
1092+ rf . SetcolumnData ( ( row . isIPV6 ? "IPV6" : "IPV4" ) + ".Address==" + row . clientIP + " and tcp.port==" + row . sourcePort . ToString ( ) ,
1093+ ( row . firstFile == row . lastFile ) ? row . firstFile . ToString ( ) : row . firstFile + "-" + row . lastFile ,
1094+ row . zwFile . ToString ( ) ,
1095+ row . zwFrame . ToString ( ) ,
1096+ row . zwCount . ToString ( ) ,
1097+ ( row . zwFromClient ? "Y" : "" ) ,
1098+ ( row . zwFromServer ? "Y" : "" ) ,
1099+ ( row . startOffset / utility . TICKS_PER_SECOND ) . ToString ( "0.000000" ) ,
1100+ ( row . endOffset / utility . TICKS_PER_SECOND ) . ToString ( "0.000000" ) ,
1101+ new DateTime ( row . endTicks ) . ToString ( utility . TIME_FORMAT ) ,
1102+ row . frames . ToString ( ) ,
1103+ ( row . duration / utility . TICKS_PER_SECOND ) . ToString ( "0.000000" ) ,
1104+ row . endFrames ) ;
1105+ break ;
1106+ }
1107+ case "W" : // list client IP and port as a WireShark filter string
1108+ {
1109+ rf . SetcolumnData ( ( row . isIPV6 ? "ipv6" : "ip" ) + ".addr==" + row . clientIP + " and tcp.port==" + row . sourcePort . ToString ( ) ,
1110+ ( row . firstFile == row . lastFile ) ? row . firstFile . ToString ( ) : row . firstFile + "-" + row . lastFile ,
1111+ row . zwFile . ToString ( ) ,
1112+ row . zwFrame . ToString ( ) ,
1113+ row . zwCount . ToString ( ) ,
1114+ ( row . zwFromClient ? "Y" : "" ) ,
1115+ ( row . zwFromServer ? "Y" : "" ) ,
1116+ ( row . startOffset / utility . TICKS_PER_SECOND ) . ToString ( "0.000000" ) ,
1117+ ( row . endOffset / utility . TICKS_PER_SECOND ) . ToString ( "0.000000" ) ,
1118+ new DateTime ( row . endTicks ) . ToString ( utility . TIME_FORMAT ) ,
1119+ row . frames . ToString ( ) ,
1120+ ( row . duration / utility . TICKS_PER_SECOND ) . ToString ( "0.000000" ) ,
1121+ row . endFrames ) ;
1122+ break ;
1123+ }
1124+ default : // list client IP and port as separate columns
1125+ {
1126+ rf . SetcolumnData ( row . clientIP ,
1127+ row . sourcePort . ToString ( ) ,
1128+ ( row . firstFile == row . lastFile ) ? row . firstFile . ToString ( ) : row . firstFile + "-" + row . lastFile ,
1129+ row . zwFile . ToString ( ) ,
1130+ row . zwFrame . ToString ( ) ,
1131+ row . zwCount . ToString ( ) ,
1132+ ( row . zwFromClient ? "Y" : "" ) ,
1133+ ( row . zwFromServer ? "Y" : "" ) ,
1134+ ( row . startOffset / utility . TICKS_PER_SECOND ) . ToString ( "0.000000" ) ,
1135+ ( row . endOffset / utility . TICKS_PER_SECOND ) . ToString ( "0.000000" ) ,
1136+ new DateTime ( row . endTicks ) . ToString ( utility . TIME_FORMAT ) ,
1137+ row . frames . ToString ( ) ,
1138+ ( row . duration / utility . TICKS_PER_SECOND ) . ToString ( "0.000000" ) ,
1139+ row . endFrames ) ;
1140+ break ;
1141+ }
1142+ }
1143+ }
1144+
1145+ Program . logMessage ( rf . GetHeaderText ( ) ) ;
1146+ Program . logMessage ( rf . GetSeparatorText ( ) ) ;
1147+
1148+ for ( int i = 0 ; i < rf . GetRowCount ( ) ; i ++ )
1149+ {
1150+ Program . logMessage ( rf . GetDataText ( i ) ) ;
1151+ }
1152+
1153+ Program . logMessage ( ) ;
1154+
1155+ //
1156+ // Display graph
1157+ //
1158+
1159+ Program . logMessage ( " Distribution of Zero-Window conversations." ) ;
1160+ Program . logMessage ( ) ;
1161+ g . ProcessData ( ) ;
1162+ Program . logMessage ( " " + g . GetLine ( 0 ) ) ;
1163+ Program . logMessage ( " " + g . GetLine ( 1 ) ) ;
1164+ Program . logMessage ( " " + g . GetLine ( 2 ) ) ;
1165+ Program . logMessage ( " " + g . GetLine ( 3 ) ) ;
1166+ Program . logMessage ( " " + g . GetLine ( 4 ) ) ;
1167+ Program . logMessage ( " " + g . GetLine ( 5 ) ) ;
1168+
1169+ Program . logMessage ( ) ;
1170+ }
1171+ }
1172+ }
1173+
1174+ if ( hasError == false )
1175+ {
1176+ Program . logMessage ( "No Zero-Window SQL conversations found." ) ;
1177+ Program . logMessage ( ) ;
1178+ }
1179+ }
1180+
9901181
9911182 private static void DisplayPktmonDrops ( NetworkTrace Trace )
9921183 {
@@ -3517,7 +3708,7 @@ private static void DisplayFooter()
35173708
35183709 private static void OutputStats ( NetworkTrace Trace )
35193710 {
3520- Program . logStat ( @"SourceIP,SourcePort,DestIP,DestPort,IPVersion,Protocol,Syn,Fin,Reset,AckSynDelayms,Retransmit,ClientDup,ServerDup,KeepAlive,Integrated Login,NTLM,Login7,Encrypted,Mars,PacketVisualization,Pktmon,MaxPktmonDelay,PktmonDrop,PktmonDropReason,MaxPayloadSize,PayloadSizeLimit,Frames,Bytes,SentBytes,ReceivedBytes,Bytes/Sec,StartFile,EndFile,StartTime,EndTime,Duration,ClientTTL,ClientLowHops,ServerTTL,ServerLowHops,ConnectionID,ServerName,InstOpt,ServerVersion,DatabaseName,ServerTDSVersion,ClientTDSVersion,ServerTLSVersion,ClientTLSVersion,RedirSrv,RedirPort,Error,ErrorState,ErrorMessage," ) ;
3711+ Program . logStat ( @"SourceIP,SourcePort,DestIP,DestPort,IPVersion,Protocol,Syn,Fin,Reset,ZeroWindow, AckSynDelayms,Retransmit,ClientDup,ServerDup,KeepAlive,Integrated Login,NTLM,Login7,Encrypted,Mars,PacketVisualization,Pktmon,MaxPktmonDelay,PktmonDrop,PktmonDropReason,MaxPayloadSize,PayloadSizeLimit,Frames,Bytes,SentBytes,ReceivedBytes,Bytes/Sec,StartFile,EndFile,StartTime,EndTime,Duration,ClientTTL,ClientLowHops,ServerTTL,ServerLowHops,ConnectionID,ServerName,InstOpt,ServerVersion,DatabaseName,ServerTDSVersion,ClientTDSVersion,ServerTLSVersion,ClientTLSVersion,RedirSrv,RedirPort,Error,ErrorState,ErrorMessage," ) ;
35213712
35223713 long traceFirstTick = 0 ;
35233714 if ( Trace . frames != null && Trace . frames . Count > 0 )
@@ -3551,6 +3742,7 @@ private static void OutputStats(NetworkTrace Trace)
35513742 c . synCount + "," +
35523743 c . finCount + "," +
35533744 c . resetCount + "," +
3745+ ( c . hasClientZeroWindow || c . hasServerZeroWindow ? "Y" : "" ) + "," +
35543746 ( c . isUDP || c . ackSynTime == 0 ? "" : ( ( int ) ( c . LoginDelay ( "AS" , firstTick ) / utility . TICKS_PER_MILLISECOND ) ) . ToString ( ) ) + "," +
35553747 c . rawRetransmits + "," +
35563748 c . duplicateClientPackets + "," +
0 commit comments