Ahmad.s
Ahmad.s

Reputation: 43

How to display current IPv6 connections?

I have been trying to display current IPv6 connections with the GetExtendedTcpTable() method from Windows, but I'm not getting it to display any IPv6 Adresses.

I only found code on how to display current IPv4 connections, so what I did is change the IPv4 methods to IPv6 methods of the Windows documentation.

I also tried other methods, like PMIB_TCP6ROW_OWNER_MODULE, but it just wont show the IPv6 adresses.

Information about the PID is saved in ptTable, but ucLocalAddr or usRemoteAddr isn't returning anything.

Code looks like this:

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <ws2tcpip.h> 
#include <iphlpapi.h>
#include <iostream>
#include <vector>
#include <in6addr.h>
#include <Ws2ipdef.h>
#include < ws2tcpip.h>

#pragma comment(lib,"psapi")
#pragma comment(lib,"iphlpapi")
#pragma comment(lib,"wsock32")
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

using namespace std;

int main()
{

vector<unsigned char> buffer2;
DWORD dwSize2 = sizeof(MIB_TCP6TABLE_OWNER_PID);
UCHAR dwSize3 = sizeof(MIB_TCP6TABLE_OWNER_PID);
DWORD dwRetValue2 = 0;

do
{
    buffer2.resize(dwSize3, 0);
    dwRetValue2 = GetExtendedTcpTable(buffer2.data(), &dwSize2, TRUE, AF_INET6, TCP_TABLE_OWNER_PID_ALL, 0);
    
} while (dwRetValue2 == ERROR_INSUFFICIENT_BUFFER);

if (dwRetValue2 == ERROR_SUCCESS)
{

    PMIB_TCP6TABLE_OWNER_PID ptTable = reinterpret_cast<PMIB_TCP6TABLE_OWNER_PID>(buffer2.data());

    cout << "Number of Entries: " << ptTable->dwNumEntries << endl << endl;

    // caution: array starts with index 0, count starts by 1
    for (DWORD i = 0; i < ptTable->dwNumEntries; i++)
    {

        DWORD pid = ptTable->table[i].dwOwningPid;
        UCHAR* lol = ptTable->table[i].ucLocalAddr;
        printf("%s", "--------------------------------\n");
        printf("%s", ptTable->table[i].ucLocalAddr);

            cout << "PID: " << ptTable->table[i].dwOwningPid << endl;
            cout << "State: " << ptTable->table[i].dwState << endl;
            cout << "Local: "
                << (ptTable->table[i].ucLocalAddr)                                               
                << ":"
                << ((ptTable->table[i].ucLocalAddr))
                << ":"
                << ((ptTable->table[i].ucLocalAddr))
                << ":"
                << ((ptTable->table[i].ucLocalAddr))
                << ":"
                << htons((unsigned short)ptTable->table[i].dwLocalPort)
                << endl;

            cout << "Remote: "
                << (ptTable->table[i].ucRemoteAddr)
                << ":"
                << ((ptTable->table[i].ucRemoteAddr))
                << ":"
                << ((ptTable->table[i].ucRemoteAddr))
                << ":"
                << ((ptTable->table[i].ucRemoteAddr))
                << ":"
                << htons((unsigned short)ptTable->table[i].dwRemotePort)
                << endl;

            cout << endl;
        }
    }

    cin.get();
}

Upvotes: 3

Views: 439

Answers (2)

Torrecto - MSFT
Torrecto - MSFT

Reputation: 640

You need to edit your protocol address family.

To display IPv4, you need to add hints.ai_family = AF_INET;

To display IPv6, you need to replace it with hints.ai_family = AF_INET6;

I wrote a program that analyze DNS/IPV4/IPV6 to obtain an IP address. Here is the code.

#include <iostream>
#include <vector>
#include <WS2tcpip.h>
#include <winsock2.h>

using namespace std;

// link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")

