[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)
- [Qemu-devel] [PATCH] qemu-ga: added windows support for 'guest-network-get-interfaces',
Kenth Andersson <=