Commit df83eabd authored by ZhiPeng Lu's avatar ZhiPeng Lu Committed by Michael Roth
Browse files

qga: replace GetIfEntry with GetIfEntry2 for interface stats



The data obtained by GetIfEntry is 32 bits, and it may overflow. Thus
using GetIfEntry2 instead of GetIfEntry.

Signed-off-by: default avatarZhiPeng Lu <lu.zhipeng@zte.com.cn>
*avoid CamelCase variable names
*update field names for MIB_IFROW -> MIB_IF_ROW2
*dynamically probe for GetIfIndex2 to deal with older OSs
*check return value from get_interface_index
Signed-off-by: default avatarMichael Roth <mdroth@linux.vnet.ibm.com>
parent b2996bb4
Loading
Loading
Loading
Loading
+38 −16
Original line number Diff line number Diff line
@@ -1169,25 +1169,47 @@ static DWORD get_interface_index(const char *guid)
        return index;
    }
}

typedef NETIOAPI_API (WINAPI *GetIfEntry2Func)(PMIB_IF_ROW2 Row);

static int guest_get_network_stats(const char *name,
                                   GuestNetworkInterfaceStat *stats)
{
    OSVERSIONINFO os_ver;

    os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    GetVersionEx(&os_ver);
    if (os_ver.dwMajorVersion >= 6) {
        MIB_IF_ROW2 a_mid_ifrow;
        GetIfEntry2Func getifentry2_ex;
        DWORD if_index = 0;
    MIB_IFROW a_mid_ifrow;
    memset(&a_mid_ifrow, 0, sizeof(a_mid_ifrow));
        HMODULE module = GetModuleHandle("iphlpapi");
        PVOID func = GetProcAddress(module, "GetIfEntry2");

        if (func == NULL) {
            return -1;
        }

        getifentry2_ex = (GetIfEntry2Func)func;
        if_index = get_interface_index(name);
    a_mid_ifrow.dwIndex = if_index;
    if (NO_ERROR == GetIfEntry(&a_mid_ifrow)) {
        stats->rx_bytes = a_mid_ifrow.dwInOctets;
        stats->rx_packets = a_mid_ifrow.dwInUcastPkts;
        stats->rx_errs = a_mid_ifrow.dwInErrors;
        stats->rx_dropped = a_mid_ifrow.dwInDiscards;
        stats->tx_bytes = a_mid_ifrow.dwOutOctets;
        stats->tx_packets = a_mid_ifrow.dwOutUcastPkts;
        stats->tx_errs = a_mid_ifrow.dwOutErrors;
        stats->tx_dropped = a_mid_ifrow.dwOutDiscards;
        if (if_index == (DWORD)~0) {
            return -1;
        }

        memset(&a_mid_ifrow, 0, sizeof(a_mid_ifrow));
        a_mid_ifrow.InterfaceIndex = if_index;
        if (NO_ERROR == getifentry2_ex(&a_mid_ifrow)) {
            stats->rx_bytes = a_mid_ifrow.InOctets;
            stats->rx_packets = a_mid_ifrow.InUcastPkts;
            stats->rx_errs = a_mid_ifrow.InErrors;
            stats->rx_dropped = a_mid_ifrow.InDiscards;
            stats->tx_bytes = a_mid_ifrow.OutOctets;
            stats->tx_packets = a_mid_ifrow.OutUcastPkts;
            stats->tx_errs = a_mid_ifrow.OutErrors;
            stats->tx_dropped = a_mid_ifrow.OutDiscards;
            return 0;
        }
    }
    return -1;
}