c++windowswinapidhcp

About DhcpGetClientInfoV6 function in dhcpsapi.h


When I used the DhcpGetClientInfoV6 function in dhcpsapi.h, it returned code 2. After searching, I found the content, but I couldn't understand it.

$ .\Err_6.4.5.exe 2             

# for hex 0x2 / decimal 2 

  BTH_ERROR_NO_CONNECTION                                        bthdef.h 

  DEVICE_QUEUE_NOT_BUSY                                          bugcodes.h 

  CDERR_INITIALIZATION                                           cderr.h 

  CR_OUT_OF_MEMORY                                               cfgmgr32.h 

  DHCP_DROP_NOMEM                                                dhcpssdk.h 

  MD_ERROR_SUB400_INVALID_DEPTH                                  iiscnfg.h 

  MD_ERROR_SUB401_LOGON_CONFIG                                   iiscnfg.h 

  MD_ERROR_SUB403_READ_ACCESS_DENIED                             iiscnfg.h 

  MD_ERROR_SUB404_DENIED_BY_POLICY                               iiscnfg.h 

  MD_ERROR_SUB423_NO_CONFLICTING_LOCK                            iiscnfg.h 

  MD_ERROR_SUB502_PREMATURE_EXIT                                 iiscnfg.h 

  MD_ERROR_SUB503_APP_CONCURRENT                                 iiscnfg.h 

  IME_RS_NOIME                                                   ime.h 

# IME is not installed 

  RSVP_Err_POLICY                                                lpmapi.h 

  RSVP_Erv_Bandwidth                                             lpmapi.h 

# /* Insufficient bandwidth   */ 

  RSVP_Erv_No_Serv                                               lpmapi.h 

# /* Unknown Service      */ 

  RSVP_Erv_API                                                   lpmapi.h 

# /* API logic error */ 

  POLICY_ERRV_UNSUPPORTED_CREDENTIAL_TYPE                        lpmapi.h 

  POLICY_ERRV_GLOBAL_GRP_FLOW_COUNT                              lpmapi.h 

  MSIDBERROR_REQUIRED                                            msiquery.h 

# non-nullable column no null values allowed 

  NMERR_INVALID_HFILTER                                          netmon.h 

  SMART_INVALID_FLAG                                             ntdddisk.h 

# Invalid command flag 

  DS_NAME_ERROR_NOT_FOUND                                        ntdsapi.h 

  STATUS_WAIT_2                                                  ntstatus.h 

  ODBC_ERROR_INVALID_BUFF_LEN                                    odbcinst.h 

  MSDRI_S_MMI_PENDING                                            pbdaerrors.h 

  MFE_NOT_FORWARDING                                             routprot.h 

# not fwding for an unspecified reason 

  SCESTATUS_RECORD_NOT_FOUND                                     scesvc.h 

  SE_ERR_FNF                                                     shellapi.h 

# file not found 

  SNMP_ERRORSTATUS_NOSUCHNAME                                    snmp.h 

  SNMP_GENERICTRAP_LINKDOWN                                      snmp.h 

  ICERR_NEWPALETTE                                               vfw.h 

  WDSMCCLIENT_CATEGORY                                           wdsmcerr.h 

# WDS Multicast Client 

  WINBIO_FP_TOO_LOW                                              winbio_err.h 

# Position your finger higher on the fingerprint reader. 

  CMC_STATUS_FAILED                                              wincrypt.h 

  CMC_FAIL_BAD_REQUEST                                           wincrypt.h 

  DRM_S_MORE_DATA                                                windowsplayready.h 

  ERROR_FILE_NOT_FOUND                                           winerror.h 

# The system cannot find the file specified. 

  ERROR_LABEL_QUESTIONABLE                                       winioctl.h 

# Label could be invalid due to unit attention condition. 

  LDAP_PROTOCOL_ERROR                                            winldap.h 

  SNMP_ERROR_NOSUCHNAME                                          winsnmp.h 

# as an HRESULT: Severity: SUCCESS (0), FACILITY_NONE (0x0), Code 0x2 

# for hex 0x2 / decimal 2 

  WINBIO_FP_TOO_LOW                                              winbio_err.h 

# Position your finger higher on the fingerprint reader. 

# as an HRESULT: Severity: SUCCESS (0), FACILITY_NULL (0x0), Code 0x2 

  ERROR_FILE_NOT_FOUND                                           winerror.h 

# The system cannot find the file specified. 

# 43 matches found for "2"

The possible code is ERROR_FILE_NOT_FOUND in winerror.h. However, after I changed the corresponding code in winerror.h and recompiled, the return code was still 2. I can't determine where the problem occurred. Please help.

This my code:

