[Qemu-devel] [PATCH v2] qemu-ga: added windows support for 'guest-network-get-interfaces'
Implementation of guest-network-get-interfaces for windows Signed-off-by: Kenth Andersson --- configure| 2 +- qga/commands-win32.c | 247 ++- 2 files changed, 244 insertions(+), 5 deletions(-) diff --git a/configure b/configure index 681abfc..7c6c60c 100755 --- a/configure +++ b/configure @@ -717,7 +717,7 @@ EOF sysconfdir="\${prefix}" local_statedir= confsuffix="" - libs_qga="-lws2_32 -lwinmm -lpowrprof $libs_qga" + libs_qga="-lws2_32 -lwinmm -lpowrprof -liphlpapi $libs_qga" fi werror="" diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 3bcbeae..fb6fdba 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include #include "qga/guest-agent-core.h" #include "qga/vss-win32.h" #include "qga-qmp-commands.h" @@ -29,6 +32,9 @@ (365 * (1970 - 1601) + \ (1970 - 1601) / 4 - 3)) +/* Defines the max length of an IPv6 address in human readable format + pad */ +#define MAX_IPv6_LEN 50 + static void acquire_privilege(const char *name, Error **errp) { HANDLE token = NULL; @@ -359,10 +365,244 @@ void qmp_guest_suspend_hybrid(Error **errp) error_set(errp, QERR_UNSUPPORTED); } +static int get_prefix_length(PIP_ADAPTER_PREFIX prefix, + SOCKET_ADDRESS *sockaddr, int socklen) +{ +PIP_ADAPTER_PREFIX p; +struct sockaddr *addr = sockaddr->lpSockaddr; + +for (p = prefix; p; p = p->Next) { +/* Compare the ip-adderss address family with the prefix + * address family */ +if (addr->sa_family == p->Address.lpSockaddr->sa_family) { +int num_bytes = p->PrefixLength / 8; +unsigned char *src = 0; +unsigned char *dst = 0; +int remaining_bits; + +if (addr->sa_family == AF_INET) { +struct sockaddr_in *sin = (struct sockaddr_in *)addr; +src = (unsigned char *)&(sin->sin_addr.s_addr); +} else if (addr->sa_family == AF_INET6) { +struct sockaddr_in6 *sin = (struct sockaddr_in6 *)addr; +src = (unsigned char *)sin->sin6_addr.s6_addr; +} + +if (p->Address.lpSockaddr->sa_family == AF_INET) { +struct sockaddr_in *sin = +(struct sockaddr_in *)p->Address.lpSockaddr; +dst = (unsigned char *)&(sin->sin_addr.s_addr); +} else if (p->Address.lpSockaddr->sa_family == AF_INET6) { +struct sockaddr_in6 *sin = +(struct sockaddr_in6 *)p->Address.lpSockaddr; +dst = (unsigned char *)sin->sin6_addr.s6_addr; +} + +/* If non of the addresses are in correct format we will continue + * to next one */ +if (src == 0 || dst == 0) { +continue; +} + +/* Check if prefix network is the same network as we are testing + * start with whole bytes */ + +if (memcmp(src, dst, num_bytes) != 0) { +continue; +} + +/* Check the remaning bits */ +remaining_bits = p->PrefixLength % 8; + +if (remaining_bits != 0) { +unsigned char mask = 0xff << (8 - remaining_bits); +int i = num_bytes; + +if ((src[i] & mask) != (dst[i] & mask)) { +continue; +} +} + +return p->PrefixLength; +} +} +return 0; +} + + + GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) { -error_set(errp, QERR_UNSUPPORTED); -return NULL; +GuestNetworkInterfaceList *head = NULL, *curr_item = NULL; +DWORD ret_val; + +PIP_ADAPTER_ADDRESSES adpt_addrs; +PIP_ADAPTER_ADDRESSES curr_adpt_addrs; +PIP_ADAPTER_UNICAST_ADDRESS adpt_uc_addr; + +/* GetAdaptersAddresses requires ULONG */ +ULONG bufLen = sizeof(IP_ADAPTER_ADDRESSES); + +/* Startup WinSock32 */ +WORD ws_version_requested = MAKEWORD(2, 2); +WSADATA ws_data; +WSAStartup(ws_version_requested, &ws_data); + +/* Allocate adapter address list with one entry, used to + * fetch the read length needed by GetAdapterAddresses */ +adpt_addrs = g_malloc(sizeof(IP_ADAPTER_ADDRESSES)); + +/* Get adapter adresses and if it doesn't fit in adpt_addrs + * we will realloc */ +if (GetAdaptersAddresses(AF_UNSPEC, + GAA_FLAG_INCLUDE_PREFIX, + NULL, + adpt_addrs, &bufLen) == +ERROR_BUFFER_OVERFLOW) { + +
Re: [Qemu-devel] [PATCH v2] qemu-ga: added windows support for 'guest-network-get-interfaces'
I will take care of the below items as soon as I get some free time. /Kenth On 01 Oct 2014, at 19:45, Michael Roth wrote: > Quoting Kenth Andersson (2014-09-29 13:22:54) >> Implementation of guest-network-get-interfaces for windows >> >> >> Signed-off-by: Kenth Andersson > > Thanks! I've been testing the functionality and it seems work nicely. Some > review comments below though: > >> --- >> configure| 2 +- >> qga/commands-win32.c | 247 >> ++- >> 2 files changed, 244 insertions(+), 5 deletions(-) >> >> diff --git a/configure b/configure >> index 681abfc..7c6c60c 100755 >> --- a/configure >> +++ b/configure >> @@ -717,7 +717,7 @@ EOF >> sysconfdir="\${prefix}" >> local_statedir= >> confsuffix="" >> - libs_qga="-lws2_32 -lwinmm -lpowrprof $libs_qga" >> + libs_qga="-lws2_32 -lwinmm -lpowrprof -liphlpapi $libs_qga" >> fi >> >> werror="" >> diff --git a/qga/commands-win32.c b/qga/commands-win32.c >> index 3bcbeae..fb6fdba 100644 >> --- a/qga/commands-win32.c >> +++ b/qga/commands-win32.c >> @@ -14,6 +14,9 @@ >> #include >> #include >> #include >> +#include >> +#include >> +#include >> #include "qga/guest-agent-core.h" >> #include "qga/vss-win32.h" >> #include "qga-qmp-commands.h" >> @@ -29,6 +32,9 @@ >>(365 * (1970 - 1601) + \ >> (1970 - 1601) / 4 - 3)) >> >> +/* Defines the max length of an IPv6 address in human readable format + pad >> */ >> +#define MAX_IPv6_LEN 50 >> + >> static void acquire_privilege(const char *name, Error **errp) >> { >> HANDLE token = NULL; >> @@ -359,10 +365,244 @@ void qmp_guest_suspend_hybrid(Error **errp) >> error_set(errp, QERR_UNSUPPORTED); >> } >> >> +static int get_prefix_length(PIP_ADAPTER_PREFIX prefix, >> + SOCKET_ADDRESS *sockaddr, int socklen) >> +{ >> +PIP_ADAPTER_PREFIX p; >> +struct sockaddr *addr = sockaddr->lpSockaddr; >> + >> +for (p = prefix; p; p = p->Next) { >> +/* Compare the ip-adderss address family with the prefix >> + * address family */ >> +if (addr->sa_family == p->Address.lpSockaddr->sa_family) { >> +int num_bytes = p->PrefixLength / 8; >> +unsigned char *src = 0; >> +unsigned char *dst = 0; >> +int remaining_bits; >> + >> +if (addr->sa_family == AF_INET) { >> +struct sockaddr_in *sin = (struct sockaddr_in *)addr; >> +src = (unsigned char *)&(sin->sin_addr.s_addr); >> +} else if (addr->sa_family == AF_INET6) { >> +struct sockaddr_in6 *sin = (struct sockaddr_in6 *)addr; >> +src = (unsigned char *)sin->sin6_addr.s6_addr; >> +} >> + >> +if (p->Address.lpSockaddr->sa_family == AF_INET) { >> +struct sockaddr_in *sin = >> +(struct sockaddr_in *)p->Address.lpSockaddr; >> +dst = (unsigned char *)&(sin->sin_addr.s_addr); >> +} else if (p->Address.lpSockaddr->sa_family == AF_INET6) { >> +struct sockaddr_in6 *sin = >> +(struct sockaddr_in6 *)p->Address.lpSockaddr; >> +dst = (unsigned char *)sin->sin6_addr.s6_addr; >> +} >> + >> +/* If non of the addresses are in correct format we will >> continue >> + * to next one */ >> +if (src == 0 || dst == 0) { >> +continue; >> +} >> + >> +/* Check if prefix network is the same network as we are testing >> + * start with whole bytes */ >> + >> +if (memcmp(src, dst, num_bytes) != 0) { >> +continue; >> +} >> + >> +/* Check the remaning bits */ >> +remaining_bits = p->PrefixLength % 8; >> + >> +if (remaining_bits != 0) { >> +unsigned char mask = 0xff << (8 - remaining_bits); >> +int i = num_bytes; >> + >> +if ((src[i] & mask) != (dst[i] & mask)) { >> +continue; >> +
[Qemu-devel] [PATCH] qemu-ga: added windows support for 'guest-network-get-interfaces'
This is my first patch so I hope I got everything right. Signed-off-by: Kenth Andersson --- configure| 2 +- qga/commands-win32.c | 267 ++- 2 files changed, 266 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 862f6d2..1d2aeae 100755 --- a/configure +++ b/configure @@ -717,7 +717,7 @@ EOF sysconfdir="\${prefix}" local_statedir= confsuffix="" - libs_qga="-lws2_32 -lwinmm -lpowrprof $libs_qga" + libs_qga="-lws2_32 -lwinmm -lpowrprof -liphlpapi $libs_qga" fi werror="" diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 3bcbeae..e084573 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include #include "qga/guest-agent-core.h" #include "qga/vss-win32.h" #include "qga-qmp-commands.h" @@ -359,10 +362,270 @@ void qmp_guest_suspend_hybrid(Error **errp) error_set(errp, QERR_UNSUPPORTED); } +static int get_prefix(PIP_ADAPTER_PREFIX prefix, + LPSOCKADDR sockaddr, int socklen) +{ +PIP_ADAPTER_PREFIX p = prefix; + +for (; p != NULL; p = p->Next) +{ +if (sockaddr->sa_family == p->Address.lpSockaddr->sa_family) +{ +int num_bytes = p->PrefixLength / 8; +int i = 0; +char* src = 0; +char* dst = 0; +int remaining_bits = 0; + +if (sockaddr->sa_family == AF_INET) +{ +struct sockaddr_in* sin = (struct sockaddr_in*)sockaddr; +src = (char*)sin->sin_addr.s_addr; +} +else if (sockaddr->sa_family == AF_INET6) +{ +struct sockaddr_in6* sin = (struct sockaddr_in6*)sockaddr; +src = (char*)sin->sin6_addr.s6_addr; +} +if (prefix->Address.lpSockaddr->sa_family == AF_INET) +{ +struct sockaddr_in* sin = +(struct sockaddr_in*)prefix->Address.lpSockaddr; +dst = (char*)sin->sin_addr.s_addr; +} +else if (prefix->Address.lpSockaddr->sa_family == AF_INET6) +{ +struct sockaddr_in6* sin = +(struct sockaddr_in6*)prefix->Address.lpSockaddr; +dst = (char*)sin->sin6_addr.s6_addr; +} +if ((src == 0) || (dst == 0)) +{ +continue; +} + +for (; i < num_bytes; ++i) +{ +if (src[i] != dst[i]) +{ +continue; +} +} + +remaining_bits = p->PrefixLength % 8; + +if (remaining_bits != 0) +{ +unsigned char mask = 0xff << (8 - remaining_bits); +int i = num_bytes; + +if ((src[i] & mask) != (dst[i] & mask)) +{ +continue; +} +} + +return p->PrefixLength; +} +} +return 0; +} + + + GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) { -error_set(errp, QERR_UNSUPPORTED); -return NULL; +GuestNetworkInterfaceList *head = NULL, *curr_item = NULL; +DWORD ret_val = 0; + +/* Startup WinSock32 */ +WORD ws_version_requested = MAKEWORD(2, 2); +WSADATA ws_data; +WSAStartup(ws_version_requested, &ws_data); + + +PIP_ADAPTER_ADDRESSES adapter_addresses = NULL; +PIP_ADAPTER_ADDRESSES current_adapter_address = NULL; +PIP_ADAPTER_UNICAST_ADDRESS adapter_unicast_address = NULL; + +unsigned long bufLen = sizeof(IP_ADAPTER_ADDRESSES); + +/* Allocate adapter address list */ +adapter_addresses = (IP_ADAPTER_ADDRESSES*) +HeapAlloc(GetProcessHeap(), 0, sizeof(IP_ADAPTER_ADDRESSES)); +if (adapter_addresses == NULL) { +goto cleanup; +} + +/* Get adapter adresses and if it doesn't fit in adapter_addresses + * we will realloc */ +if (GetAdaptersAddresses(AF_UNSPEC, + GAA_FLAG_INCLUDE_PREFIX, + NULL, + adapter_addresses, &bufLen) == +ERROR_BUFFER_OVERFLOW) { + +HeapFree(GetProcessHeap(), 0, adapter_addresses); + +adapter_addresses = (IP_ADAPTER_ADDRESSES*) +HeapAlloc(GetProcessHeap(), 0, bufLen); + +if (adapter_addresses == NULL) { +goto cleanup; +} +} + +/* Get adapter address list */ +if ((ret_val = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, + NULL, + adapter_addresses, &a