All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v6 0/2] qga: qmp_guest_network_get_interfaces for win32
@ 2015-06-02 17:41 Kirk Allan
  2015-06-02 17:41 ` [Qemu-devel] [PATCH v6 1/2] qga: add win32 library iphlpapi Kirk Allan
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Kirk Allan @ 2015-06-02 17:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: okrishtal, pbonzini, mdroth, sw

Changes from v5:
- Patch 1/2 removed testing for WINVER in QEMU_CFLAGS.

Changes from v4:
- Fixed up the commit messages to remove the utf-8 characters.

Changes from v3:
- Patch 1/2 removed setting ARCH_$ARCH
- Patch 2/2 implemented feedback from v3. Use WSAAddressToString for
inet_ntop functionality.  WSAStringToAddress is available in all versions
of Windows.

This patch set is to implement qmp_guest_network_get_interfaces for win32.

This patch set contains two patches: configuration and implementation.

The configuration patch adds the iphlpapi library.  The implementation
patch for commands-win32.c takes advantage of _WIN32_WINNT if set to 0x600
or greater for Windows Vista/2008 guests or newer to use OnLinkPrefixLength
for prefixes.  WSAStringToAddress is used for inet_ntop functionality.

Kirk Allan (2):
  qga: add win32 library iphlpapi
  qga: win32 qmp_guest_network_get_interfaces implementation

 configure            |   2 +-
 qga/commands-win32.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 218 insertions(+), 4 deletions(-)

-- 
1.8.5.6

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH v6 1/2] qga: add win32 library iphlpapi
  2015-06-02 17:41 [Qemu-devel] [PATCH v6 0/2] qga: qmp_guest_network_get_interfaces for win32 Kirk Allan
@ 2015-06-02 17:41 ` Kirk Allan
  2015-06-02 17:41 ` [Qemu-devel] [PATCH v6 2/2] qga: win32 qmp_guest_network_get_interfaces implementation Kirk Allan
  2015-07-07  1:33 ` [Qemu-devel] [PATCH v6 0/2] qga: qmp_guest_network_get_interfaces for win32 Michael Roth
  2 siblings, 0 replies; 4+ messages in thread
From: Kirk Allan @ 2015-06-02 17:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kirk Allan, okrishtal, mdroth, sw, pbonzini

Add the iphlpapi library to use APIs such as GetAdaptersInfo and
GetAdaptersAddresses.

Signed-off-by: Kirk Allan <kallan@suse.com>
---
 configure | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure b/configure
index 4e2f78a..60df96d 100755
--- a/configure
+++ b/configure
@@ -724,7 +724,7 @@ if test "$mingw32" = "yes" ; then
   sysconfdir="\${prefix}"
   local_statedir=
   confsuffix=""
