Mobile development: Netstat, know your device’s open ports
On desktop PCs you have the nice tool netstat to see which ports are open on the PC. A customer wanted to know, why his devices do not release there internet connection. The only tool I know, that will show open network connections, is called netstat. Unfortunately I did not find such tool for Windows Mobile and so I wrote one myself:
netstat for windows mobile
NetstatCF2 is written in C#, Compact Framework. After you started the tool it immediately collects the open ports data. It will also log this data periodically (every 3 seconds) to a log file called “\netstat.log”.
The code makes massive calls to the ipHlp API functions. Here are some sample snippets:
... public class IPHlpAPI32Wrapper { public const byte NO_ERROR = 0; public const int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100; public const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200; public const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; public int dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; [DllImport("iphlpapi.dll", SetLastError = true)] public extern static int GetUdpStatistics(ref MIB_UDPSTATS pStats); [DllImport("iphlpapi.dll", SetLastError = true)] public static extern int GetUdpTable(byte[] UcpTable, out int pdwSize, bool bOrder); [DllImport("iphlpapi.dll", SetLastError = true)] public extern static int GetTcpStatistics(ref MIB_TCPSTATS pStats); [DllImport("iphlpapi.dll", SetLastError = true)] public static extern int GetTcpTable(byte[] pTcpTable, out int pdwSize, bool bOrder); [DllImport("iphlpapi.dll", SetLastError = true)] public static extern int GetIpForwardTable(IntPtr pIpForwardTable, ref int pdwSize, bool bOrder); [DllImport("iphlpapi.dll", SetLastError = true)] public static extern int GetIpForwardTable(byte[] pIpForwardTable, ref int pdwSize, bool bOrder); ... public void GetTcpConnexions() { byte[] buffer = new byte[20000]; // Start with 20.000 bytes left for information about tcp table int pdwSize = 20000; int res = IPHlpAPI32Wrapper.GetTcpTable(buffer, out pdwSize, true); if (res != NO_ERROR) { buffer = new byte[pdwSize]; res = IPHlpAPI32Wrapper.GetTcpTable(buffer, out pdwSize, true); if (res != 0) return; // Error. You should handle it } TcpConnexion = new IpHlpApidotnet.MIB_TCPTABLE(); int nOffset = 0; // number of entry in the TcpConnexion.dwNumEntries = Convert.ToInt32(buffer[nOffset]); nOffset += 4; TcpConnexion.table = new MIB_TCPROW[TcpConnexion.dwNumEntries]; for (int i = 0; i < TcpConnexion.dwNumEntries; i++) { // state int st = Convert.ToInt32(buffer[nOffset]); // state in string //((MIB_TCPROW) (TcpConnexion.table[i]).StrgState = convert_state(st); // state by ID //((MIB_TCPROW) (TcpConnexion.table[i]).iState = st; nOffset += 4; // local address string LocalAdrr = buffer[nOffset].ToString() + "." + buffer[nOffset + 1].ToString() + "." + buffer[nOffset + 2].ToString() + "." + buffer[nOffset + 3].ToString(); nOffset += 4; //local port in decimal int LocalPort = (((int)buffer[nOffset]) << 8) + (((int)buffer[nOffset + 1])) + (((int)buffer[nOffset + 2]) << 24) + (((int)buffer[nOffset + 3]) << 16); nOffset += 4; // store the remote endpoint //((MIB_TCPROW)( (TcpConnexion.table[i]).Local = new IPEndPoint(IPAddress.Parse(LocalAdrr), LocalPort); // remote address string RemoteAdrr = buffer[nOffset].ToString() + "." + buffer[nOffset + 1].ToString() + "." + buffer[nOffset + 2].ToString() + "." + buffer[nOffset + 3].ToString(); nOffset += 4; // if the remote address = 0 (0.0.0.0) the remote port is always 0 // else get the remote port in decimal int RemotePort; // if (RemoteAdrr == "0.0.0.0") { RemotePort = 0; } else { RemotePort = (((int)buffer[nOffset]) << 8) + (((int)buffer[nOffset + 1])) + (((int)buffer[nOffset + 2]) << 24) + (((int)buffer[nOffset + 3]) << 16); } nOffset += 4; //((MIB_TCPROW) (TcpConnexion.table[i]).Remote = new IPEndPoint(IPAddress.Parse(RemoteAdrr), RemotePort); } } ... public void GetUdpConnexions() { byte[] buffer = new byte[20000]; // Start with 20.000 bytes left for information about tcp table int pdwSize = 20000; int res = IPHlpAPI32Wrapper.GetUdpTable(buffer, out pdwSize, true); if (res != NO_ERROR) { buffer = new byte[pdwSize]; res = IPHlpAPI32Wrapper.GetUdpTable(buffer, out pdwSize, true); if (res != 0) return; // Error. You should handle it } UdpConnexion = new IpHlpApidotnet.MIB_UDPTABLE(); int nOffset = 0; // number of entry in the UdpConnexion.dwNumEntries = Convert.ToInt32(buffer[nOffset]); nOffset += 4; UdpConnexion.table = new MIB_UDPROW[UdpConnexion.dwNumEntries]; for (int i = 0; i < UdpConnexion.dwNumEntries; i++) { string LocalAdrr = buffer[nOffset].ToString() + "." + buffer[nOffset + 1].ToString() + "." + buffer[nOffset + 2].ToString() + "." + buffer[nOffset + 3].ToString(); nOffset += 4; int LocalPort = (((int)buffer[nOffset]) << 8) + (((int)buffer[nOffset + 1])) + (((int)buffer[nOffset + 2]) << 24) + (((int)buffer[nOffset + 3]) << 16); nOffset += 4; //((MIB_UDPROW) (UdpConnexion.table[i]).Local = new IPEndPoint(IPAddress.Parse(LocalAdrr), LocalPort); } } ... public class IPHelper { private const int NO_ERROR = 0; private const int MIB_TCP_STATE_CLOSED = 1; private const int MIB_TCP_STATE_LISTEN = 2; private const int MIB_TCP_STATE_SYN_SENT = 3; private const int MIB_TCP_STATE_SYN_RCVD = 4; private const int MIB_TCP_STATE_ESTAB = 5; private const int MIB_TCP_STATE_FIN_WAIT1 = 6; private const int MIB_TCP_STATE_FIN_WAIT2 = 7; private const int MIB_TCP_STATE_CLOSE_WAIT = 8; private const int MIB_TCP_STATE_CLOSING = 9; private const int MIB_TCP_STATE_LAST_ACK = 10; private const int MIB_TCP_STATE_TIME_WAIT = 11; private const int MIB_TCP_STATE_DELETE_TCB = 12; private const int ERROR_INSUFFICIENT_BUFFER = 122; ...
But there is nothing special except on how to use C/C++ structures in C#.
Here is a sample of the logged data:
xxxxxxxxxxx AM ################# ======= TCP table ======== local remote 0.0.0.0: 21 0.0.0.0: 0 LISTEN 0.0.0.0: 1004 0.0.0.0: 0 LISTEN 0.0.0.0: 2188 0.0.0.0: 0 LISTEN 0.0.0.0: 2189 0.0.0.0: 0 LISTEN 0.0.0.0: 5655 0.0.0.0: 0 LISTEN 0.0.0.0: 52241 0.0.0.0: 0 LISTEN 127.0.0.1: 1032 127.0.0.1: 52241 ESTAB 127.0.0.1: 1034 127.0.0.1: 52241 ESTAB 127.0.0.1: 1035 127.0.0.1: 52241 ESTAB 127.0.0.1: 1036 127.0.0.1: 52241 ESTAB 127.0.0.1: 52241 127.0.0.1: 1032 ESTAB 127.0.0.1: 52241 127.0.0.1: 1034 ESTAB 127.0.0.1: 52241 127.0.0.1: 1035 ESTAB 127.0.0.1: 52241 127.0.0.1: 1036 ESTAB 192.168.55.101: 1082 192.168.55.100: 7438 ESTAB 192.168.55.101: 1083 192.168.55.100: 990 ESTAB 192.168.55.101: 1086 192.168.55.100: 990 ESTAB 192.168.55.101: 1087 192.168.55.100: 990 ESTAB 192.168.55.101: 1092 192.168.55.100: 990 ESTAB 192.168.55.101: 1102 192.168.55.100: 1004 ESTAB 192.168.55.101: 1103 192.168.55.100: 990 ESTAB 192.168.128.104: 1033 192.168.128.5: 62241 ESTAB 192.168.128.104: 5655 192.168.128.2: 59534 ESTAB 192.168.128.104: 5655 192.168.128.2: 59535 ESTAB 192.168.128.104: 6510 192.168.128.2: 59536 ESTAB 192.168.128.104: 6510 192.168.128.2: 59537 ESTAB ======= UDP table ======== 0.0.0.0: 53 0.0.0.0: 137 0.0.0.0: 138 0.0.0.0: 1088 0.0.0.0: 9204 0.0.0.0: 49111 192.168.128.104: 68 ======= TCP statistics ======== Retransmission timeout (min/max): Van Jacobson's Algorithm: 300/120000 max connnections: -1 active open: 69 passive open: 196 failed attempts: 0 established resets: 243 current established: 20 segments in: 134380 segments out: 130900 retransmitted segments: 175 in errors: 0 out resets: 861 num connections: 26 ======= UDP statistics ======== in datagrams: 13771 in errors: 0 num ports: 3353 num addresses: 7 out datagrams: 887 ======= Adapter infos ========== 131074: BCMCF1, 192.168.128.104 262147: USB Cable:, 192.168.55.101 ======= Route entries ========== Network Destination Netmask Gateway Interface Metric 0.0.0.0 0.0.0.0 192.168.55.101 003 0 225.20.0.0 0.0.0.0 255.255.255.255 255 0 0.0.0.0 0.0.0.0 192.168.128.1 002 0 225.20.0.0 0.0.0.0 255.255.255.255 255 0 127.0.0.0 255.0.0.0 127.0.0.1 001 0 104.148.1.0 0.0.0.0 255.255.255.255 255 0 192.168.55.101 255.255.255.255 127.0.0.1 001 0 225.20.0.0 0.0.0.0 255.255.255.255 255 0 192.168.55.255 255.255.255.255 192.168.55.101 003 0 225.20.0.0 0.0.0.0 255.255.255.255 255 0 192.168.128.0 255.255.255.0 192.168.128.104 002 0 67.148.1.0 0.0.0.0 255.255.255.255 255 0
Hopefully you use this small tool at a special time.
Code and sample bin at code.google.com (VS2008, CF2, WM5SDK)
Possibly outdated bin: [Download not found]
Hi,
I’m very interested in that tool but I’vnt any development switte so it’s not possible to me to compile it. Have you any arm compiled version?
Thanks in advance
Abdul
There is a binary at http://code.google.com/p/win-mobile-code/source/browse/trunk/netstatCF2/bin/Debug/netstatCF2.exe