// IPV6 version of the Tcp row. internal SystemTcpConnectionInformation(Interop.IpHlpApi.MibTcp6RowOwnerPid row) { _state = row.state; // Port is returned in Big-Endian - most significant bit on left. // Unfortunately, its done at the word level and not the DWORD level. int localPort = row.localPort1 << 8 | row.localPort2; int remotePort = ((_state == TcpState.Listen) ? 0 : row.remotePort1 << 8 | row.remotePort2); _localEndPoint = new IPEndPoint(new IPAddress(row.localAddr, row.localScopeId), (int)localPort); _remoteEndPoint = new IPEndPoint(new IPAddress(row.remoteAddr, row.remoteScopeId), (int)remotePort); }
/// /// Gets the active TCP connections. Uses the native GetTcpTable API. private List <SystemTcpConnectionInformation> GetAllTcpConnections() { uint size = 0; uint result = 0; SafeLocalAllocHandle buffer = null; List <SystemTcpConnectionInformation> tcpConnections = new List <SystemTcpConnectionInformation>(); // Check if it supports IPv4 for IPv6 only modes. if (Socket.OSSupportsIPv4) { // Get the buffer size needed. result = Interop.IpHlpApi.GetTcpTable(SafeLocalAllocHandle.Zero, ref size, true); while (result == Interop.IpHlpApi.ERROR_INSUFFICIENT_BUFFER) { // Allocate the buffer and get the TCP table. using (buffer = SafeLocalAllocHandle.LocalAlloc((int)size)) { result = Interop.IpHlpApi.GetTcpTable(buffer, ref size, true); if (result == Interop.IpHlpApi.ERROR_SUCCESS) { // The table info just gives us the number of rows. IntPtr newPtr = buffer.DangerousGetHandle(); Interop.IpHlpApi.MibTcpTable tcpTableInfo = Marshal.PtrToStructure <Interop.IpHlpApi.MibTcpTable>(newPtr); if (tcpTableInfo.numberOfEntries > 0) { // Skip over the tableinfo to get the inline rows. newPtr = (IntPtr)((long)newPtr + Marshal.SizeOf(tcpTableInfo.numberOfEntries)); for (int i = 0; i < tcpTableInfo.numberOfEntries; i++) { Interop.IpHlpApi.MibTcpRow tcpRow = Marshal.PtrToStructure <Interop.IpHlpApi.MibTcpRow>(newPtr); tcpConnections.Add(new SystemTcpConnectionInformation(tcpRow)); // Increment the pointer to the next row. newPtr = (IntPtr)((long)newPtr + Marshal.SizeOf(tcpRow)); } } } } } // If we don't have any ipv4 interfaces detected, just continue. if (result != Interop.IpHlpApi.ERROR_SUCCESS && result != Interop.IpHlpApi.ERROR_NO_DATA) { throw new NetworkInformationException((int)result); } } if (Socket.OSSupportsIPv6) { // Get the buffer size needed. size = 0; result = Interop.IpHlpApi.GetExtendedTcpTable(SafeLocalAllocHandle.Zero, ref size, true, (uint)AddressFamily.InterNetworkV6, Interop.IpHlpApi.TcpTableClass.TcpTableOwnerPidAll, 0); while (result == Interop.IpHlpApi.ERROR_INSUFFICIENT_BUFFER) { // Allocate the buffer and get the TCP table. using (buffer = SafeLocalAllocHandle.LocalAlloc((int)size)) { result = Interop.IpHlpApi.GetExtendedTcpTable(buffer, ref size, true, (uint)AddressFamily.InterNetworkV6, Interop.IpHlpApi.TcpTableClass.TcpTableOwnerPidAll, 0); if (result == Interop.IpHlpApi.ERROR_SUCCESS) { // The table info just gives us the number of rows. IntPtr newPtr = buffer.DangerousGetHandle(); Interop.IpHlpApi.MibTcp6TableOwnerPid tcpTable6OwnerPid = Marshal.PtrToStructure <Interop.IpHlpApi.MibTcp6TableOwnerPid>(newPtr); if (tcpTable6OwnerPid.numberOfEntries > 0) { // Skip over the tableinfo to get the inline rows. newPtr = (IntPtr)((long)newPtr + Marshal.SizeOf(tcpTable6OwnerPid.numberOfEntries)); for (int i = 0; i < tcpTable6OwnerPid.numberOfEntries; i++) { Interop.IpHlpApi.MibTcp6RowOwnerPid tcp6RowOwnerPid = Marshal.PtrToStructure <Interop.IpHlpApi.MibTcp6RowOwnerPid>(newPtr); tcpConnections.Add(new SystemTcpConnectionInformation(tcp6RowOwnerPid)); // We increment the pointer to the next row. newPtr = (IntPtr)((long)newPtr + Marshal.SizeOf(tcp6RowOwnerPid)); } } } } } // If we don't have any ipv6 interfaces detected, just continue. if (result != Interop.IpHlpApi.ERROR_SUCCESS && result != Interop.IpHlpApi.ERROR_NO_DATA) { throw new NetworkInformationException((int)result); } } return(tcpConnections); }