-  libs_qga="-lws2_32 -lwinmm -lpowrprof $libs_qga"
+  libs_qga="-lws2_32 -lwinmm -lpowrprof -liphlpapi $libs_qga"
 fi
 
 werror=""
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH v6 2/2] qga: win32 qmp_guest_network_get_interfaces implementation
  2015-06-02 17:41 [Qemu-devel] [PATCH v6 0/2] qga: qmp_guest_network_get_interfaces for win32 Kirk Allan
  2015-06-02 17:41 ` [Qemu-devel] [PATCH v6 1/2] qga: add win32 library iphlpapi Kirk Allan
@ 2015-06-02 17:41 ` Kirk Allan
  2015-07-07  1:33 ` [Qemu-devel] [PATCH v6 0/2] qga: qmp_guest_network_get_interfaces for win32 Michael Roth
  2 siblings, 0 replies; 4+ messages in thread
From: Kirk Allan @ 2015-06-02 17:41 UTC (permalink / raw)
  To: qemu-devel; +Cc: Kirk Allan, okrishtal, mdroth, sw, pbonzini

By default, IPv4 prefixes will be derived by matching the address
to those returned by GetAdaptersInfo.  IPv6 prefixes can not be
matched this way due to the unpredictable order of entries.

In Windows Vista/2008 guests and newer, both IPv4 and IPv6 prefixes
can be retrieved from OnLinkPrefixLength.  Setting --extra-cflags
in the build configuration to "-D_WIN32_WINNT=0x600"
or greater makes OnLinkPrefixLength available.  Setting --extra-cflags
is not required and if not set, the default approach to get the prefix
will be taken.

Signed-off-by: Kirk Allan <kallan@suse.com>
---
 qga/commands-win32.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 217 insertions(+), 3 deletions(-)

diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 3ef0549..209eba7 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -16,11 +16,17 @@
 #include <powrprof.h>
 #include <stdio.h>
 #include <string.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <ws2ipdef.h>
+#include <iptypes.h>
+#include <iphlpapi.h>
 #include "qga/guest-agent-core.h"
 #include "qga/vss-win32.h"
 #include "qga-qmp-commands.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/queue.h"
+#include "qemu/host-utils.h"
 
 #ifndef SHTDN_REASON_FLAG_PLANNED
 #define SHTDN_REASON_FLAG_PLANNED 0x80000000
@@ -589,12 +595,220 @@ void qmp_guest_suspend_hybrid(Error **errp)
     error_set(errp, QERR_UNSUPPORTED);
 }
 
-GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
+static IP_ADAPTER_ADDRESSES *guest_get_adapters_addresses(Error **errp)
 {
-    error_set(errp, QERR_UNSUPPORTED);
+    IP_ADAPTER_ADDRESSES *adptr_addrs = NULL;
+    ULONG adptr_addrs_len = 0;
+    DWORD ret;
+
+    /* Call the first time to get the adptr_addrs_len. */
+    GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX,
+                         NULL, adptr_addrs, &adptr_addrs_len);
+
+    adptr_addrs = g_malloc(adptr_addrs_len);
+    ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX,
+                               NULL, adptr_addrs, &adptr_addrs_len);
+    if (ret != ERROR_SUCCESS) {
+        error_setg_win32(errp, ret, "failed to get adapters addresses");
+        g_free(adptr_addrs);
+        adptr_addrs = NULL;
+    }
+    return adptr_addrs;
+}
+
+static char *guest_wctomb_dup(WCHAR *wstr)
+{
+    char *str;
+    size_t i;
+
+    i = wcslen(wstr) + 1;
+    str = g_malloc(i);
+    WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,
+                        wstr, -1, str, i, NULL, NULL);
+    return str;
+}
+
+static char *guest_addr_to_str(IP_ADAPTER_UNICAST_ADDRESS *ip_addr,
+                               Error **errp)
+{
+    char addr_str[INET6_ADDRSTRLEN + INET_ADDRSTRLEN];
+    DWORD len;
+    int ret;
+
+    if (ip_addr->Address.lpSockaddr->sa_family == AF_INET ||
+            ip_addr->Address.lpSockaddr->sa_family == AF_INET6) {
+        len = sizeof(addr_str);
+        ret = WSAAddressToString(ip_addr->Address.lpSockaddr,
+                                 ip_addr->Address.iSockaddrLength,
+                                 NULL,
+                                 addr_str,
+                                 &len);
+        if (ret != 0) {
+            error_setg_win32(errp, WSAGetLastError(),
+                "failed address presentation form conversion");
+            return NULL;
+        }
+        return g_strdup(addr_str);
+    }
     return NULL;
 }
 
+#if (_WIN32_WINNT >= 0x0600)
+static int64_t guest_ip_prefix(IP_ADAPTER_UNICAST_ADDRESS *ip_addr)
+{
+    /* For Windows Vista/2008 and newer, use the OnLinkPrefixLength
+     * field to obtain the prefix.
+     */
+    return ip_addr->OnLinkPrefixLength;
+}
+#else
+/* When using the Windows XP and 2003 build environment, do the best we can to
+ * figure out the prefix.
+ */
+static IP_ADAPTER_INFO *guest_get_adapters_info(void)
+{
+    IP_ADAPTER_INFO *adptr_info = NULL;
+    ULONG adptr_info_len = 0;
+    DWORD ret;
+
+    /* Call the first time to get the adptr_info_len. */
+    GetAdaptersInfo(adptr_info, &adptr_info_len);
+
+    adptr_info = g_malloc(adptr_info_len);
+    ret = GetAdaptersInfo(adptr_info, &adptr_info_len);
+    if (ret != ERROR_SUCCESS) {
+        g_free(adptr_info);
+        adptr_info = NULL;
+    }
+    return adptr_info;
+}
+
+static int64_t guest_ip_prefix(IP_ADAPTER_UNICAST_ADDRESS *ip_addr)
+{
+    int64_t prefix = -1; /* Use for AF_INET6 and unknown/undetermined values. */
+    IP_ADAPTER_INFO *adptr_info, *info;
+    IP_ADDR_STRING *ip;
+    struct in_addr *p;
+
+    if (ip_addr->Address.lpSockaddr->sa_family != AF_INET) {
+        return prefix;
+    }
+    adptr_info = guest_get_adapters_info();
+    if (adptr_info == NULL) {
+        return prefix;
+    }
+
+    /* Match up the passed in ip_addr with one found in adaptr_info.
+     * The matching one in adptr_info will have the netmask.
+     */
+    p = &((struct sockaddr_in *)ip_addr->Address.lpSockaddr)->sin_addr;
+    for (info = adptr_info; info; info = info->Next) {
+        for (ip = &info->IpAddressList; ip; ip = ip->Next) {
+            if (p->S_un.S_addr == inet_addr(ip->IpAddress.String)) {
+                prefix = ctpop32(inet_addr(ip->IpMask.String));
+                goto out;
+            }
+        }
+    }
+out:
+    g_free(adptr_info);
+    return prefix;
+}
+#endif
+
+GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
+{
+    IP_ADAPTER_ADDRESSES *adptr_addrs, *addr;
+    IP_ADAPTER_UNICAST_ADDRESS *ip_addr = NULL;
+    GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
+    GuestIpAddressList *head_addr, *cur_addr;
+    GuestNetworkInterfaceList *info;
+    GuestIpAddressList *address_item = NULL;
+    unsigned char *mac_addr;
+    char *addr_str;
+    WORD wsa_version;
+    WSADATA wsa_data;
+    int ret;
+
+    adptr_addrs = guest_get_adapters_addresses(errp);
+    if (adptr_addrs == NULL) {
+        return NULL;
+    }
+
+    /* Make WSA APIs available. */
+    wsa_version = MAKEWORD(2, 2);
+    ret = WSAStartup(wsa_version, &wsa_data);
+    if (ret != 0) {
+        error_setg_win32(errp, ret, "failed socket startup");
+        goto out;
+    }
+
+    for (addr = adptr_addrs; addr; addr = addr->Next) {
+        info = g_malloc0(sizeof(*info));
+
+        if (cur_item == NULL) {
+            head = cur_item = info;
+        } else {
+            cur_item->next = info;
+            cur_item = info;
+        }
+
+        info->value = g_malloc0(sizeof(*info->value));
+        info->value->name = guest_wctomb_dup(addr->FriendlyName);
+
+        if (addr->PhysicalAddressLength != 0) {
+            mac_addr = addr->PhysicalAddress;
+
+            info->value->hardware_address =
+                g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x",
+                                (int) mac_addr[0], (int) mac_addr[1],
+                                (int) mac_addr[2], (int) mac_addr[3],
+                                (int) mac_addr[4], (int) mac_addr[5]);
+
+            info->value->has_hardware_address = true;
+        }
+
+        head_addr = NULL;
+        cur_addr = NULL;
+        for (ip_addr = addr->FirstUnicastAddress;
+                ip_addr;
+                ip_addr = ip_addr->Next) {
+            addr_str = guest_addr_to_str(ip_addr, errp);
+            if (addr_str == NULL) {
+                continue;
+            }
+
+            address_item = g_malloc0(sizeof(*address_item));
+
+            if (!cur_addr) {
+                head_addr = cur_addr = address_item;
+            } else {
+                cur_addr->next = address_item;
+                cur_addr = address_item;
+            }
+
+            address_item->value = g_malloc0(sizeof(*address_item->value));
+            address_item->value->ip_address = addr_str;
+            address_item->value->prefix = guest_ip_prefix(ip_addr);
+            if (ip_addr->Address.lpSockaddr->sa_family == AF_INET) {
+                address_item->value->ip_address_type =
+                    GUEST_IP_ADDRESS_TYPE_IPV4;
+            } else if (ip_addr->Address.lpSockaddr->sa_family == AF_INET6) {
+                address_item->value->ip_address_type =
+                    GUEST_IP_ADDRESS_TYPE_IPV6;
+            }
+        }
+        if (head_addr) {
+            info->value->has_ip_addresses = true;
+            info->value->ip_addresses = head_addr;
+        }
+    }
+    WSACleanup();
+out:
+    g_free(adptr_addrs);
+    return head;
+}
+
 int64_t qmp_guest_get_time(Error **errp)
 {
     SYSTEMTIME ts = {0};
@@ -707,7 +921,7 @@ GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp)
 GList *ga_command_blacklist_init(GList *blacklist)
 {
     const char *list_unsupported[] = {
-        "guest-suspend-hybrid", "guest-network-get-interfaces",
+        "guest-suspend-hybrid",
         "guest-get-vcpus", "guest-set-vcpus",
         "guest-set-user-password",
         "guest-get-memory-blocks", "guest-set-memory-blocks",
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [PATCH v6 0/2] qga: qmp_guest_network_get_interfaces for win32
  2015-06-02 17:41 [Qemu-devel] [PATCH v6 0/2] qga: qmp_guest_network_get_interfaces for win32 Kirk Allan
  2015-06-02 17:41 ` [Qemu-devel] [PATCH v6 1/2] qga: add win32 library iphlpapi Kirk Allan
  2015-06-02 17:41 ` [Qemu-devel] [PATCH v6 2/2] qga: win32 qmp_guest_network_get_interfaces implementation Kirk Allan
@ 2015-07-07  1:33 ` Michael Roth
  2 siblings, 0 replies; 4+ messages in thread
