C语言 使用AddIpAddress()/DeleteIpAddress()以及来自GetAdaptersAddresses()的信息

mwkjh3gx  于 2023-01-20  发布在  其他
关注(0)|答案(2)|浏览(176)

我需要从C/C++程序中更改特定网络接口的IP地址和子掩码。在Windows文档中,我发现应该使用Windows API中的AddIPAddress()/DeleteIpAddress()。但是,例如DeleteIpAddress()需要一个NTEContext作为参数。我发现an example使用GetAdaptersInfo()来获取接口和上下文的索引。但是,该页面还明确声明:
在Windows XP和更高版本上:使用获取适配器地址函数,而不是获取适配器信息。
但是,当GetAdaptersInfo()填充其中存在索引/NTEcontext的IP_ADAPTER_INFO结构体时,GetAdaptersAddresses()提供了其中不存在此类成员的IP_ADAPTER_ADDRESSES结构体。
我应该如何使用较新的GetAdaptersAddresses()函数来获取接口的索引/上下文?

xam8gpfp

xam8gpfp1#

基于https://learn.microsoft.com/en-us/windows/win32/iphlp/managing-network-adapters,您应该能够使用以下内容:

类似这样的方法应该可以奏效:

ULONG IfIndex = 0;
/* check error returned */ GetAdapterIndex(AdapterName, &IfIndex);
IP_PER_ADAPTER_INFO/*_W2KSP1?*/ PerAdapterInfo;
ULONG OutBufLen = sizeof(PerAdapterInfo);
/* check error returned */ GetPerAdapterInfo(IfIndex, &PerAdapterInfo, &OutBufLen);
/* check error returned */ DeleteIPAddress(PerAdapterInfo.DnsServerList.Context);

P.S.对于旧版本的Windows,这可能会工作:https://microsoft.public.vb.winapi.narkive.com/TW7rVsdu/how-to-obtain-ntecontext-for-use-in-deleteipaddress-without-first-calling-addipaddress

lg40wkob

lg40wkob2#

此示例检索与系统关联的适配器的IP_ADAPTER_ADDRESSES结构,并打印每个适配器接口的一些成员。
以下示例检索IP地址表以确定第一个适配器的接口索引,然后将命令行中指定的IP地址添加到第一个适配器。添加的IP地址随后被删除。
我把这两个程序结合在一起并修改了代码。
可以输出网卡描述、IP地址、MAC地址、DNS地址,也可以将IP地址添加到第一个网卡上,也可以删除相同的地址。

**注意:**DeleteIPAddress()函数用于删除先前使用AddIPAddress()添加的IP地址。如果您只是使用AddIPAddress()添加IP地址,则在添加IP地址之后需要手动删除。

此图为添加的IP,您可以通过左侧的“编辑”删除添加的IP。

下面是代码:

#pragma comment (lib, "Ws2_32.lib")
// Link with Iphlpapi.lib
#pragma comment(lib, "IPHLPAPI.lib")

