[Qemu-devel] [PATCH v2] qemu-ga: added windows support for 'guest-network-get-interfaces'

2014-09-29 Thread Kenth Andersson
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'

2014-10-08 Thread Kenth Andersson
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'

2014-09-25 Thread Kenth Andersson
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