qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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


From: Kenth Andersson
Subject: [Qemu-devel] [PATCH] qemu-ga: added windows support for 'guest-network-get-interfaces'
Date: Fri, 26 Sep 2014 00:09:57 +0200

This is my first patch so I hope I got everything right.



Signed-off-by: Kenth Andersson <address@hidden>
---
 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 <glib.h>
 #include <wtypes.h>
 #include <powrprof.h>
+#include <winsock2.h>
+#include <iphlpapi.h>
+#include <ws2tcpip.h>
 #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, &bufLen)) == NO_ERROR) {
+
+        /* Iterate all adapter addresses */
+
+        current_adapter_address = adapter_addresses;
+
+        while (current_adapter_address) {
+            /* Check if this adapter is up and running */
+
+            if ((current_adapter_address->OperStatus == IfOperStatusUp) &&
+                ((current_adapter_address->IfType == IF_TYPE_ETHERNET_CSMACD) 
||
+                 (current_adapter_address->IfType == IF_TYPE_IEEE80211) ||
+                 (current_adapter_address->IfType ==
+                                            IF_TYPE_SOFTWARE_LOOPBACK))) {
+
+                int len = 0;
+                char* temp_description = 0;
+
+                GuestNetworkInterfaceList* interface_list =
+                                            g_malloc0(sizeof(*interface_list));
+                if (interface_list == NULL) {
+                    goto cleanup;
+                }
+
+                interface_list->value = 
g_malloc0(sizeof(*interface_list->value));
+                if (interface_list->value == NULL) {
+                    g_free(interface_list);
+                    goto cleanup;
+                }
+
+                len = wcslen(current_adapter_address->Description) + 1;
+                temp_description = g_malloc0(len);
+                if (temp_description == NULL) {
+                    g_free(interface_list->value);
+                    g_free(interface_list);
+                    goto cleanup;
+                }
+
+                wcstombs(temp_description,
+                         current_adapter_address->Description,
+                         len);
+                interface_list->value->name = g_strdup(temp_description);
+                g_free(temp_description);
+
+                if (curr_item == NULL) {
+                    head = curr_item = interface_list;
+                } else {
+                    curr_item->next = interface_list;
+                    curr_item = interface_list;
+                }
+
+                /* Format MAC address */
+                interface_list->value->hardware_address =
+                    g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x",
+                            (int) current_adapter_address->PhysicalAddress[0],
+                            (int) current_adapter_address->PhysicalAddress[1],
+                            (int) current_adapter_address->PhysicalAddress[2],
+                            (int) current_adapter_address->PhysicalAddress[3],
+                            (int) current_adapter_address->PhysicalAddress[4],
+                            (int) current_adapter_address->PhysicalAddress[5]);
+
+
+                interface_list->value->has_hardware_address = true;
+
+                /* Iterate all unicast addresses of this adapter */
+                GuestIpAddressList **address_list =
+                                        &interface_list->value->ip_addresses;
+
+                GuestIpAddressList *address_item = NULL;
+
+                adapter_unicast_address =
+                        current_adapter_address->FirstUnicastAddress;
+
+                while (adapter_unicast_address) {
+                    SOCKET_ADDRESS* saddr = &adapter_unicast_address->Address;
+                    int socklen = 0;
+                    char buffer[50];
+                    DWORD len = 50;
+
+                    /* Allocate an address item */
+                    address_item = g_malloc0(sizeof(*address_item));
+                    if (address_item == NULL) {
+                        goto cleanup;
+                    }
+                    address_item->value =
+                                    g_malloc0(sizeof(*address_item->value));
+
+                    if (address_item->value == NULL) {
+                        g_free(address_item);
+                        goto cleanup;
+                    }
+
+                    /* Is this IPv4 or IPv6 */
+                    if (saddr->lpSockaddr->sa_family == AF_INET) {
+                        address_item->value->ip_address_type =
+                                                GUEST_IP_ADDRESS_TYPE_IPV4;
+                        socklen = sizeof(struct sockaddr_in);
+                    } else if (saddr->lpSockaddr->sa_family == AF_INET6) {
+                        address_item->value->ip_address_type =
+                                                GUEST_IP_ADDRESS_TYPE_IPV6;
+                        socklen = sizeof(struct sockaddr_in6);
+                    }
+
+                    /* Temporary buffer to hold human readable address */
+                    WSAAddressToString(saddr->lpSockaddr,
+                                       socklen, NULL, buffer, &len);
+                    buffer[len] = 0;
+                    address_item->value->ip_address = g_strdup(buffer);
+
+                    /* Get the prefix for this address */
+                    address_item->value->prefix =
+                              get_prefix(current_adapter_address->FirstPrefix,
+                                         saddr->lpSockaddr, socklen);
+
+                    /* Add this address to the end of the address list */
+                    while (*address_list && (*address_list)->next) {
+                        address_list = &(*address_list)->next;
+                    }
+
+                    if (!*address_list) {
+                        *address_list = address_item;
+                    } else {
+                        (*address_list)->next = address_item;
+                    }
+
+                    /* Jump to next address */
+                    adapter_unicast_address = adapter_unicast_address->Next;
+                }
+                interface_list->value->has_ip_addresses = true;
+
+            }
+
+            /* Jump to next adapter */
+            current_adapter_address = current_adapter_address->Next;
+        }
+    }
+
+cleanup:
+
+    /* Free the adapter list */
+    if (adapter_addresses != NULL) {
+        HeapFree(GetProcessHeap(), 0, adapter_addresses);
+    }
+
+    /* Cleanup WinSock32 */
+    WSACleanup();
+
+    return head;
 }
 
 int64_t qmp_guest_get_time(Error **errp)
-- 
1.8.5.2 (Apple Git-48)





reply via email to

[Prev in Thread] Current Thread [Next in Thread]