#include<WinSock2.h>
#include<WS2tcpip.h>
#include<iostream>
#include<IPHlpApi.h>
using namespace std;
#pragma warning(disable:4996)
int main()
{
    PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
    IP_ADAPTER_DNS_SERVER_ADDRESS* pDnServer = nullptr;
    ULONG outBufLen = 0;
    DWORD dwRetVal = 10;
    char buff[128];
    DWORD bufflen = 128;
    int i;

    PMIB_IPADDRTABLE pIPAddrTable;
    DWORD dwSize =128;
    
    UINT iaIPAddress;
    UINT imIPMask;

    ULONG NTEContext = 0;
    ULONG NTEInstance = 0;

    LPVOID lpMsgBuf;

    pIPAddrTable = (MIB_IPADDRTABLE*)VirtualAlloc(&dwSize, sizeof(PMIB_IPADDRTABLE), MEM_RESERVE, NULL);
    pIPAddrTable = (MIB_IPADDRTABLE*)malloc(150 * sizeof(MIB_IPADDRTABLE));
    GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses, &outBufLen);

    pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen);

    if ((dwRetVal = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST, NULL, pAddresses, &outBufLen)) == NO_ERROR) {

        while (pAddresses) {
            printf("%S, %.2x-%.2x-%.2x-%.2x-%.2x-%.2x: \n",
                pAddresses->FriendlyName,
                pAddresses->PhysicalAddress[0], pAddresses->PhysicalAddress[1],
                pAddresses->PhysicalAddress[2], pAddresses->PhysicalAddress[3],
                pAddresses->PhysicalAddress[4], pAddresses->PhysicalAddress[5]);

            PIP_ADAPTER_UNICAST_ADDRESS pUnicast = pAddresses->FirstUnicastAddress;
            pDnServer = pAddresses->FirstDnsServerAddress;

            if (pDnServer)
            {
                sockaddr_in* sa_in = (sockaddr_in*)pDnServer->Address.lpSockaddr;
                printf("DNS:%s\n", inet_ntop(AF_INET, &(sa_in->sin_addr), buff, bufflen));
            }
            if (pAddresses->OperStatus == IfOperStatusUp)
            {
                printf("Status: active\n");
            }
            else
            {
                printf("Status: deactive\n");
            }

            for (i = 0; pUnicast != NULL; i++)
            {
                if (pUnicast->Address.lpSockaddr->sa_family == AF_INET)
                {
                    sockaddr_in* sa_in = (sockaddr_in*)pUnicast->Address.lpSockaddr;
                    printf("IPV4 Unicast Address:%s\n", inet_ntop(AF_INET, &(sa_in->sin_addr), buff, bufflen));
                }
                else if (pUnicast->Address.lpSockaddr->sa_family == AF_INET6)
                {
                    sockaddr_in6* sa_in6 = (sockaddr_in6*)pUnicast->Address.lpSockaddr;
                    printf("IPV6:%s\n", inet_ntop(AF_INET6, &(sa_in6->sin6_addr), buff, bufflen));
                }
                else
                {
                    printf("\tUNSPEC");
                }
                pUnicast = pUnicast->Next;
            }
            printf("Number of Unicast Addresses: %d\n", i);
            pAddresses = pAddresses->Next;
        }
    }
    else {
        LPVOID lpMsgBuf;
        printf("Call to GetAdaptersAddresses failed.\n");
        if (FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            dwRetVal,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR)&lpMsgBuf,
            0,
            NULL)) {
            printf("\tError: %s", lpMsgBuf);
        }
        
    }
    if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) 
    {
        GlobalFree(pIPAddrTable);
        
    }
    // Make a second call to GetIpAddrTable to get the
    // actual data we want
    if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) == NO_ERROR) {
        printf("\t Address: %d\n", pIPAddrTable->table[0].dwAddr);
        printf("\t Mask:    %d\n", pIPAddrTable->table[0].dwMask);
        printf("\t Index:   %d\n", pIPAddrTable->table[0].dwIndex);
        printf("\t BCast:   %d\n", pIPAddrTable->table[0].dwBCastAddr);
        printf("\t Reasm:   %d\n", pIPAddrTable->table[0].dwReasmSize);
    }
    else {
        printf("Call to GetIpAddrTable failed.\n");
    }

    // IP and mask we will be adding

    iaIPAddress = inet_addr("192.168.0.27");
    imIPMask = inet_addr("255.255.255.0");
    
    if ((dwRetVal = AddIPAddress(iaIPAddress,
        imIPMask,
        pIPAddrTable->table[0].dwIndex,
        &NTEContext, &NTEInstance)) == NO_ERROR) 
    {
        printf("\tIP address added.\n");
    }
    
    else {
       
        printf("Error adding IP address.\n");

        if (FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 
            NULL, 
            dwRetVal, 
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),       // Default language
            (LPTSTR)&lpMsgBuf, 
            0, 
            NULL))

        {
            
            printf(" Error: %d");
        }
        LocalFree(lpMsgBuf);
    }
    
    if ((dwRetVal = DeleteIPAddress(NTEContext)) == NO_ERROR)
    {
        printf("\t IP Address Deleted.\n");
    }
    else {
        
        printf("\t Call to DeleteIPAddress failed.\n");
    }
    
    free(pAddresses);
    VirtualFree(&dwSize, 0, MEM_RELEASE);

    return 0;
}

相关问题