std::string LookupIPv6(const std::string& ip) {

    struct in6_addr addr;

    if (inet_pton(AF_INET6, ip.c_str(), &addr) != 1) {

        throw std::invalid_argument("Invalid IPv6 address");

    }

    DHCP_SEARCH_INFO_V6 query;

    ZeroMemory(&query, sizeof(query));

    query.SearchType = Dhcpv6ClientIpAddress;

    memcpy(&query.SearchInfo.ClientIpAddress, &addr, sizeof(addr));

    LPDHCP_CLIENT_INFO_V6 result = nullptr;

    DWORD ret = DhcpGetClientInfoV6(nullptr, &query, &result);

    if (ret != ERROR_SUCCESS || !result) {

        FreeClientInfoMemoryV6(result);

        throw std::runtime_error("Failed to get DHCP client info, error code: " + std::to_string(ret));

    }

    char mac[64];

    BYTE* macData = result->ClientDUID.Data;

    snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",

        macData[0], macData[1], macData[2], macData[3], macData[4], macData[5]);

    FreeClientInfoMemoryV6(result);

    return std::string(mac);

}

Solution

  • Invalid IPv6 Format Provided

    I found the issue: the IPv6 address I was using for the query was incorrect. After fixing it, the following code worked as expected:

    int main() {
        DHCP_CLIENT_INFO_V6 clientInfo = { 0 };
        DHCP_IPV6_ADDRESS clientAddress = { 0 };
    
        // Correct IPv6 address: 2022::74c0:f5e6:feca:3fb3
        clientAddress.HighOrderBits = 0x2022000000000000;
        clientAddress.LowOrderBits = 0x74c0f5e6feca3fb3;
        clientInfo.ClientIpAddress = clientAddress;
    
        DHCP_SEARCH_INFO_V6 query{};
        query.SearchType = Dhcpv6ClientIpAddress;
        query.SearchInfo.ClientIpAddress = clientAddress;
    
        LPDHCP_CLIENT_INFO_V6 result{ 0 };
        DWORD ret = DhcpGetClientInfoV6(L"WIN-QI9RF26NQVN", &query, &result);
    
        if (ret == ERROR_SUCCESS) {
            //
            // Process the result...
            //
        } else {
            std::cout << std::to_string(ret) << std::endl;
        }
    }
    

    To make the implementation more robust, I wrote a helper function to convert IN6_ADDR to DHCP_IPV6_ADDRESS:

    // Converts IN6_ADDR to DHCP_IPV6_ADDRESS
    static void convertToDHCPIPv6(const IN6_ADDR* in6Addr, DHCP_IPV6_ADDRESS* dhcpAddr) {
        if (!in6Addr || !dhcpAddr) return;
    
        dhcpAddr->HighOrderBits = 0;
        dhcpAddr->LowOrderBits = 0;
        for (size_t i = 0; i < 4; i++) {
            dhcpAddr->HighOrderBits = (dhcpAddr->HighOrderBits << 16) | ntohs(in6Addr->u.Word[i]);
        }
        for (size_t i = 4; i < 8; i++) {
            dhcpAddr->LowOrderBits = (dhcpAddr->LowOrderBits << 16) | ntohs(in6Addr->u.Word[i]);
        }
    }
    

    Here’s the complete, improved implementation:

    static std::string LookupIPv6(const std::string& ip) {
        IN6_ADDR addr{};
        if (inet_pton(AF_INET6, ip.c_str(), &addr) != 1) {
            throw std::invalid_argument("Invalid IPv6 address");
        }
    
        DHCP_IPV6_ADDRESS clientIp;
        convertToDHCPIPv6(&addr, &clientIp);
    
        DHCP_SEARCH_INFO_V6 query{};
        query.SearchType = Dhcpv6ClientIpAddress;
        query.SearchInfo.ClientIpAddress = clientIp;
    
        LPDHCP_CLIENT_INFO_V6 result{ 0 };
        DWORD ret = DhcpGetClientInfoV6(DHCPSERVER, &query, &result);
    
        if (ret != ERROR_SUCCESS || !result) {
            std::string msg;
            switch (ret) {
            case ERROR_DHCP_JET_ERROR:
            case ERROR_DHCP_INVALID_DHCP_CLIENT:
                msg = "DHCP client not found.";
                break;
            default:
                msg = "Failed to get DHCP client info, error code : " + std::to_string(ret);
                break;
            }
            FreeClientInfoMemoryV6(result);
            throw std::runtime_error(msg);
        }
    
        char mac[128]{};
        BYTE* macData = result->ClientDUID.Data;
        size_t macLength = result->ClientDUID.DataLength;
    
        size_t len = macLength < sizeof(mac) / 3 ? macLength : sizeof(mac) / 3;
    
        char* macPtr = mac;
        for (size_t i = 0; i < len; i++) {
            int printed = (i == len - 1) ?
                snprintf(macPtr, sizeof(mac) - (macPtr - mac), "%02x", macData[i]) :
                snprintf(macPtr, sizeof(mac) - (macPtr - mac), "%02x:", macData[i]);
            macPtr += printed;
        }
        FreeClientInfoMemoryV6(result);
    
        return std::string(mac);
    }
    

    Issue: Status Code Returns 2

    Although this code now works correctly, I am still unsure why the status code returns 2. If anyone can provide insights into this specific error code, it would be much appreciated.