windows-nt/Source/XPSP1/NT/net/tcpip/driver/kdext/tcpext.c
2020-09-26 16:20:57 +08:00

2385 lines
58 KiB
C

#include "precomp.h"
#pragma hdrstop
#include <tdint.h>
#include <tcp.h>
#include <tcpconn.h>
#include <addr.h>
#include <udp.h>
#include <raw.h>
#include <winsock.h>
#include <tcb.h>
//#define CONN_INDEX(c) ((c) & 0xffffff)
//#define CONN_INST(c) ((uchar)((c) >> 24))
FLAG_INFO FlagsTcb[] =
{
{ WINDOW_SET, "Window_Set" },
{ CLIENT_OPTIONS, "Client_Options" },
{ CONN_ACCEPTED, "Connection_Accepted" },
{ ACTIVE_OPEN, "Active_Open" },
{ DISC_NOTIFIED, "Disc_Notified" },
{ IN_DELAY_Q, "In_Delay_Q" },
{ RCV_CMPLTING, "Receives_Completing" },
{ IN_RCV_IND, "In_Receive_Indication" },
{ NEED_RCV_CMPLT, "Need_To_Have_Rcvs_Completed" },
{ NEED_ACK, "Need_To_Send_Ack" },
{ NEED_OUTPUT, "Need_To_Output" },
{ ACK_DELAYED, "Delayed_Ack" },
{ PMTU_BH_PROBE, "PMTU_BH_Probe" },
{ BSD_URGENT, "BSD_Urgent" },
{ IN_DELIV_URG, "In_Deliver_Urgent" },
{ URG_VALID, "Urgent_Valid" },
{ FIN_NEEDED, "Fin_Needed" },
{ NAGLING, "Nagling" },
{ IN_TCP_SEND, "In_Tcp_Send" },
{ FLOW_CNTLD, "Flow_Controlled" },
{ DISC_PENDING, "Disconnect_Pending" },
{ TW_PENDING, "Timed_Wait_Pending" },
{ FORCE_OUTPUT, "Force_Output" },
{ SEND_AFTER_RCV, "Send_After_Receive" },
{ GC_PENDING, "Graceful_Close_Pending" },
{ KEEPALIVE, "KeepAlive" },
{ URG_INLINE, "Urgent_Inline" },
{ FIN_OUTSTANDING, "Fin_Outstanding" },
{ FIN_SENT, "Fin_Sent" },
{ NEED_RST, "Need_Rst" },
{ IN_TCB_TABLE, "In_Tcb_Table" },
{ IN_TWTCB_TABLE, "IN_TWTCB_TABLE" },
{ IN_TWQUEUE, "IN_TWQUEUE" },
{ 0, NULL }
};
FLAG_INFO FlagsFastChk[] =
{
{ TCP_FLAG_SLOW, "Need_Slow_Path" },
{ TCP_FLAG_IN_RCV, "In_Receive_Path" },
{ TCP_FLAG_FASTREC, "FastXmit_In_Progress" },
{ 0, NULL }
};
FLAG_INFO FlagsAO[] =
{
{ AO_RAW_FLAG, "Raw" },
{ AO_DHCP_FLAG, "DHCP" },
{ AO_VALID_FLAG, "Valid" },
{ AO_BUSY_FLAG, "Busy" },
{ AO_OOR_FLAG, "Out_of_Resources" },
{ AO_QUEUED_FLAG, "On_PendingQ" },
{ AO_XSUM_FLAG, "Use_Xsums" },
{ AO_SEND_FLAG, "Send_Pending" },
{ AO_OPTIONS_FLAG, "Options_Pending" },
{ AO_DELETE_FLAG, "Delete_Pending" },
{ AO_BROADCAST_FLAG ,"BCast_Enabled" },
{ AO_CONNUDP_FLAG, "Connected_UDP" },
{ 0, NULL }
};
ENUM_INFO StateTcb[] =
{
{ TCB_CLOSED, "Closed" },
{ TCB_LISTEN, "Listening" },
{ TCB_SYN_SENT, "Syn_Sent" },
{ TCB_SYN_RCVD, "Syn_Received" },
{ TCB_ESTAB, "Established" },
{ TCB_FIN_WAIT1, "Fin_Wait_1" },
{ TCB_FIN_WAIT2, "Fin_Wait_2" },
{ TCB_CLOSE_WAIT, "Close_Wait" },
{ TCB_CLOSING, "Closing" },
{ TCB_LAST_ACK, "Last_Ack" },
{ TCB_TIME_WAIT, "Time_Wait" },
{ 0, NULL }
};
ENUM_INFO CloseReason[] =
{
{ TCB_CLOSE_RST, "RST_Received" },
{ TCB_CLOSE_ABORTED, "Local_Abort" },
{ TCB_CLOSE_TIMEOUT, "Timed_Out" },
{ TCB_CLOSE_REFUSED, "Refused" },
{ TCB_CLOSE_UNREACH, "Dest_Unreachable" },
{ TCB_CLOSE_SUCCESS, "Sucessful_Close" },
{ 0, NULL }
};
ENUM_INFO FsContext2[] =
{
{ TDI_TRANSPORT_ADDRESS_FILE, "Transport_Address" },
{ TDI_CONNECTION_FILE, "Connection" },
{ TDI_CONTROL_CHANNEL_FILE, "Control_Channel" },
{ 0, NULL }
};
ENUM_INFO Prot[] =
{
{ PROTOCOL_UDP, "Udp" },
{ PROTOCOL_TCP, "Tcp" },
{ PROTOCOL_RAW, "Raw" },
{ 0, NULL }
};
VOID
DumpTcpTCB(
ULONG TcbAddr,
VERBOSITY Verbosity
);
VOID
SearchTCB(
ULONG addressToSearch,
VERBOSITY Verbosity
);
VOID
DumpTcpConn(
ULONG TcpConnAddr,
VERBOSITY Verbosity
);
VOID
DumpTcpConnBlock
(
ULONG TcpConnBlockAddr,
VERBOSITY Verbosity
);
VOID
DumpTcpAO(
ULONG TcpAOAddr,
VERBOSITY Verbosity
);
VOID
Tcptcbtable(
VERBOSITY Verbosity
);
VOID
syntcbtable(
VERBOSITY Verbosity
);
VOID
Tcptwtcbtable(
VERBOSITY Verbosity
);
VOID
DumpTcpConnTable
(
VERBOSITY Verbosity
);
VOID
TcpConnTableStats
(
VERBOSITY Verbosity
);
VOID
TcpAOTableStats
(
VERBOSITY Verbosity
);
VOID
TcpTwqStats
(
VERBOSITY Verbosity
);
VOID
DumpIrp(
PVOID IrpToDump,
BOOLEAN FullOutput
);
DECLARE_API( irp )
/*++
Routine Description:
Dumps the specified Irp
Arguments:
args - Address
Return Value:
None
--*/
{
ULONG irpToDump;
char buf[128];
buf[0] = '\0';
if (*args) {
sscanf(args, "%lx %s", &irpToDump, buf);
DumpIrp((PUCHAR)irpToDump, (BOOLEAN) (buf[0] != '\0'));
}
}
VOID
DumpTcpIrp(
ULONG _objAddr
);
DECLARE_API( tcpfile )
/*++
Routine Description:
Dumps the specified Irp
Arguments:
args - Address
Return Value:
None
--*/
{
ULONG irpToDump;
if (*args) {
sscanf(args, "%lx", &irpToDump);
DumpTcpIrp(irpToDump);
}
}
DECLARE_API( tcb )
{
ULONG addressToDump = 0;
ULONG result;
if ( *args ) {
sscanf(args, "%lx", &addressToDump);
}
DumpTcpTCB( addressToDump, VERBOSITY_NORMAL );
}
DECLARE_API( tcbsrch )
{
ULONG addressToSearch = 0;
ULONG result;
if ( *args ) {
sscanf(args, "%lx", &addressToSearch);
}
SearchTCB( addressToSearch, VERBOSITY_NORMAL );
}
DECLARE_API( tcpconntable )
{
char buf[128];
buf[0] = '\0';
if ( *args ) {
sscanf(args, "%s", buf);
}
if (buf[0] == '\0') {
DumpTcpConnTable( VERBOSITY_NORMAL );
} else {
DumpTcpConnTable( VERBOSITY_FULL );
}
}
DECLARE_API( tcpconnstats )
{
TcpConnTableStats( VERBOSITY_NORMAL );
}
DECLARE_API( tcbtable )
{
char buf[128];
buf[0] = '\0';
if ( *args ) {
sscanf(args, "%s", buf);
}
if (buf[0] == '\0') {
Tcptcbtable( VERBOSITY_NORMAL );
} else {
Tcptcbtable( VERBOSITY_FULL );
}
}
DECLARE_API( syntable )
{
char buf[128];
buf[0] = '\0';
if ( *args ) {
sscanf(args, "%s", buf);
}
if (buf[0] == '\0') {
syntcbtable( VERBOSITY_NORMAL );
} else {
syntcbtable( VERBOSITY_FULL );
}
}
DECLARE_API( twtcbtable )
{
char buf[128];
buf[0] = '\0';
if ( *args ) {
sscanf(args, "%s", buf);
}
if (buf[0] == '\0') {
Tcptwtcbtable( VERBOSITY_NORMAL );
} else {
Tcptwtcbtable( VERBOSITY_FULL );
}
}
DECLARE_API( tcpaostats )
{
TcpAOTableStats( VERBOSITY_NORMAL );
}
DECLARE_API( tcptwqstats )
{
TcpTwqStats( VERBOSITY_NORMAL );
}
DECLARE_API( tcpconn )
{
ULONG addressToDump = 0;
ULONG result;
char buf[128];
buf[0] = '\0';
if ( *args ) {
sscanf(args, "%lx %s", &addressToDump, buf);
}
if (buf[0] == '\0') {
DumpTcpConn( addressToDump, VERBOSITY_NORMAL );
} else {
DumpTcpConn( addressToDump, VERBOSITY_FULL );
}
}
DECLARE_API( tcpconnblock )
{
ULONG addressToDump = 0;
ULONG result;
char buf[128];
buf[0] = '\0';
if ( *args ) {
sscanf(args, "%lx %s", &addressToDump, buf);
}
if (buf[0] == '\0') {
DumpTcpConnBlock( addressToDump, VERBOSITY_NORMAL );
} else {
DumpTcpConnBlock( addressToDump, VERBOSITY_FULL );
}
}
DECLARE_API( ao )
{
ULONG addressToDump = 0;
ULONG result;
if ( *args ) {
sscanf(args, "%lx", &addressToDump);
}
DumpTcpAO( addressToDump, VERBOSITY_NORMAL );
}
#ifdef _obj
# undef _obj
# undef _objAddr
# undef _objType
# undef _objTypeName
#endif
#define _obj Tcb
#define _objAddr TcbToDump
#define _objType TCB
#define _objTypeName "TCB"
VOID
DumpTcpTCB
(
ULONG _objAddr,
VERBOSITY Verbosity
)
/*++
Routine Description:
Dumps the fields of the specified DEVICE_CONTEXT structure
Arguments:
DeviceToDump - The device context object to display
Full - Display a partial listing if 0, full listing otherwise.
Return Value:
None
--*/
{
_objType _obj;
ULONG result;
unsigned int index;
BOOL bActive;
if ( !ReadMemory( _objAddr,
&_obj,
sizeof( _obj ),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", _objAddr, _objTypeName );
return;
}
#if DBG
CHECK_SIGNATURE( tcb_sig, tcb_signature );
#endif
if ( Verbosity == VERBOSITY_ONE_LINER )
{
dprintf( "NOT IMPLEMENTED" );
return;
}
dprintf( "%s @ %08lx\n", _objTypeName, _objAddr );
PrintStartStruct();
PrintFieldName( "tcb_next" );
dprint_addr_list( ( ULONG )_obj.tcb_next,
FIELD_OFFSET( TCB, tcb_next ));
PrintLock( tcb_lock );
PrintULong( tcb_senduna );
PrintULong( tcb_sendnext );
PrintULong( tcb_sendmax );
PrintULong( tcb_sendwin );
PrintULong( tcb_unacked );
PrintULong( tcb_maxwin );
PrintULong( tcb_cwin );
PrintULong( tcb_ssthresh );
PrintULong( tcb_phxsum );
PrintPtr( tcb_cursend );
PrintPtr( tcb_sendbuf );
PrintULong( tcb_sendofs );
PrintULong( tcb_sendsize );
PrintLLTcp( tcb_sendq );
PrintULong( tcb_rcvnext );
PrintULong( tcb_rcvwin );
PrintULong( tcb_sendwl1 );
PrintULong( tcb_sendwl2 );
PrintPtr( tcb_currcv );
PrintULong( tcb_indicated );
PrintFlags( tcb_flags, FlagsTcb );
PrintFlags( tcb_fastchk, FlagsFastChk );
PrintSymbolPtr( tcb_rcvhndlr );
PrintIPAddress( tcb_daddr );
PrintIPAddress( tcb_saddr );
PrintHTONUShort( tcb_dport );
PrintHTONUShort( tcb_sport );
#if TRACE_EVENT
PrintPtr( tcb_cpcontext ); // CP HOOK context.
#endif
PrintUShort( tcb_mss );
PrintUShort( tcb_rexmit );
PrintULong( tcb_refcnt );
PrintULong( tcb_rttseq );
PrintUShort( tcb_smrtt );
PrintUShort( tcb_delta );
PrintUShort( tcb_remmss );
PrintUChar( tcb_slowcount );
PrintXEnum( tcb_state, StateTcb );
PrintUChar( tcb_rexmitcnt );
PrintUChar( tcb_pending );
PrintUChar( tcb_kacount );
PrintXULong( tcb_error );
PrintULong( tcb_rtt );
PrintULong( tcb_defaultwin );
PrintPtr( tcb_raq );
PrintPtr( tcb_rcvhead );
PrintPtr( tcb_rcvtail );
PrintULong( tcb_pendingcnt );
PrintPtr( tcb_pendhead );
PrintPtr( tcb_pendtail );
PrintPtr( tcb_connreq );
PrintPtr( tcb_conncontext );
PrintULong( tcb_bcountlow );
PrintULong( tcb_bcounthi );
PrintULong( tcb_totaltime );
PrintPtr( tcb_aonext );
PrintPtr( tcb_conn );
PrintLLTcp( tcb_delayq );
PrintXEnum( tcb_closereason, CloseReason );
PrintUChar( tcb_bhprobecnt );
PrintSymbolPtr( tcb_rcvind );
PrintPtr( tcb_ricontext );
PrintPtr( tcb_opt.ioi_options );
PrintIPAddress( tcb_opt.ioi_addr );
PrintUChar( tcb_opt.ioi_optlength );
PrintUChar( tcb_opt.ioi_ttl );
PrintUChar( tcb_opt.ioi_tos );
PrintUChar( tcb_opt.ioi_flags );
PrintUChar( tcb_opt.ioi_hdrincl );
PrintULong( tcb_opt.ioi_GPCHandle );
PrintULong( tcb_opt.ioi_uni );
PrintULong( tcb_opt.ioi_TcpChksum );
PrintULong( tcb_opt.ioi_UdpChksum );
PrintPtr( tcb_rce );
PrintPtr( tcb_discwait );
PrintPtr( tcb_exprcv );
PrintPtr( tcb_urgpending );
PrintULong( tcb_urgcnt );
PrintULong( tcb_urgind );
PrintULong( tcb_urgstart );
PrintULong( tcb_urgend );
PrintULong( tcb_walkcount );
PrintLLTcp( tcb_TWQueue ); // Place to hang all the timed_waits
PrintUShort( tcb_dup ); // For Fast recovery algorithm
PrintUShort( tcb_force ); // Force next send after fast send
PrintULong( tcb_tcpopts ); // rfc 1323 and 2018 options holder
PrintPtr( tcb_SackBlock ); // Sacks which needs to be sent
PrintPtr( tcb_SackRcvd ); // Sacks which needs to be proces
PrintUShort( tcb_sndwinscale ); // send window scale
PrintUShort( tcb_rcvwinscale ); // receive window scale
PrintULong( tcb_tsrecent ); // time stamp recent
PrintULong( tcb_lastack ); // ack number in the last segment sent
PrintULong( tcb_tsupdatetime ); // Time when tsrecent was updated
// used for invalidating TS
PrintPtr( tcb_chainedrcvind ); //for chained receives
PrintPtr( tcb_chainedrcvcontext );
PrintULong( tcb_delackticks );
PrintULong( tcb_GPCCachedIF);
PrintULong( tcb_GPCCachedLink);
PrintPtr( tcb_GPCCachedRTE );
#if DBG
PrintULong( tcb_LargeSend );
#endif
PrintULong( tcb_moreflag );
PrintULong( tcb_partition );
PrintXULong( tcb_connid );
#if ACK_DEBUG
PrintULong( tcb_history_index );
for (index = 0; index < NUM_ACK_HISTORY_ITEMS; index++) {
dprintf("[%2i] seq:%lu unacked:%lu\n",
index,
Tcb.tcb_ack_history[index].sequence,
Tcb.tcb_ack_history[index].unacked);
}
#endif // ACK_DEBUG
#if REFERENCE_DEBUG
PrintULong ( tcb_refhistory_index );
for (index = 0; index < MAX_REFERENCE_HISTORY; index++) {
if (index == _obj.tcb_refhistory_index) {
dprintf( "*");
}
dprintf( "[%2d]\t: Ref %d File ", index, _obj.tcb_refhistory[index].Count );
dprint_ansi_string( _obj.tcb_refhistory[index].File );
dprintf( ",%d Caller ", _obj.tcb_refhistory[index].Line );
dprintSymbolPtr( (_obj.tcb_refhistory[index].Caller), EOL );
}
#endif // REFERENCE_DEBUG
PrintEndStruct();
}
#ifdef _obj
# undef _obj
# undef _objAddr
# undef _objType
# undef _objTypeName
#endif
#define _obj TcpConn
#define _objAddr TcpConnToDump
#define _objType TCPConn
#define _objTypeName "TCPConn"
VOID
DumpTcpConn
(
ULONG _objAddr,
VERBOSITY Verbosity
)
/*++
Routine Description:
Dumps the fields of the specified DEVICE_CONTEXT structure
Arguments:
DeviceToDump - The device context object to display
Full - Display a partial listing if 0, full listing otherwise.
Return Value:
None
--*/
{
_objType _obj;
ULONG result;
unsigned int index;
BOOL bActive;
if ( !ReadMemory( _objAddr,
&_obj,
sizeof( _obj ),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", _objAddr, _objTypeName );
return;
}
#if DBG
CHECK_SIGNATURE( tc_sig, tc_signature );
#endif
if ( Verbosity == VERBOSITY_ONE_LINER )
{
dprintf( "NOT IMPLEMENTED" );
return;
}
dprintf( "%s @ %08lx\n", _objTypeName, _objAddr );
PrintStartStruct();
PrintLLTcp( tc_q );
PrintPtr( tc_tcb );
PrintPtr( tc_ao );
PrintUChar( tc_inst );
PrintUChar( tc_flags );
PrintUShort( tc_refcnt );
PrintPtr( tc_context );
PrintSymbolPtr( tc_rtn );
PrintPtr( tc_rtncontext );
PrintSymbolPtr( tc_donertn );
PrintFlags( tc_tcbflags, FlagsTcb );
PrintULong( tc_tcbkatime );
PrintULong( tc_tcbkainterval );
PrintULong( tc_window );
PrintPtr( tc_LastTCB );
PrintPtr( tc_ConnBlock );
PrintXULong( tc_connid );
PrintEndStruct();
if (Verbosity == VERBOSITY_FULL) {
if (_obj.tc_tcb) {
DumpTcpTCB( (ULONG)_obj.tc_tcb, VERBOSITY_NORMAL );
}
if (_obj.tc_ao) {
DumpTcpAO( (ULONG)_obj.tc_ao, VERBOSITY_NORMAL );
}
}
}
#ifdef _obj
# undef _obj
# undef _objAddr
# undef _objType
# undef _objTypeName
#endif
#define _obj AddressObject
#define _objAddr AddrObjToDump
#define _objType AddrObj
#define _objTypeName "AddrObj"
VOID
DumpTcpAO
(
ULONG _objAddr,
VERBOSITY Verbosity
)
/*++
Routine Description:
Dumps the fields of the specified DEVICE_CONTEXT structure
Arguments:
DeviceToDump - The device context object to display
Full - Display a partial listing if 0, full listing otherwise.
Return Value:
None
--*/
{
_objType _obj;
ULONG result;
unsigned int index;
BOOL bActive;
if ( !ReadMemory( _objAddr,
&_obj,
sizeof( _obj ),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", _objAddr, _objTypeName );
return;
}
#if DBG
CHECK_SIGNATURE( ao_sig, ao_signature );
#endif
if ( Verbosity == VERBOSITY_ONE_LINER )
{
dprintf( "NOT IMPLEMENTED" );
return;
}
dprintf( "%s @ %08lx\n", _objTypeName, _objAddr );
PrintStartStruct();
PrintPtr( ao_next );
PrintLock( ao_lock );
PrintPtr( ao_request );
PrintLLTcp( ao_sendq );
PrintLLTcp( ao_pendq );
PrintLLTcp( ao_rcvq );
PrintPtr( ao_opt.ioi_options );
PrintIPAddress( ao_opt.ioi_addr );
PrintUChar( ao_opt.ioi_optlength );
PrintUChar( ao_opt.ioi_ttl );
PrintUChar( ao_opt.ioi_tos );
PrintUChar( ao_opt.ioi_flags );
PrintUChar( ao_opt.ioi_hdrincl );
PrintULong( ao_opt.ioi_GPCHandle );
PrintULong( ao_opt.ioi_uni );
PrintULong( ao_opt.ioi_TcpChksum );
PrintULong( ao_opt.ioi_UdpChksum );
PrintIPAddress( ao_addr );
PrintHTONUShort( ao_port );
PrintFlags( ao_flags, FlagsAO );
PrintXEnum( ao_prot, Prot );
PrintULong( ao_listencnt );
PrintUShort( ao_usecnt );
PrintUShort ( ao_mcast_loop );
PrintUShort( ao_rcvall );
PrintUShort( ao_rcvall_mcast );
PrintPtr( ao_mcastopt.ioi_options );
PrintIPAddress( ao_mcastopt.ioi_addr );
PrintUChar( ao_mcastopt.ioi_optlength );
PrintUChar( ao_mcastopt.ioi_ttl );
PrintUChar( ao_mcastopt.ioi_tos );
PrintUChar( ao_mcastopt.ioi_flags );
PrintIPAddress( ao_mcastaddr );
PrintLLTcp( ao_activeq );
PrintLLTcp( ao_idleq );
PrintLLTcp( ao_listenq );
PrintCTEEvent( ao_event );
PrintSymbolPtr( ao_connect );
PrintPtr( ao_conncontext );
PrintSymbolPtr( ao_disconnect );
PrintPtr( ao_disconncontext );
PrintSymbolPtr( ao_error );
PrintPtr( ao_errcontext );
PrintSymbolPtr( ao_rcv );
PrintPtr( ao_rcvcontext );
PrintSymbolPtr( ao_rcvdg );
PrintPtr( ao_rcvdgcontext );
PrintSymbolPtr( ao_exprcv );
PrintPtr( ao_exprcvcontext );
PrintPtr( ao_mcastlist );
PrintSymbolPtr( ao_dgsend );
PrintUShort( ao_maxdgsize );
PrintSymbolPtr( ao_errorex ); // Error event routine.
PrintPtr( ao_errorexcontext ); // Error event context.
// PrintULong( ConnLimitReached ); //set when there are no connections left
PrintSymbolPtr( ao_chainedrcv ); // Chained Receive event handler
PrintPtr( ao_chainedrcvcontext ); // Chained Receive context.
PrintAddr( ao_udpconn );
PrintULong( ao_udpconn.UserDataLength );
PrintPtr( ao_udpconn.UserData );
PrintULong( ao_udpconn.OptionsLength );
PrintPtr( ao_udpconn.Options );
PrintULong( ao_udpconn.RemoteAddressLength );
PrintPtr (ao_udpconn.RemoteAddress );
PrintPtr ( ao_RemoteAddress );
PrintPtr ( ao_Options );
PrintPtr ( ao_rce );
PrintULong( ao_GPCHandle );
PrintULong( ao_GPCCachedIF );
PrintULong( ao_GPCCachedLink );
PrintPtr ( ao_GPCCachedRTE );
PrintIPAddress( ao_rcesrc );
PrintIPAddress( ao_destaddr );
PrintHTONUShort( ao_destport );
PrintULong( ao_promis_ifindex );
PrintUChar( ao_absorb_rtralert );
PrintULong ( ao_bindindex );
PrintEndStruct();
}
#ifdef _obj
# undef _obj
# undef _objAddr
# undef _objType
# undef _objTypeName
#endif
#define _obj TcpConnBlock
#define _objAddr TcpConnBlockToDump
#define _objType TCPConnBlock
#define _objTypeName "TCPConnBlock"
VOID
DumpTcpConnBlock
(
ULONG _objAddr,
VERBOSITY Verbosity
)
{
_objType _obj;
ULONG result;
unsigned int index;
BOOL bActive;
unsigned int count = 0;
if ( !ReadMemory( _objAddr,
&_obj,
sizeof( _obj ),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", _objAddr, _objTypeName );
return;
}
dprintf( "%s @ %08lx\n", _objTypeName, _objAddr );
PrintStartStruct();
PrintULong( cb_freecons );
PrintULong( cb_nextfree );
PrintULong( cb_blockid );
PrintULong( cb_conninst );
PrintAddr( cb_conn );
PrintEndStruct();
for (index=0; index<MAX_CONN_PER_BLOCK; index++) {
if ( _obj.cb_conn[index] != NULL ) {
dprintf(" TCPConn @ %08lx\n", _obj.cb_conn[index] );
if (Verbosity == VERBOSITY_FULL) {
DumpTcpConn( (ULONG)(_obj.cb_conn[index]), VERBOSITY_NORMAL );
}
count++;
}
}
dprintf("\n %d Active TCPConn entries in this block.\n", count);
}
VOID
DumpTcpConnTable
(
VERBOSITY Verbosity
)
{
TCPConnBlock **ConnTableBlock, **PreservedPtr;
ULONG result;
unsigned int index;
unsigned int count = 0;
ULONG TabAddr;
ULONG Tablen;
TabAddr = GetUlongValue( "tcpip!ConnTable" );
Tablen = GetUlongValue( "tcpip!MaxConnBlocks" );
dprintf("Dumping ConnTable @ %08lx - ConnTableSize = %08lx\n",
TabAddr, Tablen );
ConnTableBlock = malloc(sizeof( TCPConn * ) * Tablen);
PreservedPtr = ConnTableBlock;
if (ConnTableBlock == NULL) {
dprintf("malloc failed in DumpTcpConnTable.\n");
return;
}
if ( !ReadMemory( TabAddr,
&ConnTableBlock[0],
(sizeof( TCPConnBlock *) * Tablen),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", TabAddr, "ConnTable" );
free(ConnTableBlock);
return;
}
for (index=0; index<Tablen && !CheckControlC(); index++) {
if ( *ConnTableBlock != NULL ) {
dprintf(" TCPConnBlock @ %08lx\n", *ConnTableBlock );
DumpTcpConnBlock( (ULONG)*ConnTableBlock, VERBOSITY_NORMAL );
count++;
}
ConnTableBlock++;
}
dprintf("\n %d Active TCPConnBlock entries.\n", count);
//free(ConnTable);
free(PreservedPtr);
}
typedef struct ConnStats {
ULONG associated;
ULONG connected;
} ConnStats;
#ifdef _obj
# undef _obj
# undef _objAddr
# undef _objType
# undef _objTypeName
#endif
#define _obj TcpConn
#define _objAddr TcpConnToDump
#define _objType TCPConn
#define _objTypeName "TCPConn"
ULONG
ReadConnInfo
(
ULONG _objAddr
)
{
_objType _obj;
ULONG result;
unsigned int index;
BOOL bActive;
ULONG num=1;
ULONG start=_objAddr;
while (1) {
if ( !ReadMemory( _objAddr,
&_obj,
sizeof( _obj ),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", _objAddr, _objTypeName );
return(num);
}
_objAddr = (ULONG)_obj.tc_q.q_next;
if (_objAddr == start) {
break;
}
num++;
}
return(num);
}
VOID
TcpConnStats
(
ULONG _objAddr,
ConnStats *CS
)
/*++
Routine Description:
Dumps the fields of the specified DEVICE_CONTEXT structure
Arguments:
DeviceToDump - The device context object to display
Full - Display a partial listing if 0, full listing otherwise.
Return Value:
None
--*/
{
_objType _obj;
ULONG result;
unsigned int index;
BOOL bActive;
if ( !ReadMemory( _objAddr,
&_obj,
sizeof( _obj ),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", _objAddr, _objTypeName );
return;
}
#if DBG
CHECK_SIGNATURE( tc_sig, tc_signature );
#endif
if (_obj.tc_tcb) {
CS->connected++;
}
if (_obj.tc_ao) {
CS->associated++;
}
}
#ifdef _obj
# undef _obj
# undef _objAddr
# undef _objType
# undef _objTypeName
#endif
#define _obj TcpConnBlock
#define _objAddr TcpConnBlockToDump
#define _objType TCPConnBlock
#define _objTypeName "TCPConnBlock"
VOID
TcpConnTableStats (
VERBOSITY Verbosity
)
{
TCPConn **ConnTableBlock, **PreservedPtr;
ULONG result;
unsigned int index;
unsigned int count = 0;
ULONG TabAddr;
ULONG Tablen;
ConnStats CS = { 0, 0 };
TabAddr = GetUlongValue( "tcpip!ConnTable" );
Tablen = GetUlongValue( "tcpip!MaxConnBlocks" );
dprintf("Statistics for ConnTable @ %08lx - ConnTableSize = %08lx\n",
TabAddr, Tablen );
ConnTableBlock = malloc(sizeof( TCPConn * ) * Tablen);
PreservedPtr = ConnTableBlock;
if (ConnTableBlock == NULL) {
dprintf("malloc failed in DumpTcpConnTable.\n");
return;
}
if ( !ReadMemory( TabAddr,
&ConnTableBlock[0],
(sizeof( TCPConnBlock *) * Tablen),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", TabAddr, "ConnTable" );
free(PreservedPtr);
return;
}
for (index=0; index<Tablen && !CheckControlC(); index++) {
if ( *ConnTableBlock != NULL ) {
{
ULONG _objAddr;
ULONG result;
unsigned int index;
_objType _obj;
_objAddr = (ULONG) *ConnTableBlock;
if ( !ReadMemory( _objAddr,
&_obj,
sizeof( _obj ),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", _objAddr, _objTypeName );
free(PreservedPtr);
return;
}
for (index=0; index<MAX_CONN_PER_BLOCK; index++) {
if ( _obj.cb_conn[index] != NULL ) {
count++;
TcpConnStats( (ULONG)(_obj.cb_conn[index]), &CS );
}
}
}
}
ConnTableBlock++;
}
dprintf("\n %d Active TCPConn entries.\n", count);
dprintf("\n %d TCPConn entries are associated with AOs.\n", CS.associated);
dprintf("\n %d TCPConn entries are connected.\n", CS.connected);
free(PreservedPtr);
}
VOID Tcptcbtable(
VERBOSITY Verbosity
)
{
UINT i,result;
TCB *CurrentTcb, *NextTcb;
TCB **TCBTable;
USHORT *TcbDepths;
ULONG_PTR TableAddr;
ULONG TableSize;
ULONG TotalTcbs = 0;
ULONG AverageDepth;
ULONG Variance;
ULONG Depth;
ULONG MinDepth = ~0;
ULONG MaxDepth = 0;
ULONG NumberWithZeroDepth = 0;
TableAddr = GetUlongValue( "tcpip!TcbTable" );
TableSize = GetUlongValue( "tcpip!MaxHashTableSize" );
dprintf("Dumping TcbTable @ %08lx - TableSize = 0x%x (%u)\n",
TableAddr, TableSize, TableSize );
TCBTable = malloc(TableSize * sizeof(TCB *));
if (!TCBTable) {
dprintf("malloc failed in DumpTcbTable.\n");
return;
}
// Array of depths we need in order to go back and calculate the
// variance and standard deviation.
//
TcbDepths = malloc(TableSize * sizeof(USHORT));
if (!TcbDepths) {
free (TCBTable);
dprintf("malloc failed in DumpTcbTable.\n");
return;
}
if ( !ReadMemory(TableAddr,
TCBTable,
(sizeof(TCB *) * TableSize),
&result )) {
free (TcbDepths);
free (TCBTable);
dprintf("%08lx: Could not read %s structure.\n", TCBTable, "Tcb" );
return;
}
for (i = 0; i < TableSize && !CheckControlC(); i++) {
CurrentTcb = TCBTable[i];
if (!CurrentTcb)
{
NumberWithZeroDepth++;
}
Depth = 0;
while (CurrentTcb != NULL && !CheckControlC()) {
TotalTcbs++;
Depth++;
if ( !ReadMemory((ULONG)CurrentTcb + FIELD_OFFSET(TCB, tcb_next),
&NextTcb,
sizeof(TCB*), &result )) {
dprintf("%08lx: Could not read %s structure.\n", TCBTable, "TcbObj" );
free (TcbDepths);
free (TCBTable);
return;
}
if (VERBOSITY_FULL == Verbosity) {
TCB Tcb;
if ( !ReadMemory((ULONG)CurrentTcb,
&Tcb,
sizeof(TCB),
&result )) {
dprintf("%08lx: Could not read %s structure.\n", TCBTable, "TcbObj" );
free (TcbDepths);
free (TCBTable);
return;
}
dprintf("[%u] tcb %x :: SA: ", i, CurrentTcb);
dprint_IP_address( (IPAddr) Tcb.tcb_saddr);
dprintf(" DA: ");
dprint_IP_address( (IPAddr) Tcb.tcb_daddr);
dprintf(" SPort: %u Dport: %u ", htons(Tcb.tcb_sport), htons(Tcb.tcb_dport));
dprint_enum_name( (ULONG) Tcb.tcb_state, StateTcb );
dprintf("\n");
}
CurrentTcb = NextTcb;
}
if (Depth)
{
if (Depth > MaxDepth)
{
MaxDepth = Depth;
}
if (Depth < MinDepth)
{
MinDepth = Depth;
}
}
TcbDepths[i] = (USHORT)Depth;
}
AverageDepth = TotalTcbs / TableSize;
Variance = 0;
for (i = 0; i < TableSize; i++) {
SHORT Diff = (SHORT)(TcbDepths[i] - (USHORT)AverageDepth);
Variance += (Diff * Diff);
}
Variance /= (TableSize-1);
dprintf(
"\n"
"%10u total TCBs\n"
"%10u total hash buckets\n"
"%10u should ideally be in each bucket\n"
"%10u Minimum (non-zero) depth\n"
"%10u Maximum depth\n"
"%10u Variance (Standard Deviation = %0.1f)\n"
"%10u on average in the non-empty buckets\n"
"%10u empty hash buckets (%u%% of the hash table is unused)\n",
TotalTcbs,
TableSize,
AverageDepth,
MinDepth,
MaxDepth,
Variance, sqrt(Variance),
TotalTcbs / (TableSize - NumberWithZeroDepth),
NumberWithZeroDepth, (NumberWithZeroDepth * 100) / TableSize
);
free (TcbDepths);
free (TCBTable);
}
VOID syntcbtable(
VERBOSITY Verbosity
)
{
UINT i,result;
Queue *TCBTable;
Queue *Scan;
Queue NextItem;
SYNTCB *CurrentTcb, *NextTcb;
USHORT *TcbDepths;
ULONG_PTR TableAddr;
ULONG TableSize;
ULONG TotalTcbs = 0;
ULONG AverageDepth;
ULONG Variance;
ULONG Depth;
ULONG MinDepth = ~0;
ULONG MaxDepth = 0;
ULONG NumberWithZeroDepth = 0;
ULONG TableBuckets;
TableAddr = GetUlongValue( "tcpip!SynTcbTable" );
TableBuckets = GetUlongValue("tcpip!MaxHashTableSize");
TableSize = TableBuckets * sizeof(Queue);
dprintf("Dumping synTcbTable @ %08lx - TableSize = 0x%x (%u)\n",
TableAddr, TableSize, TableSize );
TCBTable = malloc(TableSize);
if (!TCBTable) {
dprintf("malloc failed in DumpsynTcbTable.\n");
return;
}
// Array of depths we need in order to go back and calculate the
// variance and standard deviation.
//
TcbDepths = malloc(TableSize * sizeof(USHORT));
if (!TcbDepths) {
free (TCBTable);
dprintf("malloc failed in DumpTcbTable.\n");
return;
}
if ( !ReadMemory(TableAddr,
TCBTable,
TableSize,
&result )) {
free (TcbDepths);
free (TCBTable);
dprintf("%08lx: Could not read %s structure.\n", TCBTable, "Tcb" );
return;
}
for (i = 0; i < TableSize && !CheckControlC(); i++) {
dprintf("\r...%d%%", (i * 100) / TableBuckets);
if (TCBTable[i].q_next == (Queue*)(TableAddr + (i * sizeof(Queue))))
{
NumberWithZeroDepth++;
}
Depth = 0;
for (Scan = TCBTable[i].q_next;
Scan != (Queue*)(TableAddr + (i * sizeof(Queue)));
Scan = NextItem.q_next) {
TotalTcbs++;
Depth++;
if (!ReadMemory((ULONG_PTR)Scan, &NextItem, sizeof(Queue), &result)) {
dprintf("%08lx: %d Could not read %s structure.\n", TCBTable, i,"scansyntcb" );
free (TcbDepths);
free (TCBTable);
return;
}
if (VERBOSITY_FULL == Verbosity) {
SYNTCB Tcb;
if (!ReadMemory((ULONG_PTR)Scan - FIELD_OFFSET(SYNTCB, syntcb_link),
&Tcb,
sizeof(SYNTCB),
&result )) {
dprintf("%08lx: Could not read %s structure.\n", TCBTable, "TcbObj" );
free (TcbDepths);
free (TCBTable);
return;
}
dprintf("[%u] tcb %x :: SA: ", i, Tcb);
//dprint_IP_address( (IPAddr) Tcb.tcb_saddr);
dprintf(" DA: ");
dprint_IP_address( (IPAddr) Tcb.syntcb_daddr);
dprintf(" SPort: %u Dport: %u ", htons(Tcb.syntcb_sport), htons(Tcb.syntcb_dport));
dprint_enum_name( (ULONG) Tcb.syntcb_state, StateTcb );
dprintf("\n");
}
}
if (Depth)
{
if (Depth > MaxDepth)
{
MaxDepth = Depth;
}
if (Depth < MinDepth)
{
MinDepth = Depth;
}
}
TcbDepths[i] = (USHORT)Depth;
}
AverageDepth = TotalTcbs / TableSize;
Variance = 0;
for (i = 0; i < TableSize; i++) {
SHORT Diff = (SHORT)(TcbDepths[i] - (USHORT)AverageDepth);
Variance += (Diff * Diff);
}
Variance /= (TableSize-1);
dprintf(
"\n"
"%10u total TCBs\n"
"%10u total hash buckets\n"
"%10u should ideally be in each bucket\n"
"%10u Minimum (non-zero) depth\n"
"%10u Maximum depth\n"
"%10u Variance (Standard Deviation = %0.1f)\n"
"%10u on average in the non-empty buckets\n"
"%10u empty hash buckets (%u%% of the hash table is unused)\n",
TotalTcbs,
TableSize,
AverageDepth,
MinDepth,
MaxDepth,
Variance, sqrt(Variance),
TotalTcbs / (TableSize - NumberWithZeroDepth),
NumberWithZeroDepth, (NumberWithZeroDepth * 100) / TableSize
);
free (TcbDepths);
free (TCBTable);
}
VOID Tcptwtcbtable(
VERBOSITY Verbosity
)
{
UINT i,result;
Queue *Table;
Queue *Scan;
Queue NextItem;
USHORT *Depths;
ULONG_PTR TableAddr;
ULONG TableBuckets;
ULONG TableSize;
ULONG TotalItems = 0;
ULONG AverageDepth;
ULONG Variance;
ULONG Depth;
ULONG MinDepth = ~0;
ULONG MaxDepth = 0;
ULONG NumberWithZeroDepth = 0;
TableAddr = GetUlongValue("tcpip!TWTCBTable");
TableBuckets = GetUlongValue("tcpip!MaxHashTableSize");
TableSize = TableBuckets * sizeof(Queue);
dprintf("Dumping TWTCBTable @ %08x - TableBuckets = 0x%x (%u)\n",
TableAddr, TableBuckets, TableBuckets );
Table = malloc(TableSize);
if (!Table) {
dprintf("malloc failed in DumpTcbTable.\n");
return;
}
// Array of depths we need in order to go back and calculate the
// variance and standard deviation.
//
Depths = malloc(TableBuckets * sizeof(USHORT));
if (!Depths) {
free (Table);
dprintf("malloc failed in DumpTcbTable.\n");
return;
}
if (!ReadMemory(TableAddr, Table, TableSize, &result)) {
free (Depths);
free (Table);
dprintf("%08lx: Could not read TWTCBTable structure.\n", Table);
return;
}
for (i = 0; i < TableBuckets && !CheckControlC(); i++) {
dprintf("\r...%d%%", (i * 100) / TableBuckets);
if (Table[i].q_next == (Queue*)(TableAddr + (i * sizeof(Queue))))
{
NumberWithZeroDepth++;
}
Depth = 0;
for (Scan = Table[i].q_next;
Scan != (Queue*)(TableAddr + (i * sizeof(Queue)));
Scan = NextItem.q_next) {
TotalItems++;
Depth++;
if (!ReadMemory((ULONG_PTR)Scan, &NextItem, sizeof(Queue), &result)) {
dprintf("%08lx: Could not read Queue structure.\n", Table);
free (Depths);
free (Table);
return;
}
if (VERBOSITY_FULL == Verbosity) {
TWTCB Twtcb;
if (!ReadMemory((ULONG_PTR)Scan - FIELD_OFFSET(TWTCB, twtcb_link),
&Twtcb,
sizeof(TWTCB),
&result )) {
dprintf("%08lx: Could not read Twtcb structure.\n", Table);
free (Depths);
free (Table);
return;
}
dprintf("[%u] twtcb %x :: SA: ", i, (ULONG_PTR)Scan - FIELD_OFFSET(TWTCB, twtcb_link));
dprint_IP_address( (IPAddr) Twtcb.twtcb_saddr);
dprintf(" DA: ");
dprint_IP_address( (IPAddr) Twtcb.twtcb_daddr);
dprintf(" SPort: %u Dport: %u\n", htons(Twtcb.twtcb_sport), htons(Twtcb.twtcb_dport));
}
}
if (Depth)
{
if (Depth > MaxDepth)
{
MaxDepth = Depth;
}
if (Depth < MinDepth)
{
MinDepth = Depth;
}
}
Depths[i] = (USHORT)Depth;
}
dprintf("\r...100%%\n");
AverageDepth = TotalItems / TableBuckets;
Variance = 0;
for (i = 0; i < TableBuckets; i++) {
SHORT Diff = (SHORT)(Depths[i] - (USHORT)AverageDepth);
Variance += (Diff * Diff);
}
Variance /= (TableBuckets-1);
dprintf(
"\n"
"%10u total TWTCBs\n"
"%10u total hash buckets\n"
"%10u should ideally be in each bucket\n"
"%10u Minimum (non-zero) depth\n"
"%10u Maximum depth\n"
"%10u Variance (Standard Deviation = %0.1f)\n"
"%10u on average in the non-empty buckets\n"
"%10u empty hash buckets (%u%% of the hash table is unused)\n",
TotalItems,
TableBuckets,
AverageDepth,
MinDepth,
MaxDepth,
Variance, sqrt(Variance),
TotalItems / (TableBuckets - NumberWithZeroDepth),
NumberWithZeroDepth, (NumberWithZeroDepth * 100) / TableBuckets
);
free (Depths);
free (Table);
}
VOID SearchTCB(
ULONG TcbAddr,
VERBOSITY Verbosity
)
{
unsigned int i,j=0,result; // Index variable.
TCB *CurrentTcb; // Current AddrObj being examined.
TCB Tcb; // Current AddrObj being examined.
TCB **TCBTable, **PreservedPtr;
ULONG TableAddr;
ULONG TableSize;
int found = 0;
TCB *PrevTcb;
TableAddr = GetUlongValue( "tcpip!TcbTable" );
TableSize = GetUlongValue( "tcpip!MaxHashTableSize" );
dprintf("Dumping TCbTable @ %08lx - TableSize = %08lx\n",
TableAddr, TableSize );
TCBTable = malloc(sizeof( TCB * ) * TableSize);
PreservedPtr = TCBTable;
if (TCBTable == NULL) {
dprintf("malloc failed in DumpTcbTable.\n");
return;
}
dprintf("Searching for Tcb @ %08lx \n", TcbAddr);
if ( !ReadMemory(TableAddr,
&TCBTable[0],
(sizeof( TCB *) * TableSize),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", TCBTable, "Tcb" );
return;
}
for (i = 0; i < TableSize && !CheckControlC(); i++) {
CurrentTcb = (TCB *)TCBTable[i];
j = 0;
PrevTcb = NULL;
dprintf("Searching in bucket i %d \n", i+1);
while (CurrentTcb != NULL && !CheckControlC()) {
j++;
if ( !ReadMemory((ULONG)CurrentTcb,
&Tcb,
sizeof(TCB),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", TCBTable, "TcbObj" );
return;
}
if (TcbAddr == (ULONG) CurrentTcb) {
found = 1;
dprintf("found tcb %x i %d j %d Prev %x\n", CurrentTcb, i+1, j, PrevTcb);
return;
}
dprintf("still searching j %d Prev %x\n", j, PrevTcb);
PrevTcb = CurrentTcb;
CurrentTcb = Tcb.tcb_next;
}
dprintf("Search completed in bucket i %d \n", i+1);
dprintf("************************ \n", i);
}
if (found == 0)
dprintf("\n Not found TCB entries.\n");
free(PreservedPtr);
}
#define EMPTY ((q).q_next == (q))
VOID
TcpAOTableStats(
VERBOSITY Verbosity
)
{
UINT i,result;
ULONG_PTR TdiErrorHandler;
ULONG valid=0,busy=0,emptylisten=0,emptyactive=0,emptyidle=0;
ULONG pendingque=0,pendingdel=0,netbtaos=0,tcpaos=0;
ULONG numidle, numlisten, numactive;
AddrObj AO;
USHORT *Depths;
ULONG_PTR TableAddr;
ULONG_PTR AOAddress;
ULONG TableBuckets;
ULONG TableSize;
ULONG TotalItems = 0;
ULONG AverageDepth;
ULONG Variance;
ULONG Depth;
ULONG MinDepth = ~0;
ULONG MaxDepth = 0;
ULONG NumberWithZeroDepth = 0;
TdiErrorHandler = GetExpression("netbt!TdiErrorHandler");
TableAddr = GetUlongValue("tcpip!AddrObjTable");
TableBuckets = GetUlongValue("tcpip!AO_TABLE_SIZE");
TableSize = TableBuckets * sizeof(AddrObj*);
dprintf("Statistics for AddrObjTable @ %08x - TableBuckets = 0x%x (%u)\n",
TableAddr, TableBuckets, TableBuckets );
// Array of depths we need in order to go back and calculate the
// variance and standard deviation.
//
Depths = malloc(TableBuckets * sizeof(USHORT));
if (!Depths) {
dprintf("malloc failed in TcpAOTableStats.\n");
return;
}
for (i = 0; i < TableBuckets && !CheckControlC(); i++) {
dprintf("\r...%d%%", (i * 100) / TableSize);
if (!ReadMemory(TableAddr + (i * 4), &AOAddress, sizeof(AddrObj*), &result)) {
dprintf("%08lx: Could not read AddrObj address.\n", TableAddr + (i * 4));
free (Depths);
return;
}
if (!AOAddress) {
NumberWithZeroDepth++;
}
Depth = 0;
while (AOAddress && !CheckControlC()) {
TotalItems++;
Depth++;
if (!ReadMemory(AOAddress, &AO, sizeof(AO), &result)) {
dprintf("%08lx: Could not read AddrObj structure.\n", AOAddress);
free (Depths);
return;
}
if (AO.ao_flags & AO_VALID_FLAG) {
valid++;
if (AO.ao_flags & AO_BUSY_FLAG) {
busy++;
}
if (AO.ao_flags & AO_QUEUED_FLAG) {
pendingque++;
}
if (AO.ao_flags & AO_DELETE_FLAG) {
pendingdel++;
}
if ((ULONG_PTR)AO.ao_error == TdiErrorHandler) {
netbtaos++;
}
if (AO.ao_prot == 6) {
tcpaos++;
}
//numidle = numactive = numlisten = 0;
if ((uint)AO.ao_activeq.q_next == (AOAddress + FIELD_OFFSET(AddrObj, ao_activeq.q_next))) {
emptyactive++;
} else {
//numactive = ReadConnInfo((ULONG )AO.ao_activeq.q_next);
}
if ((uint)AO.ao_idleq.q_next == (AOAddress + FIELD_OFFSET(AddrObj, ao_idleq.q_next))) {
emptyidle++;
} else {
//numidle = ReadConnInfo((ULONG )AO.ao_idleq.q_next);
}
if ((uint)AO.ao_listenq.q_next == (AOAddress + FIELD_OFFSET(AddrObj, ao_listenq.q_next))) {
emptylisten++;
} else {
//numlisten = ReadConnInfo((ULONG )AO.ao_listenq.q_next);
}
//dprintf("%x Connidle %d Conactive %d Connlisten %d loop %d\n",
// AOAddress, numidle, numactive, numlisten,
// (ushort)AO.ao_mcast_loop );
} else {
dprintf(" %x Invalid\n", AOAddress );
}
AOAddress = (ULONG_PTR)AO.ao_next;
}
if (Depth)
{
if (Depth > MaxDepth)
{
MaxDepth = Depth;
}
if (Depth < MinDepth)
{
MinDepth = Depth;
}
}
Depths[i] = (USHORT)Depth;
}
dprintf("\r...100%%\n");
AverageDepth = TotalItems / TableBuckets;
Variance = 0;
for (i = 0; i < TableBuckets; i++) {
SHORT Diff = (SHORT)(Depths[i] - (USHORT)AverageDepth);
Variance += (Diff * Diff);
}
Variance /= (TableBuckets-1);
dprintf(
"\n"
"%10u total Address objects\n"
"%10u total hash buckets\n"
"%10u should ideally be in each bucket\n"
"%10u Minimum (non-zero) depth\n"
"%10u Maximum depth\n"
"%10u Variance (Standard Deviation = %0.1f)\n"
"%10u on average in the non-empty buckets\n"
"%10u empty hash buckets (%u%% of the hash table is unused)\n",
TotalItems,
TableBuckets,
AverageDepth,
MinDepth,
MaxDepth,
Variance, sqrt(Variance),
TotalItems / (TableBuckets - NumberWithZeroDepth),
NumberWithZeroDepth, (NumberWithZeroDepth * 100) / TableBuckets
);
free (Depths);
dprintf("%10u are valid\n", valid);
dprintf("%10u are busy\n", busy);
dprintf("%10u with pending queue on\n", pendingque);
dprintf("%10u with pending delete on\n", pendingdel);
dprintf("%10u with empty active queue\n", emptyactive);
dprintf("%10u with empty idle queues\n", emptyidle);
dprintf("%10u with empty listen queues\n", emptylisten);
dprintf("%10u NETBT AO's\n", netbtaos);
dprintf("%10u TCP AO's\n\n", tcpaos);
}
VOID
TcpTwqStats(
VERBOSITY Verbosity
)
{
int i,j=0,result,sum; // Index variable.
ULONG_PTR TableAddr, TablePtr;
ULONG Tcbnext, Tcb;
TWTCB Tcbstr ;
ULONG Offset;
TablePtr = GetExpression( "tcpip!TWQueue" );
if (!TablePtr) {
dprintf("Error in tcpip!TWQueue: Please try reload\n");
return;
}
if ( !ReadMemory(TablePtr,
&TableAddr,
4,
&result ))
{
dprintf(" Could not read twqueu \n" );
return;
}
dprintf("Statistics for Twqueue @ %08lx\n",
TableAddr );
if ( !ReadMemory(TableAddr,
&Tcbnext,
4,
&result ))
{
dprintf(" Could not read twqueu \n" );
return;
}
sum=i=0;
// Tcb = Tcbnext - 0x118;
Tcb = Tcbnext - FIELD_OFFSET(TWTCB, twtcb_TWQueue);
dprintf(" First tcb::: Tcb %x\n", Tcb );
while ((Tcbnext != TableAddr) && !CheckControlC()) {
// Tcb = Tcbnext - 0x118;
Tcb = Tcbnext - FIELD_OFFSET(TWTCB, twtcb_TWQueue);
if ( !ReadMemory(Tcb,
&Tcbstr,
sizeof(TWTCB),
&result ))
{
dprintf(" Could not read tcb %x \n", Tcb );
return;
}
if (Tcbstr.twtcb_rexmittimer > 0x20) {
dprintf(" Tcb %x:: delta %u: rexmittimer %u\n ",Tcb,Tcbstr.twtcb_delta,Tcbstr.twtcb_rexmittimer);
}
sum += Tcbstr.twtcb_rexmittimer;
Tcbnext = (ULONG)Tcbstr.twtcb_TWQueue.q_next;
i++;
}
dprintf(" Total %d sum of rexmittimer %d\n ",i, sum);
}
#ifdef _obj
# undef _obj
# undef _objAddr
# undef _objType
# undef _objTypeName
#endif
#define _obj TcpConnBlock
#define _objAddr TcpConnBlockToDump
#define _objType TCPConnBlock
#define _objTypeName "TCPConnBlock"
VOID
DumpConnection(
ULONG ConnID
)
{
ULONG ConnIndex = CONN_INDEX(ConnID);
ULONG ConnBlockId = CONN_BLOCKID(ConnID);
UCHAR inst = CONN_INST(ConnID);
ULONG TableAddr;
ULONG ConnBlockAddr;
ULONG ConnTableSize;
ULONG MatchingConn;
ULONG result;
ULONG MaxAllocatedConnBlocks;
TableAddr = GetUlongValue( "tcpip!ConnTable" );
MaxAllocatedConnBlocks = GetUlongValue( "tcpip!MaxAllocatedConnBlocks" );
if ((ConnIndex < MAX_CONN_PER_BLOCK) &&
(ConnBlockId < MaxAllocatedConnBlocks) ){
// get the ConnBlockId
TableAddr += (ConnBlockId * sizeof(ULONG));
if ( !ReadMemory( TableAddr,
&ConnBlockAddr,
sizeof( ULONG ),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", TableAddr, "ConnTableBlock" );
return;
}
if (ConnBlockAddr) {
_objType _obj;
ULONG _objAddr;
_objAddr = ConnBlockAddr;
if ( !ReadMemory( _objAddr,
&_obj,
sizeof( _obj ),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", _objAddr, _objTypeName );
return;
}
MatchingConn = (ULONG)_obj.cb_conn[ConnIndex];
if (MatchingConn) {
DumpTcpConn( MatchingConn, VERBOSITY_FULL );
} else {
dprintf( "NULL Conn!!\n");
}
} else {
dprintf( "NULL ConnBlock!!\n");
}
} else {
dprintf( "Invalid ConnIndex!!\n");
}
}
#ifdef _obj
# undef _obj
# undef _objAddr
# undef _objType
# undef _objTypeName
#endif
#define _obj TcpContext
#define _objAddr TcpContextToDump
#define _objType TCP_CONTEXT
#define _objTypeName "Tcp Context"
VOID
DumpTcpContext(
ULONG _objAddr,
ULONG Type
)
{
_objType _obj;
ULONG result;
unsigned int index;
BOOL bActive;
if ( !ReadMemory( _objAddr,
&_obj,
sizeof( _obj ),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", _objAddr, _objTypeName );
return;
}
dprintf( "%s @ %08lx\n", _objTypeName, _objAddr );
PrintStartStruct();
switch ( Type) {
case TDI_TRANSPORT_ADDRESS_FILE:
PrintPtr( Handle.AddressHandle );
break;
case TDI_CONNECTION_FILE:
PrintPtr( Handle.ConnectionContext );
break;
case TDI_CONTROL_CHANNEL_FILE:
PrintPtr( Handle.ControlChannel );
break;
default:
dprintf(" INVALID FsContext2 - Unknown Type \n");
break;
}
PrintULong( ReferenceCount );
PrintBool( CancelIrps );
PrintKEvent( CleanupEvent );
PrintEndStruct();
switch ( Type) {
case TDI_TRANSPORT_ADDRESS_FILE:
break;
case TDI_CONNECTION_FILE:
DumpConnection( (ULONG)_obj.Handle.ConnectionContext );
break;
case TDI_CONTROL_CHANNEL_FILE:
break;
default:
break;
}
}
#ifdef _obj
# undef _obj
# undef _objAddr
# undef _objType
# undef _objTypeName
#endif
#define _obj FileObj
#define _objAddr FileObjToDump
#define _objType FILE_OBJECT
#define _objTypeName "File Object"
VOID
DumpTcpIrp(
ULONG _objAddr
)
{
_objType _obj;
ULONG result;
unsigned int index;
BOOL bActive;
if ( !ReadMemory( _objAddr,
&_obj,
sizeof( _obj ),
&result ))
{
dprintf("%08lx: Could not read %s structure.\n", _objAddr, _objTypeName );
return;
}
dprintf(" %s @ %08lx\n", _objTypeName, _objAddr );
PrintPtr( FsContext );
PrintXEnum( FsContext2, FsContext2 );
DumpTcpContext( (ULONG)_obj.FsContext, (ULONG)_obj.FsContext2 );
}
VOID
DumpIrp(
PVOID IrpToDump,
BOOLEAN FullOutput
)
/*++
Routine Description:
This routine dumps an Irp. It does not check to see that the address
supplied actually locates an Irp. This is done to allow for dumping
Irps post mortem, or after they have been freed or completed.
Arguments:
IrpToDump - the address of the irp.
Return Value:
None
--*/
{
IO_STACK_LOCATION irpStack;
PCHAR buffer;
ULONG irpStackAddress;
ULONG result;
IRP irp;
CCHAR irpStackIndex;
BOOLEAN TcpIrp = FALSE;
if ( !ReadMemory( (DWORD) IrpToDump,
&irp,
sizeof(irp),
&result) ) {
dprintf("%08lx: Could not read Irp\n", IrpToDump);
return;
}
if (irp.Type != IO_TYPE_IRP) {
dprintf("IRP signature does not match, probably not an IRP\n");
return;
}
dprintf("Irp is Active with %d stacks %d is current\n",
irp.StackCount,
irp.CurrentLocation);
if ((irp.MdlAddress != NULL) && (irp.Type == IO_TYPE_IRP)) {
dprintf(" Mdl = %08lx ", irp.MdlAddress);
} else {
dprintf(" No Mdl ");
}
if (irp.AssociatedIrp.MasterIrp != NULL) {
dprintf("%s = %08lx ",
(irp.Flags & IRP_ASSOCIATED_IRP) ? "Associated Irp" :
(irp.Flags & IRP_DEALLOCATE_BUFFER) ? "System buffer" :
"Irp count",
irp.AssociatedIrp.MasterIrp);
}
dprintf("Thread %08lx: ", irp.Tail.Overlay.Thread);
if (irp.StackCount > 15) {
dprintf("Too many Irp stacks to be believed (>15)!!\n");
return;
} else {
if (irp.CurrentLocation > irp.StackCount) {
dprintf("Irp is completed. ");
} else {
dprintf("Irp stack trace. ");
}
}
if (irp.PendingReturned) {
dprintf("Pending has been returned\n");
} else {
dprintf("\n");
}
if (FullOutput)
{
dprintf("Flags = %08lx\n", irp.Flags);
dprintf("ThreadListEntry.Flink = %08lx\n", irp.ThreadListEntry.Flink);
dprintf("ThreadListEntry.Blink = %08lx\n", irp.ThreadListEntry.Blink);
dprintf("IoStatus.Status = %08lx\n", irp.IoStatus.Status);
dprintf("IoStatus.Information = %08lx\n", irp.IoStatus.Information);
dprintf("RequestorMode = %08lx\n", irp.RequestorMode);
dprintf("Cancel = %02lx\n", irp.Cancel);
dprintf("CancelIrql = %lx\n", irp.CancelIrql);
dprintf("ApcEnvironment = %02lx\n", irp.ApcEnvironment);
dprintf("UserIosb = %08lx\n", irp.UserIosb);
dprintf("UserEvent = %08lx\n", irp.UserEvent);
dprintf("Overlay.AsynchronousParameters.UserApcRoutine = %08lx\n", irp.Overlay.AsynchronousParameters.UserApcRoutine);
dprintf("Overlay.AsynchronousParameters.UserApcContext = %08lx\n", irp.Overlay.AsynchronousParameters.UserApcContext);
dprintf(
"Overlay.AllocationSize = %08lx - %08lx\n",
irp.Overlay.AllocationSize.HighPart,
irp.Overlay.AllocationSize.LowPart);
dprintf("CancelRoutine = %08lx\n", irp.CancelRoutine);
dprintf("UserBuffer = %08lx\n", irp.UserBuffer);
dprintf("&Tail.Overlay.DeviceQueueEntry = %08lx\n", &irp.Tail.Overlay.DeviceQueueEntry);
dprintf("Tail.Overlay.Thread = %08lx\n", irp.Tail.Overlay.Thread);
dprintf("Tail.Overlay.AuxiliaryBuffer = %08lx\n", irp.Tail.Overlay.AuxiliaryBuffer);
dprintf("Tail.Overlay.ListEntry.Flink = %08lx\n", irp.Tail.Overlay.ListEntry.Flink);
dprintf("Tail.Overlay.ListEntry.Blink = %08lx\n", irp.Tail.Overlay.ListEntry.Blink);
dprintf("Tail.Overlay.CurrentStackLocation = %08lx\n", irp.Tail.Overlay.CurrentStackLocation);
dprintf("Tail.Overlay.OriginalFileObject = %08lx\n", irp.Tail.Overlay.OriginalFileObject);
dprintf("Tail.Apc = %08lx\n", irp.Tail.Apc);
dprintf("Tail.CompletionKey = %08lx\n", irp.Tail.CompletionKey);
}
irpStackAddress = (ULONG)IrpToDump + sizeof(irp);
buffer = LocalAlloc(LPTR, 256);
if (buffer == NULL) {
dprintf("Can't allocate 256 bytes\n");
return;
}
dprintf(" cmd flg cl Device File Completion-Context\n");
for (irpStackIndex = 1; irpStackIndex <= irp.StackCount; irpStackIndex++) {
if ( !ReadMemory( (DWORD) irpStackAddress,
&irpStack,
sizeof(irpStack),
&result) ) {
dprintf("%08lx: Could not read IrpStack\n", irpStackAddress);
goto exit;
}
dprintf("%c%3x %2x %2x %08lx %08lx %08lx-%08lx %s %s %s %s\n",
irpStackIndex == irp.CurrentLocation ? '>' : ' ',
irpStack.MajorFunction,
irpStack.Flags,
irpStack.Control,
irpStack.DeviceObject,
irpStack.FileObject,
irpStack.CompletionRoutine,
irpStack.Context,
(irpStack.Control & SL_INVOKE_ON_SUCCESS) ? "Success" : "",
(irpStack.Control & SL_INVOKE_ON_ERROR) ? "Error" : "",
(irpStack.Control & SL_INVOKE_ON_CANCEL) ? "Cancel" : "",
(irpStack.Control & SL_PENDING_RETURNED) ? "pending" : "");
if (irpStack.DeviceObject != NULL) {
if ((ULONG)irpStack.DeviceObject != GetUlongValue( "tcpip!TCPDeviceObject" )) {
dprintf("THIS IS NOT A TCP Irp!!!!\n");
TcpIrp = FALSE;
} else {
dprintf("\t \\Driver\\Tcpip");
TcpIrp = TRUE;
}
}
if (irpStack.CompletionRoutine != NULL) {
GetSymbol(irpStack.CompletionRoutine, buffer, &result);
dprintf("\t%s\n", buffer);
} else {
dprintf("\n");
}
dprintf("\t\t\tArgs: %08lx %08lx %08lx %08lx\n",
irpStack.Parameters.Others.Argument1,
irpStack.Parameters.Others.Argument2,
irpStack.Parameters.Others.Argument3,
irpStack.Parameters.Others.Argument4);
irpStackAddress += sizeof(irpStack);
if (CheckControlC()) {
goto exit;
}
if (TcpIrp) {
if ( irpStack.FileObject != NULL ) {
DumpTcpIrp( (ULONG)irpStack.FileObject );
} else {
dprintf("FILEOBJECT Ptr is NULL!!!!\n");
}
}
}
exit:
LocalFree(buffer);
}