From: Michael Roth @ 2015-07-07  1:33 UTC (permalink / raw)
  To: Kirk Allan, qemu-devel; +Cc: okrishtal, pbonzini, sw

Quoting Kirk Allan (2015-06-02 12:41:05)
> Changes from v5:
> - Patch 1/2 removed testing for WINVER in QEMU_CFLAGS.
> 
> Changes from v4:
> - Fixed up the commit messages to remove the utf-8 characters.
> 
> Changes from v3:
> - Patch 1/2 removed setting ARCH_$ARCH
> - Patch 2/2 implemented feedback from v3. Use WSAAddressToString for
> inet_ntop functionality.  WSAStringToAddress is available in all versions
> of Windows.
> 
> This patch set is to implement qmp_guest_network_get_interfaces for win32.
> 
> This patch set contains two patches: configuration and implementation.
> 
> The configuration patch adds the iphlpapi library.  The implementation
> patch for commands-win32.c takes advantage of _WIN32_WINNT if set to 0x600
> or greater for Windows Vista/2008 guests or newer to use OnLinkPrefixLength
> for prefixes.  WSAStringToAddress is used for inet_ntop functionality.

Applied, thanks.

> 
> Kirk Allan (2):
>   qga: add win32 library iphlpapi
>   qga: win32 qmp_guest_network_get_interfaces implementation
> 
>  configure            |   2 +-
>  qga/commands-win32.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 218 insertions(+), 4 deletions(-)
> 
> -- 
> 1.8.5.6
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-07-07  1:36 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-02 17:41 [Qemu-devel] [PATCH v6 0/2] qga: qmp_guest_network_get_interfaces for win32 Kirk Allan
2015-06-02 17:41 ` [Qemu-devel] [PATCH v6 1/2] qga: add win32 library iphlpapi Kirk Allan
2015-06-02 17:41 ` [Qemu-devel] [PATCH v6 2/2] qga: win32 qmp_guest_network_get_interfaces implementation Kirk Allan
2015-07-07  1:33 ` [Qemu-devel] [PATCH v6 0/2] qga: qmp_guest_network_get_interfaces for win32 Michael Roth

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.