int main() {
                const char* hostname = "v----------M";
                WSAData wsaData;
                addrinfo* ptr = nullptr;
                addrinfo* res = nullptr;
                addrinfo hints;
                int addr_ret;

                memset(&hints, 0, sizeof(hints));
                
                hints.ai_family = AF_INET;
                hints.ai_socktype = SOCK_STREAM;
                hints.ai_family = AF_UNSPEC;
                
                hints.ai_protocol = IPPROTO_TCP;
                //hints.ai_family = AF_INET6;
                
                int wsaRes = WSAStartup(MAKEWORD(2, 2), &wsaData);
                if (wsaRes != 0) {
                                cerr << "WSAload failed:" << wsaRes << endl;
                                system("pause");
                                return -1;
                }

                //para1can be ip\dns, para2 can be service/port type like 80/http 443/https
                addr_ret = getaddrinfo(hostname, "443", &hints, &res);
                if (addr_ret != 0) {
                                cerr << "analyze error,code is:" << addr_ret << endl;
                                system("pause");
                                return -1;
                }

                sockaddr_in* ip_v4;
                LPSOCKADDR ip_v6;
                int count = 0;
                int retval;
                DWORD ip_v6_strlen = 46;
                char ip_v6_str[46];
                
                for (ptr = res; ptr != NULL; ptr = ptr->ai_next) {
                                cout << "The " << count++ << "ip address:" << endl;
                                switch (ptr->ai_family)
                                {
                                case AF_UNSPEC:
                                                cout << "unknown ip" << endl;
                                                break;
                                case AF_INET:
                                                cout << "ip v4: ";
                                                ip_v4 = (sockaddr_in*)ptr->ai_addr;
#pragma warning(disable : 4996)
                                                cout << inet_ntoa(ip_v4->sin_addr) << endl;
                                                break;
                                case AF_INET6:
                                                cout << "ip v6: ";
                                                ip_v6 = (LPSOCKADDR)ptr->ai_addr;
#pragma warning(disable : 4996)
                                                retval = WSAAddressToStringA(ip_v6, (DWORD)ptr->ai_addrlen, NULL, ip_v6_str, &ip_v6_strlen);
                                                if (retval)
                                                                cerr << "WSAAddressToString failed:" << WSAGetLastError << endl;
                                                else
                                                                cout << ip_v6_str << endl;
                                                break;
                                default:
                                                cout << "Other type:" << ptr->ai_family << endl;
                                                break;
                                }
                }
                freeaddrinfo(res);
                WSACleanup();
                system("pause");
                return 0;
}

This is my hostname: enter image description here

It runs well.

enter image description here enter image description here

Upvotes: 1

Remy Lebeau
Remy Lebeau

Reputation: 597941

Your do loop is not expanding the vector correctly, it resizes the vector to the same value on each iteration. Get rid of dwSize3 and use dwSize2 for both the resize and the enumeration.

Also, since you are retrieving AF_INET6 entries, each IPv6 address in the table is 16 bytes in size, but you are not even displaying any of the bytes correctly. The IP addresses are provided as raw bytes, not as strings. Fortunately, the API has functions for that conversion, per the documentation:

The ucLocalAddr and ucRemoteAddr members are stored in a character array in network byte order. The RtlIpv6AddressToString or RtlIpv6AddressToStringEx functions may be used to convert the IPv6 address in the ucLocalAddr or ucRemoteAddr members to a string without loading the Windows Sockets DLL.

Try something more like this:

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <ws2tcpip.h> 
#include <iphlpapi.h>
#include <iostream>
#include <vector>
#include <in6addr.h>
#include <Ws2ipdef.h>
#include <ws2tcpip.h>
#include <Mstcpip.h>

#pragma comment(lib, "psapi")
#pragma comment(lib, "iphlpapi")
#pragma comment(lib, "wsock32")
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

using namespace std;

int main()
{
    vector<BYTE> buffer;
    DWORD dwSize = sizeof(MIB_TCP6TABLE_OWNER_PID);
    DWORD dwRetValue = 0;

    in6_addr in6_localAddr, in6_remoteAddr; 
    char szLocalAddr[INET6_ADDRSTRLEN], szRemoteAddr[INET6_ADDRSTRLEN];
    ULONG ulAddrLen;

    do
    {
        buffer.resize(dwSize, 0);
        dwRetValue = GetExtendedTcpTable(buffer.data(), &dwSize, TRUE, AF_INET6, TCP_TABLE_OWNER_PID_ALL, 0);
    
    } while (dwRetValue == ERROR_INSUFFICIENT_BUFFER);

    if (dwRetValue == ERROR_SUCCESS)
    {
        PMIB_TCP6TABLE_OWNER_PID ptTable = reinterpret_cast<PMIB_TCP6TABLE_OWNER_PID>(buffer.data());

        cout << "Number of Entries: " << ptTable->dwNumEntries << endl << endl;

        for (DWORD i = 0; i < ptTable->dwNumEntries; i++)
        {
            memcpy(&in6_localAddr.u.Byte, ptTable->table[i].ucLocalAddr, 16);
            memcpy(&in6_remoteAddr.u.Byte, ptTable->table[i].ucRemoteAddr, 16);

            ulAddrLen = INET6_ADDRSTRLEN;
            RtlIpv6AddressToStringExA(&in6_localAddr, ptTable->table[i].dwLocalScopeId, ptTable->table[i].dwLocalPort, szLocalAddr, &ulAddrLen);

            ulAddrLen = INET6_ADDRSTRLEN;
            RtlIpv6AddressToStringExA(&in6_remoteAddr, ptTable->table[i].dwRemoteScopeId, ptTable->table[i].dwRemotePort, szRemoteAddr, &ulAddrLen);

            cout << "--------------------------------\n";

            cout << "PID: " << ptTable->table[i].dwOwningPid << endl;
            cout << "State: " << ptTable->table[i].dwState << endl;
            cout << "Local: " << szLocalAddr << endl;
            cout << "Remote: " << szRemoteAddr << endl;

            cout << endl;
        }
    }

    cin.get();
}

Upvotes: 1

Related Questions