[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 3/3] qga support process list, netstat and file stat
From: |
itamar . tal4 |
Subject: |
[Qemu-devel] [PATCH 3/3] qga support process list, netstat and file stat/delete |
Date: |
Wed, 25 Mar 2015 14:25:25 +0200 |
From: Itamar Tal <address@hidden>
this patch add support for some more functionality in the qemu-guest-agent,
both for windows and linux. Main added features are:
- interface listing in Windows
- Process list in Windows
- network connections enumeration in Windows
- file delete for both Windows and Posix
- file stat() for both Windows and Posix
- system uptime for both Windows and Posix
Itamar,
Guardicore
address@hidden
---
qga/commands-posix.c | 49 +++++
qga/commands-win32.c | 552 +++++++++++++++++++++++++++++++++++++++++++++++-
qga/commands.c | 25 +++
qga/guest-agent-core.h | 2 +
qga/main.c | 9 +
qga/qapi-schema.json | 172 +++++++++++++++
qga/win32-definitions.h | 115 ++++++++++
qga/win32-iptypes.h | 411 +++++++++++++++++++++++++++++++++++
8 files changed, 1332 insertions(+), 3 deletions(-)
create mode 100644 qga/win32-definitions.h
create mode 100644 qga/win32-iptypes.h
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index ba8de62..15e39fc 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -23,6 +23,7 @@
#include <string.h>
#include <sys/stat.h>
#include <inttypes.h>
+#include <sys/sysinfo.h>
#include "qga/guest-agent-core.h"
#include "qga-qmp-commands.h"
#include "qapi/qmp/qerror.h"
@@ -2456,3 +2457,51 @@ void ga_command_state_init(GAState *s, GACommandState
*cs)
#endif
ga_command_state_add(cs, guest_file_init, NULL);
}
+
+uint64_t qmp_guest_uptime(Error **errp)
+{
+ struct sysinfo sys_info;
+ if (sysinfo(&sys_info))
+ {
+ error_setg(errp, "Failed reading system info");
+ }
+
+ return sys_info.uptime;
+}
+
+GuestFileStat *qmp_guest_file_stat(const char *path, Error **errp)
+{
+ GuestFileStat * file_stat = g_malloc0(sizeof(GuestFileStat));
+ struct stat file_os_stat;
+
+ if (stat(path, &file_os_stat))
+ {
+ error_setg(errp, "Failed to get file stat() for file '%s'",
path);
+ return NULL;
+ }
+
+ file_stat->mode = file_os_stat.st_mode;
+ file_stat->inode = file_os_stat.st_ino;
+ file_stat->dev = file_os_stat.st_dev;
+ file_stat->nlink = file_os_stat.st_nlink;
+ file_stat->uid = file_os_stat.st_uid;
+ file_stat->gid = file_os_stat.st_gid;
+ file_stat->size = file_os_stat.st_size;
+ file_stat->atime = file_os_stat.st_atime;
+ file_stat->mtime = file_os_stat.st_mtime;
+ file_stat->ctime = file_os_stat.st_ctime;
+
+ return file_stat;
+}
+
+GuestProcessInfoList *qmp_guest_get_process_list(Error **errp)
+{
+ error_set(errp, QERR_UNSUPPORTED);
+ return NULL;
+}
+
+GuestActiveConnectionList *qmp_guest_get_active_connections(Error **errp)
+{
+ error_set(errp, QERR_UNSUPPORTED);
+ return NULL;
+}
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 3ef0549..55d8f2e 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -19,6 +19,7 @@
#include "qga/guest-agent-core.h"
#include "qga/vss-win32.h"
#include "qga-qmp-commands.h"
+#include "qga/win32-definitions.h"
#include "qapi/qmp/qerror.h"
#include "qemu/queue.h"
@@ -26,6 +27,41 @@
#define SHTDN_REASON_FLAG_PLANNED 0x80000000
#endif
+ULONG (__stdcall * GetAdaptersAddresses)( uint32_t Family,
+
uint32_t Flags,
+
void * Reserved,
+
IP_ADAPTER_ADDRESSES * AdapterAddresses,
+
uint32_t * SizePointer) = NULL;
+
+DWORD (__stdcall * GetExtendedTcpTable)(void * pTcpTable,
+
DWORD * pdwSize,
+
BOOL bOrder,
+
ULONG ulAf,
+
TCP_TABLE_CLASS TableClass,
+
ULONG Reserved) = NULL;
+
+DWORD (__stdcall * GetExtendedUdpTable)( void * pUdpTable,
+
DWORD * pdwSize,
+
BOOL bOrder,
+
ULONG ulAf,
+
UDP_TABLE_CLASS TableClass,
+
ULONG Reserved) = NULL;
+
+NTSTATUS (__stdcall * RtlUnicodeStringToAnsiString)(ANSI_STRING *
DestinationString,
+
UNICODE_STRING * SourceString,
+
BOOLEAN AllocateDestinationString) = NULL;
+
+NTSTATUS (__stdcall * NtQueryInformationProcess)( HANDLE ProcessHandle,
+
PROCESSINFOCLASS ProcessInformationClass,
+
void * ProcessInformation,
+
uint32_t ProcessInformationLength,
+
uint32_t * ReturnLength) = NULL;
+
+NTSTATUS (__stdcall * NtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS
SystemInformationClass,
+
void * SystemInformation,
+
uint32_t SystemInformationLength,
+
uint32_t * ReturnLength) = NULL;
+
/* multiple of 100 nanoseconds elapsed between windows baseline
* (1/1/1601) and Unix Epoch (1/1/1970), accounting for leap years */
#define W32_FT_OFFSET (10000000ULL * 60 * 60 * 24 * \
@@ -591,8 +627,132 @@ void qmp_guest_suspend_hybrid(Error **errp)
GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
{
- error_set(errp, QERR_UNSUPPORTED);
- return NULL;
+ GuestNetworkInterfaceList * iface_list = NULL;
+ IP_ADAPTER_ADDRESSES * ip_adapter_addresses = NULL;
+ IP_ADAPTER_ADDRESSES * current_adapter = NULL;
+ uint32_t adapter_buff_size = 15 * 1024;
+ ULONG ret = 0;
+
+ for (;;)
+ {
+ ip_adapter_addresses = g_malloc0(adapter_buff_size);
+ if (NULL == ip_adapter_addresses)
+ {
+ error_setg(errp, "Failed allocating adapters info
buffer");
+ return NULL;
+ }
+
+ ret = GetAdaptersAddresses( AF_UNSPEC,
+
GAA_FLAG_SKIP_ANYCAST |
+
GAA_FLAG_SKIP_MULTICAST |
+
GAA_FLAG_SKIP_DNS_SERVER |
+
GAA_FLAG_INCLUDE_PREFIX,
+ NULL,
+
ip_adapter_addresses,
+
&adapter_buff_size);
+ if (NO_ERROR != ret)
+ {
+ (void)g_free(ip_adapter_addresses);
+ ip_adapter_addresses = NULL;
+
+ if (ERROR_BUFFER_OVERFLOW == ret)
+ {
+ adapter_buff_size <<= 1;
+ continue;
+ }
+
+ error_setg(errp, "Error quering network adapters info");
+ return NULL;
+ }
+
+ break;
+ }
+
+ /* add all adapters to the list */
+ for ( current_adapter = ip_adapter_addresses;
+ NULL != current_adapter;
+ current_adapter = current_adapter->Next)
+ {
+ IP_ADAPTER_UNICAST_ADDRESS * ip_address = NULL;
+ UNICODE_STRING adapter_name_us;
+ ANSI_STRING adapter_name;
+ GuestNetworkInterfaceList * new_item =
g_malloc0(sizeof(GuestNetworkInterfaceList));
+ new_item->value = g_malloc0(sizeof(GuestNetworkInterface));
+ new_item->next = iface_list;
+ iface_list = new_item;
+
+ adapter_name_us.Buffer = current_adapter->FriendlyName;
+ adapter_name_us.Length = wcslen(current_adapter->FriendlyName)
* sizeof(wchar_t);
+ adapter_name_us.MaximumLength = adapter_name_us.Length +
sizeof(wchar_t);
+ adapter_name.MaximumLength = adapter_name_us.MaximumLength;
+ adapter_name.Length = 0;
+ adapter_name.Buffer = g_malloc0(adapter_name_us.MaximumLength);
+
+ /* convert the adapter name to ansi string */
+ (void)RtlUnicodeStringToAnsiString( &adapter_name,
+
&adapter_name_us,
+
FALSE);
+ new_item->value->name = adapter_name.Buffer;
+
+ /* copy physical address */
+ if (current_adapter->PhysicalAddressLength != 0)
+ {
+ int i = 0;
+
+ new_item->value->hardware_address =
g_malloc0(current_adapter->PhysicalAddressLength * 3 + 1);
+
+ for (i = 0; i < current_adapter->PhysicalAddressLength;
++i)
+ {
+ sprintf(&new_item->value->hardware_address[i *
3],
+ "%02x:",
current_adapter->PhysicalAddress[i]);
+ }
+
+ new_item->value->hardware_address[i * 3 - 1] = '\0';
+ new_item->value->has_hardware_address = true;
+ }
+
+ /* build IP list */
+ for ( ip_address = current_adapter->FirstUnicastAddress;
+ NULL != ip_address;
+ ip_address = ip_address->Next)
+ {
+ GuestIpAddressList * new_ip = NULL;
+
+ /* skip unknown addresses */
+ if ((AF_INET !=
ip_address->Address.lpSockaddr->sa_family) &&
+ (AF_INET6 !=
ip_address->Address.lpSockaddr->sa_family))
+ {
+ continue;
+ }
+
+ /* allocate new item in the list */
+ new_ip = g_malloc0(sizeof(GuestIpAddressList));
+ new_ip->value = g_malloc0(sizeof(GuestIpAddress));
+ new_item->value->has_ip_addresses = true;
+
+ /* push the new IP at the head of the list */
+ new_ip->next = new_item->value->ip_addresses;
+ new_item->value->ip_addresses = new_ip;
+
+
+ /* convert IP info by family */
+ if (AF_INET ==
ip_address->Address.lpSockaddr->sa_family)
+ {
+ SOCKADDR_IN * in_addr = (SOCKADDR_IN
*)ip_address->Address.lpSockaddr;
+ new_ip->value->ip_address_type =
GUEST_IP_ADDRESS_TYPE_IPV4;
+ new_ip->value->ip_address =
g_strdup(inet_ntoa(in_addr->sin_addr));
+ }
+ else if (AF_INET6 ==
ip_address->Address.lpSockaddr->sa_family)
+ {
+ new_ip->value->ip_address_type =
GUEST_IP_ADDRESS_TYPE_IPV6;
+ new_ip->value->ip_address = g_strdup("IPv6 not
supported");
+ }
+ }
+ }
+
+ (void)g_free(ip_adapter_addresses);
+
+ return iface_list;
}
int64_t qmp_guest_get_time(Error **errp)
@@ -703,11 +863,73 @@ GuestMemoryBlockInfo
*qmp_guest_get_memory_block_info(Error **errp)
return NULL;
}
+int ga_win_commands_init(void)
+{
+ HMODULE ntdll_module = GetModuleHandle("ntdll.dll");
+ HMODULE iphlpapi_module = LoadLibrary("iphlpapi.dll");
+ WSADATA wsa_data = {0};
+
+ if (WSAStartup(MAKEWORD(2,2), &wsa_data))
+ {
+ g_critical("failed to initialize WSA engine");
+ goto error;
+ }
+
+ if ((NULL == ntdll_module) ||
+ (NULL == iphlpapi_module))
+ {
+ goto error;
+ }
+
+ NtQuerySystemInformation = (void *)GetProcAddress(ntdll_module,
"NtQuerySystemInformation");
+ if (NULL == NtQuerySystemInformation)
+ {
+ goto error;
+ }
+
+ RtlUnicodeStringToAnsiString = (void *)GetProcAddress(ntdll_module,
"RtlUnicodeStringToAnsiString");
+ if (NULL == RtlUnicodeStringToAnsiString)
+ {
+ goto error;
+ }
+
+ NtQueryInformationProcess = (void *)GetProcAddress(ntdll_module,
"NtQueryInformationProcess");
+ if (NULL == NtQueryInformationProcess)
+ {
+ goto error;
+ }
+
+ GetAdaptersAddresses = (void *)GetProcAddress(iphlpapi_module,
"GetAdaptersAddresses");
+ if (NULL == GetAdaptersAddresses)
+ {
+ goto error;
+ }
+
+ GetExtendedTcpTable = (void *)GetProcAddress(iphlpapi_module,
"GetExtendedTcpTable");
+ if (NULL == GetExtendedTcpTable)
+ {
+ goto error;
+ }
+
+ GetExtendedUdpTable = (void *)GetProcAddress(iphlpapi_module,
"GetExtendedUdpTable");
+ if (NULL == GetExtendedUdpTable)
+ {
+ goto error;
+ }
+
+ return 1;
+
+error:
+ (void)FreeLibrary(iphlpapi_module);
+
+ return 0;
+}
+
/* add unsupported commands to the blacklist */
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",
@@ -742,3 +964,327 @@ void ga_command_state_init(GAState *s, GACommandState *cs)
}
ga_command_state_add(cs, guest_file_init, NULL);
}
+
+uint64_t qmp_guest_uptime(Error **errp)
+{
+ uint64_t uptime_milli = GetTickCount();
+ return uptime_milli / 1000;
+}
+
+GuestFileStat *qmp_guest_file_stat(const char *path, Error **errp)
+{
+ GuestFileStat * file_stat = g_malloc0(sizeof(GuestFileStat));
+ struct _stat file_os_stat = {0};
+
+ if (_stat(path, &file_os_stat))
+ {
+ error_setg(errp, "Failed to get file stat() for file '%s': %d",
path, (int)GetLastError());
+ return NULL;
+ }
+
+ file_stat->mode = file_os_stat.st_mode;
+ file_stat->inode = file_os_stat.st_ino;
+ file_stat->dev = file_os_stat.st_dev;
+ file_stat->nlink = file_os_stat.st_nlink;
+ file_stat->uid = file_os_stat.st_uid;
+ file_stat->gid = file_os_stat.st_gid;
+ file_stat->size = file_os_stat.st_size;
+ file_stat->atime = file_os_stat.st_atime;
+ file_stat->mtime = file_os_stat.st_mtime;
+ file_stat->ctime = file_os_stat.st_ctime;
+
+ return file_stat;
+}
+
+GuestProcessInfoList *qmp_guest_get_process_list(Error **errp)
+{
+ uint32_t bytes_needed = sizeof(SYSTEM_PROCESS_INFORMATION) * 20;
+ SYSTEM_PROCESS_INFORMATION * process_list = NULL;
+ SYSTEM_PROCESS_INFORMATION * process_list_iter = NULL;
+ GuestProcessInfoList * process_list_head = NULL;
+ GuestProcessInfoList * process_list_last = NULL;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ /* find the minimal buffer for the process list */
+ for (;;)
+ {
+ process_list = g_malloc0(bytes_needed);
+ if (NULL == process_list)
+ {
+ error_setg(errp, "Failed allocating space for process
list (%d bytes)", bytes_needed);
+ return NULL;
+ }
+
+ /* query the process list (if enough bytes are given) */
+ status = NtQuerySystemInformation(
SystemProcessInformation,
+
process_list,
+
bytes_needed,
+
&bytes_needed);
+ if (STATUS_SUCCESS != status)
+ {
+ (void)g_free(process_list);
+
+ if (STATUS_INFO_LENGTH_MISMATCH == status)
+ {
+ bytes_needed <<= 1;
+ continue;
+ }
+
+ error_setg(errp, "Failed quering process list (status
%08X)", (int)status);
+ return NULL;
+ }
+
+ break;
+ }
+
+ /* iterate the process list and build the JSON reply */
+ for (process_list_iter = process_list;;)
+ {
+ GuestProcessInfoList * list_item =
g_malloc0(sizeof(GuestProcessInfoList));
+ ANSI_STRING process_name;
+ HANDLE process_handle = NULL;
+ UNICODE_STRING * process_image_path = NULL;
+ PROCESS_BASIC_INFORMATION process_basic_info = {0};
+
+ if (NULL == process_list_head)
+ {
+ process_list_head = list_item;
+ }
+ if (NULL != process_list_last)
+ {
+ process_list_last->next = list_item;
+ }
+ process_list_last = list_item;
+
+ list_item->next = NULL;
+ list_item->value = g_malloc0(sizeof(GuestProcessInfo));
+ list_item->value->process_id =
(int)process_list_iter->UniqueProcessId;
+ list_item->value->session_id =
(int)process_list_iter->SessionId;
+
+ process_name.MaximumLength =
process_list_iter->ImageName.MaximumLength;
+ process_name.Length = 0;
+ process_name.Buffer = g_malloc0(process_name.MaximumLength);
+
+ /* convert the image name to ansi string */
+ (void)RtlUnicodeStringToAnsiString( &process_name,
+
&process_list_iter->ImageName,
+
FALSE);
+ list_item->value->process_name = process_name.Buffer;
+
+ if (!process_list_iter->NextEntryOffset)
+ {
+ break;
+ }
+
+ process_handle = OpenProcess( PROCESS_QUERY_INFORMATION,
+
FALSE,
+
list_item->value->process_id);
+ if (NULL != process_handle)
+ {
+ status = NtQueryInformationProcess( process_handle,
+
ProcessBasicInformation,
+
&process_basic_info,
+
sizeof(PROCESS_BASIC_INFORMATION),
+
NULL);
+ if (STATUS_SUCCESS == status)
+ {
+ list_item->value->parent_id =
(int)process_basic_info.InheritedFromUniqueProcessId;
+ }
+
+ process_image_path = g_malloc0(sizeof(UNICODE_STRING) +
256 * sizeof(wchar_t));
+
+ status = NtQueryInformationProcess( process_handle,
+
ProcessImageFileName,
+
process_image_path,
+
sizeof(UNICODE_STRING) + 256 * sizeof(wchar_t),
+
NULL);
+ if (STATUS_SUCCESS == status)
+ {
+ process_name.MaximumLength =
process_image_path->MaximumLength;
+ process_name.Length = 0;
+ process_name.Buffer =
g_malloc0(process_name.MaximumLength);
+
+ /* convert the image name to ansi string */
+ (void)RtlUnicodeStringToAnsiString(
&process_name,
+
process_image_path,
+
FALSE);
+ list_item->value->image_path =
process_name.Buffer;
+ }
+
+ (void)g_free(process_image_path);
+
+ (void)CloseHandle(process_handle);
+ }
+
+ process_list_iter = (void *)((uint32_t)process_list_iter +
process_list_iter->NextEntryOffset);
+ }
+
+ (void)g_free(process_list);
+
+ return process_list_head;
+}
+
+GuestActiveConnectionList *qmp_guest_get_active_connections(Error **errp)
+{
+ MIB_UDPTABLE_OWNER_MODULE * udp_table = NULL;
+ MIB_TCPTABLE_OWNER_MODULE * tcp_table = NULL;
+ DWORD bytes_needed = sizeof(MIB_UDPTABLE_OWNER_MODULE) * 30;
+ GuestActiveConnectionList * connections = NULL;
+ int entry_index = 0;
+ DWORD ret;
+
+ /* get the UDP table */
+ for (;;)
+ {
+ udp_table = g_malloc0(bytes_needed);
+ if (NULL == udp_table)
+ {
+ error_setg(errp, "Failed allocating active UDP
connections table");
+ return NULL;
+ }
+
+ ret = GetExtendedUdpTable( udp_table,
+
&bytes_needed,
+ TRUE,
+ AF_INET,
+
UDP_TABLE_OWNER_MODULE,
+ 0);
+ if (NO_ERROR != ret)
+ {
+ (void)g_free(tcp_table);
+ udp_table = NULL;
+
+ if (ERROR_INSUFFICIENT_BUFFER == ret)
+ {
+ bytes_needed <<= 1;
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ /* add the UDP connections to the list backward */
+ for ( entry_index = udp_table->dwNumEntries - 1;
+ entry_index >= 0;
+ --entry_index)
+ {
+ /* allocate new active connection item */
+ GuestActiveConnectionList * new_item =
g_malloc0(sizeof(GuestActiveConnectionList));
+ new_item->value = g_malloc0(sizeof(GuestActiveConnection));
+
+ /* push the connection to the head of the list */
+ new_item->next = connections;
+ connections = new_item;
+
+ new_item->value->source_addr = g_strdup(inet_ntoa(*(struct
in_addr *)&udp_table->table[entry_index].dwLocalAddr));
+ new_item->value->source_port =
htons(udp_table->table[entry_index].dwLocalPort);
+ new_item->value->owner_process_id =
udp_table->table[entry_index].dwOwningPid;
+ new_item->value->if_family = GUEST_IP_ADDRESS_TYPE_IPV4;
+ new_item->value->protocol = GUEST_IP_PROTOCOL_UDP;
+ new_item->value->start_time =
udp_table->table[entry_index].liCreateTimestamp.QuadPart;
+ }
+
+ (void)g_free(udp_table);
+ udp_table = NULL;
+
+ bytes_needed = sizeof(MIB_TCPROW_OWNER_PID) * 30;
+
+ /* get the TCP table */
+ for (;;)
+ {
+ tcp_table = g_malloc0(bytes_needed);
+ if (NULL == tcp_table)
+ {
+ error_setg(errp, "Failed allocating active connections
table");
+ return NULL;
+ }
+
+ ret = GetExtendedTcpTable( tcp_table,
+
&bytes_needed,
+ TRUE,
+ AF_INET,
+
TCP_TABLE_OWNER_MODULE_ALL,
+ 0);
+ if (NO_ERROR != ret)
+ {
+ (void)g_free(tcp_table);
+ tcp_table = NULL;
+
+ if (ERROR_INSUFFICIENT_BUFFER == ret)
+ {
+ bytes_needed <<= 1;
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ /* add the TCP connections to the list backward */
+ for ( entry_index = tcp_table->dwNumEntries - 1;
+ entry_index >= 0;
+ --entry_index)
+ {
+ /* allocate new active connection item */
+ GuestActiveConnectionList * new_item =
g_malloc0(sizeof(GuestActiveConnectionList));
+ new_item->value = g_malloc0(sizeof(GuestActiveConnection));
+
+ /* push the connection to the head of the list */
+ new_item->next = connections;
+ connections = new_item;
+
+ new_item->value->source_addr = g_strdup(inet_ntoa(*(struct
in_addr *)&tcp_table->table[entry_index].dwLocalAddr));
+ new_item->value->source_port =
htons(tcp_table->table[entry_index].dwLocalPort);
+ new_item->value->dest_addr = g_strdup(inet_ntoa(*(struct
in_addr *)&tcp_table->table[entry_index].dwRemoteAddr));
+ new_item->value->dest_port =
htons(tcp_table->table[entry_index].dwRemotePort);
+ new_item->value->owner_process_id =
tcp_table->table[entry_index].dwOwningPid;
+ new_item->value->if_family = GUEST_IP_ADDRESS_TYPE_IPV4;
+ new_item->value->protocol = GUEST_IP_PROTOCOL_TCP;
+ new_item->value->start_time =
tcp_table->table[entry_index].liCreateTimestamp.QuadPart;
+
+ switch (tcp_table->table[entry_index].dwState)
+ {
+ case MIB_TCP_STATE_CLOSED:
+ new_item->value->state =
GUEST_TCP_PROTOCOL_STATE_CLOSED;
+ break;
+ case MIB_TCP_STATE_LISTEN:
+ new_item->value->state =
GUEST_TCP_PROTOCOL_STATE_LISTEN;
+ break;
+ case MIB_TCP_STATE_SYN_SENT:
+ new_item->value->state =
GUEST_TCP_PROTOCOL_STATE_SYN_SENT;
+ break;
+ case MIB_TCP_STATE_SYN_RCVD:
+ new_item->value->state =
GUEST_TCP_PROTOCOL_STATE_SYN_RCVD;
+ break;
+ case MIB_TCP_STATE_ESTAB:
+ new_item->value->state =
GUEST_TCP_PROTOCOL_STATE_ESTABLISHED;
+ break;
+ case MIB_TCP_STATE_FIN_WAIT1:
+ new_item->value->state =
GUEST_TCP_PROTOCOL_STATE_FIN_WAIT1;
+ break;
+ case MIB_TCP_STATE_FIN_WAIT2:
+ new_item->value->state =
GUEST_TCP_PROTOCOL_STATE_FIN_WAIT2;
+ break;
+ case MIB_TCP_STATE_CLOSE_WAIT:
+ new_item->value->state =
GUEST_TCP_PROTOCOL_STATE_CLOSE_WAIT;
+ break;
+ case MIB_TCP_STATE_CLOSING:
+ new_item->value->state =
GUEST_TCP_PROTOCOL_STATE_CLOSING;
+ break;
+ case MIB_TCP_STATE_LAST_ACK:
+ new_item->value->state =
GUEST_TCP_PROTOCOL_STATE_LAST_ACK;
+ break;
+ case MIB_TCP_STATE_TIME_WAIT:
+ new_item->value->state =
GUEST_TCP_PROTOCOL_STATE_TIME_WAIT;
+ break;
+ case MIB_TCP_STATE_DELETE_TCB:
+ new_item->value->state =
GUEST_TCP_PROTOCOL_STATE_DELETE_TCB;
+ break;
+ }
+ }
+
+ (void)g_free(tcp_table);
+
+ return connections;
+}
diff --git a/qga/commands.c b/qga/commands.c
index 7834967..2fb364c 100644
--- a/qga/commands.c
+++ b/qga/commands.c
@@ -70,3 +70,28 @@ struct GuestAgentInfo *qmp_guest_info(Error **errp)
qmp_for_each_command(qmp_command_info, info);
return info;
}
+
+void qmp_guest_file_delete(const char *path, Error **errp)
+{
+ if (unlink(path))
+ {
+ error_setg(errp, "Error deleting file '%s'", path);
+ }
+}
+
+char *qmp_guest_get_hostname(Error **errp)
+{
+ char hostname[64];
+
+ if (gethostname(hostname, 64))
+ {
+#ifdef _WIN32
+ error_setg(errp, "Error getting hostname (%d)",
WSAGetLastError());
+#else
+ error_setg(errp, "Error getting hostname");
+#endif
+ return NULL;
+ }
+
+ return g_strdup(hostname);
+}
diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h
index e92c6ab..89d4165 100644
--- a/qga/guest-agent-core.h
+++ b/qga/guest-agent-core.h
@@ -40,4 +40,6 @@ int64_t ga_get_fd_handle(GAState *s, Error **errp);
#ifndef _WIN32
void reopen_fd_to_null(int fd);
+#else
+int ga_win_commands_init(void);
#endif
diff --git a/qga/main.c b/qga/main.c
index 9939a2b..3992aac 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -1163,6 +1163,15 @@ int main(int argc, char **argv)
g_critical("failed to register signal handlers");
goto out_bad;
}
+#else
+ {
+
+ if (!ga_win_commands_init())
+ {
+ g_critical("failed initializing commands module");
+ goto out_bad;
+ }
+ }
#endif
s->main_loop = g_main_loop_new(NULL, false);
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 95f49e3..1e38f98 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -891,3 +891,175 @@
##
{ 'command': 'guest-get-memory-block-info',
'returns': 'GuestMemoryBlockInfo' }
+
+##
+# @GuestFileStat
+#
+# @st_mode: file access permissions mode
+# @st_ino: file inode id
+# @st_dev: file device node
+# @st_nlink: number of links pointing to the file
+# @st_uid: file user id
+# @st_gid: file group id
+# @st_atime: file access time
+# @st_mtime: file modification time
+# @st_ctime: file creation time
+# @st_size: file size in bytes
+#
+# Since: 2.3
+##
+{ 'type': 'GuestFileStat',
+ 'data': {'mode': 'int', 'inode': 'int', 'dev': 'int',
+ 'nlink': 'int', 'uid': 'int', 'gid': 'int',
+ 'size': 'uint64', 'atime': 'int', 'mtime': 'int',
+ 'ctime': 'int'
+ }}
+
+##
+# @guest-file-stat:
+#
+# Get the stat() for a file in the guest's operating system
+#
+# Returns: hostname string.
+#
+# Since 2.3
+##
+{ 'command': 'guest-file-stat',
+ 'data': { 'path': 'str' },
+ 'returns': 'GuestFileStat' }
+
+##
+# @guest-file-delete:
+#
+# Delete a file in the guest's operating system
+#
+# Returns:
+#
+# Since 2.3
+##
+{ 'command': 'guest-file-delete',
+ 'data': { 'path': 'str' }}
+
+##
+# @guest-get-hostname:
+#
+# Get the hostname of the guest's operating system
+#
+# Returns: hostname string.
+#
+# Since 2.3
+##
+{ 'command': 'guest-get-hostname',
+ 'returns': 'str' }
+
+##
+# @guest-uptime:
+#
+# Get the time in seconds since the guest machine operating system was started
+#
+# Returns: uptime in seconds
+#
+# Since 2.3
+##
+{ 'command': 'guest-uptime',
+ 'returns': 'uint64' }
+
+##
+# @GuestProcessInfo
+#
+# @process-id: the process unique id
+# @parent-id: the process parent unique id
+# @process-name: the name of the process
+# @image-path: full path of the process image
+# @session-id: the session id of the process
+#
+# Since: 2.3
+##
+{ 'type': 'GuestProcessInfo',
+ 'data': {'process-id': 'int', 'parent-id': 'int', 'process-name': 'str',
+ 'image-path': 'str', 'session-id': 'int'}}
+
+##
+# @guest-get-process-list:
+#
+# Get the list of active processes on the guest operating system
+#
+# Returns: array of active processes
+#
+# Since 2.3
+##
+{ 'command': 'guest-get-process-list',
+ 'returns': ['GuestProcessInfo'] }
+
+##
+# @GuestIpProtocol:
+#
+# An enumeration of supported IP protocols
+#
+# @tcp: TCP
+#
+# @udp: UDP
+#
+# Since: 2.3
+##
+{ 'enum': 'GuestIpProtocol',
+ 'data': [ 'tcp', 'udp' ] }
+
+##
+# @GuestTcpProtocolState:
+#
+# An enumeration of TCP connection state
+#
+# @closed: CLOSED
+# @listen: LISTEN
+# @syn-sent: SYN_SENT
+# @syn-rcvd: SYN_RCVD
+# @established: ESTABLISHED
+# @fin-wait1: FIN_WAIT1
+# @fin-wait2: FIN_WAIT2
+# @close-wait: CLOSE_WAIT
+# @closing: CLOSING
+# @last-ack: LAST_ACK
+# @time-wait: TIME_WAIT
+# @delete-tcb: DELETE_TCB
+#
+# Since: 2.3
+##
+{ 'enum': 'GuestTcpProtocolState',
+ 'data': [ 'closed', 'listen', 'syn-sent', 'syn-rcvd', 'established',
+ 'fin-wait1', 'fin-wait2', 'close-wait', 'closing',
+ 'last-ack', 'time-wait', 'delete-tcb' ] }
+
+##
+# @GuestActiveConnection
+#
+# @if-family: 4 / 6
+# @protocol: TCP / UDP
+# @source-addr: the source IP address of the connection
+# @source-port: the source port of the connection
+# @dest-addr: the destination IP address of the connection
+# @dest-port: the destination port of the connection
+# @owner-process_id: the process unique id for the connection owner
+# @state: connection protocol state
+# @start-time: time where bind() was called for the connection
+#
+# Since: 2.3
+##
+{ 'type': 'GuestActiveConnection',
+ 'data': { 'source-addr': 'str', 'source-port': 'int', 'dest-addr': 'str',
+ 'dest-port': 'int', 'owner-process_id': 'int', 'state':
'GuestTcpProtocolState',
+ 'if-family': 'GuestIpAddressType', 'protocol':
'GuestIpProtocol',
+ 'start-time': 'uint64'}}
+
+ ##
+# @guest-get-active-connections:
+#
+# Get the list of active connections on the guest operating system
+#
+# Returns: array of active connections
+#
+# Since 2.3
+##
+{ 'command': 'guest-get-active-connections',
+ 'returns': ['GuestActiveConnection'] }
+
diff --git a/qga/win32-definitions.h b/qga/win32-definitions.h
new file mode 100644
index 0000000..6bb610e
--- /dev/null
+++ b/qga/win32-definitions.h
@@ -0,0 +1,115 @@
+
+#ifndef WIN32_DEFINITIONS_H_
+#define WIN32_DEFINITIONS_H_ 1
+
+#include "win32-iptypes.h"
+
+#define STATUS_INFO_LENGTH_MISMATCH (0xC0000004)
+
+typedef
+enum _PROCESSINFOCLASS
+{
+ ProcessBasicInformation=0x0000,
+ ProcessDebugPort=0x0007,
+ ProcessWow64Information=0x001a,
+ ProcessImageFileName=0x001b,
+ ProcessBreakOnTermination=0x001d,
+} PROCESSINFOCLASS;
+
+typedef struct
+{
+ ULONG AllocationSize;
+ ULONG ActualSize;
+ ULONG Flags;
+ ULONG Unknown1;
+ UNICODE_STRING Unknown2;
+ HANDLE InputHandle;
+ HANDLE OutputHandle;
+ HANDLE ErrorHandle;
+ UNICODE_STRING CurrentDirectory;
+ HANDLE CurrentDirectoryHandle;
+ UNICODE_STRING SearchPaths;
+ UNICODE_STRING ApplicationName;
+ UNICODE_STRING CommandLine;
+ PVOID EnvironmentBlock;
+ ULONG Unknown[9];
+ UNICODE_STRING Unknown3;
+ UNICODE_STRING Unknown4;
+ UNICODE_STRING Unknown5;
+ UNICODE_STRING Unknown6;
+} PROCESS_PARAMETERS, *PPROCESS_PARAMETERS;
+
+typedef struct
+{
+ ULONG AllocationSize;
+ ULONG Unknown1;
+ HINSTANCE ProcessHinstance;
+ PVOID ListDlls;
+ PPROCESS_PARAMETERS ProcessParameters;
+ ULONG Unknown2;
+ HANDLE Heap;
+} PEB, *PPEB;
+
+typedef struct
+{
+ DWORD ExitStatus;
+ PPEB PebBaseAddress;
+ DWORD AffinityMask;
+ DWORD BasePriority;
+ ULONG UniqueProcessId;
+ ULONG InheritedFromUniqueProcessId;
+} PROCESS_BASIC_INFORMATION;
+
+typedef
+enum _SYSTEM_INFORMATION_CLASS
+{
+ SystemBasicInformation=0x0000,
+ SystemProcessorInformation=0x0001,
+ SystemPerformanceInformation=0x0002,
+ SystemTimeOfDayInformation=0x0003,
+ SystemPathInformation=0x0004,
+ SystemProcessInformation=0x0005,
+ SystemDeviceInformation=0x0007,
+ SystemModuleInformation=0x000B,
+} SYSTEM_INFORMATION_CLASS;
+
+typedef
+struct _SYSTEM_PROCESS_INFORMATION // Size=184
+{
+ ULONG NextEntryOffset; // Size=4 Offset=0
+ ULONG NumberOfThreads; // Size=4 Offset=4
+ LARGE_INTEGER WorkingSetPrivateSize; // Size=8 Offset=8
+ ULONG HardFaultCount; // Size=4 Offset=16
+ ULONG NumberOfThreadsHighWatermark; // Size=4 Offset=20
+ ULONGLONG CycleTime; // Size=8 Offset=24
+ LARGE_INTEGER CreateTime; // Size=8 Offset=32
+ LARGE_INTEGER UserTime; // Size=8 Offset=40
+ LARGE_INTEGER KernelTime; // Size=8 Offset=48
+ UNICODE_STRING ImageName; // Size=8 Offset=56
+ LONG BasePriority; // Size=4 Offset=64
+ PVOID UniqueProcessId; // Size=4 Offset=68
+ PVOID InheritedFromUniqueProcessId; // Size=4 Offset=72
+ ULONG HandleCount; // Size=4 Offset=76
+ ULONG SessionId; // Size=4 Offset=80
+ ULONG UniqueProcessKey; // Size=4 Offset=84
+ ULONG PeakVirtualSize; // Size=4 Offset=88
+ ULONG VirtualSize; // Size=4 Offset=92
+ ULONG PageFaultCount; // Size=4 Offset=96
+ ULONG PeakWorkingSetSize; // Size=4 Offset=100
+ ULONG WorkingSetSize; // Size=4 Offset=104
+ ULONG QuotaPeakPagedPoolUsage; // Size=4 Offset=108
+ ULONG QuotaPagedPoolUsage; // Size=4 Offset=112
+ ULONG QuotaPeakNonPagedPoolUsage; // Size=4 Offset=116
+ ULONG QuotaNonPagedPoolUsage; // Size=4 Offset=120
+ ULONG PagefileUsage; // Size=4 Offset=124
+ ULONG PeakPagefileUsage; // Size=4 Offset=128
+ ULONG PrivatePageCount; // Size=4 Offset=132
+ LARGE_INTEGER ReadOperationCount; // Size=8 Offset=136
+ LARGE_INTEGER WriteOperationCount; // Size=8 Offset=144
+ LARGE_INTEGER OtherOperationCount; // Size=8 Offset=152
+ LARGE_INTEGER ReadTransferCount; // Size=8 Offset=160
+ LARGE_INTEGER WriteTransferCount; // Size=8 Offset=168
+ LARGE_INTEGER OtherTransferCount; // Size=8 Offset=176
+} SYSTEM_PROCESS_INFORMATION;
+
+#endif /* WIN32_DEFINITIONS_H_ */
diff --git a/qga/win32-iptypes.h b/qga/win32-iptypes.h
new file mode 100644
index 0000000..baae4ea
--- /dev/null
+++ b/qga/win32-iptypes.h
@@ -0,0 +1,411 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ iptypes.h
+
+--*/
+
+#ifndef IP_TYPES_INCLUDED
+#define IP_TYPES_INCLUDED
+
+#include <time.h>
+
+#define INET_ADDRSTRLEN (16)
+#define INET6_ADDRSTRLEN (48)
+
+// Definitions and structures used by getnetworkparams and getadaptersinfo apis
+
+#define MAX_ADAPTER_DESCRIPTION_LENGTH 128 // arb.
+#define MAX_ADAPTER_NAME_LENGTH 256 // arb.
+#define MAX_ADAPTER_ADDRESS_LENGTH 8 // arb.
+#define DEFAULT_MINIMUM_ENTITIES 32 // arb.
+#define MAX_HOSTNAME_LEN 128 // arb.
+#define MAX_DOMAIN_NAME_LEN 128 // arb.
+#define MAX_SCOPE_ID_LEN 256 // arb.
+
+//
+// types
+//
+
+// Node Type
+
+#define BROADCAST_NODETYPE 1
+#define PEER_TO_PEER_NODETYPE 2
+#define MIXED_NODETYPE 4
+#define HYBRID_NODETYPE 8
+
+//
+// IP_ADDRESS_STRING - store an IP address as a dotted decimal string
+//
+
+typedef struct {
+ char String[4 * 4];
+} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;
+
+//
+// IP_ADDR_STRING - store an IP address with its corresponding subnet mask,
+// both as dotted decimal strings
+//
+
+typedef struct _IP_ADDR_STRING {
+ struct _IP_ADDR_STRING* Next;
+ IP_ADDRESS_STRING IpAddress;
+ IP_MASK_STRING IpMask;
+ DWORD Context;
+} IP_ADDR_STRING, *PIP_ADDR_STRING;
+
+//
+// ADAPTER_INFO - per-adapter information. All IP addresses are stored as
+// strings
+//
+
+typedef struct _IP_ADAPTER_INFO {
+ struct _IP_ADAPTER_INFO* Next;
+ DWORD ComboIndex;
+ char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
+ char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
+ UINT AddressLength;
+ BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
+ DWORD Index;
+ UINT Type;
+ UINT DhcpEnabled;
+ PIP_ADDR_STRING CurrentIpAddress;
+ IP_ADDR_STRING IpAddressList;
+ IP_ADDR_STRING GatewayList;
+ IP_ADDR_STRING DhcpServer;
+ BOOL HaveWins;
+ IP_ADDR_STRING PrimaryWinsServer;
+ IP_ADDR_STRING SecondaryWinsServer;
+ time_t LeaseObtained;
+ time_t LeaseExpires;
+} IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;
+
+//
+// The following types require Winsock2.
+//
+
+typedef enum {
+ IpPrefixOriginOther = 0,
+ IpPrefixOriginManual,
+ IpPrefixOriginWellKnown,
+ IpPrefixOriginDhcp,
+ IpPrefixOriginRouterAdvertisement,
+} IP_PREFIX_ORIGIN;
+
+typedef enum {
+ IpSuffixOriginOther = 0,
+ IpSuffixOriginManual,
+ IpSuffixOriginWellKnown,
+ IpSuffixOriginDhcp,
+ IpSuffixOriginLinkLayerAddress,
+ IpSuffixOriginRandom,
+} IP_SUFFIX_ORIGIN;
+
+typedef enum {
+ IpDadStateInvalid = 0,
+ IpDadStateTentative,
+ IpDadStateDuplicate,
+ IpDadStateDeprecated,
+ IpDadStatePreferred,
+} IP_DAD_STATE;
+
+typedef struct _IP_ADAPTER_UNICAST_ADDRESS {
+ union {
+ ULONGLONG Alignment;
+ struct {
+ ULONG Length;
+ DWORD Flags;
+ };
+ };
+ struct _IP_ADAPTER_UNICAST_ADDRESS *Next;
+ SOCKET_ADDRESS Address;
+
+ IP_PREFIX_ORIGIN PrefixOrigin;
+ IP_SUFFIX_ORIGIN SuffixOrigin;
+ IP_DAD_STATE DadState;
+
+ ULONG ValidLifetime;
+ ULONG PreferredLifetime;
+ ULONG LeaseLifetime;
+} IP_ADAPTER_UNICAST_ADDRESS, *PIP_ADAPTER_UNICAST_ADDRESS;
+
+typedef struct _IP_ADAPTER_ANYCAST_ADDRESS {
+ union {
+ ULONGLONG Alignment;
+ struct {
+ ULONG Length;
+ DWORD Flags;
+ };
+ };
+ struct _IP_ADAPTER_ANYCAST_ADDRESS *Next;
+ SOCKET_ADDRESS Address;
+} IP_ADAPTER_ANYCAST_ADDRESS, *PIP_ADAPTER_ANYCAST_ADDRESS;
+
+typedef struct _IP_ADAPTER_MULTICAST_ADDRESS {
+ union {
+ ULONGLONG Alignment;
+ struct {
+ ULONG Length;
+ DWORD Flags;
+ };
+ };
+ struct _IP_ADAPTER_MULTICAST_ADDRESS *Next;
+ SOCKET_ADDRESS Address;
+} IP_ADAPTER_MULTICAST_ADDRESS, *PIP_ADAPTER_MULTICAST_ADDRESS;
+
+//
+// Per-address Flags
+//
+#define IP_ADAPTER_ADDRESS_DNS_ELIGIBLE 0x01
+#define IP_ADAPTER_ADDRESS_TRANSIENT 0x02
+
+typedef struct _IP_ADAPTER_DNS_SERVER_ADDRESS {
+ union {
+ ULONGLONG Alignment;
+ struct {
+ ULONG Length;
+ DWORD Reserved;
+ };
+ };
+ struct _IP_ADAPTER_DNS_SERVER_ADDRESS *Next;
+ SOCKET_ADDRESS Address;
+} IP_ADAPTER_DNS_SERVER_ADDRESS, *PIP_ADAPTER_DNS_SERVER_ADDRESS;
+
+typedef struct _IP_ADAPTER_PREFIX {
+ union {
+ ULONGLONG Alignment;
+ struct {
+ ULONG Length;
+ DWORD Flags;
+ };
+ };
+ struct _IP_ADAPTER_PREFIX *Next;
+ SOCKET_ADDRESS Address;
+ ULONG PrefixLength;
+} IP_ADAPTER_PREFIX, *PIP_ADAPTER_PREFIX;
+
+//
+// Per-adapter Flags
+//
+#define IP_ADAPTER_DDNS_ENABLED 0x01
+#define IP_ADAPTER_REGISTER_ADAPTER_SUFFIX 0x02
+#define IP_ADAPTER_DHCP_ENABLED 0x04
+#define IP_ADAPTER_RECEIVE_ONLY 0x08
+#define IP_ADAPTER_NO_MULTICAST 0x10
+#define IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG 0x20
+
+//
+// OperStatus values from RFC 2863
+//
+typedef enum {
+ IfOperStatusUp = 1,
+ IfOperStatusDown,
+ IfOperStatusTesting,
+ IfOperStatusUnknown,
+ IfOperStatusDormant,
+ IfOperStatusNotPresent,
+ IfOperStatusLowerLayerDown
+} IF_OPER_STATUS;
+
+//
+// Scope levels from RFC 2373 used with ZoneIndices array.
+//
+typedef enum {
+ ScopeLevelInterface = 1,
+ ScopeLevelLink = 2,
+ ScopeLevelSubnet = 3,
+ ScopeLevelAdmin = 4,
+ ScopeLevelSite = 5,
+ ScopeLevelOrganization = 8,
+ ScopeLevelGlobal = 14
+} SCOPE_LEVEL;
+
+typedef struct _IP_ADAPTER_ADDRESSES {
+ union {
+ ULONGLONG Alignment;
+ struct {
+ ULONG Length;
+ DWORD IfIndex;
+ };
+ };
+ struct _IP_ADAPTER_ADDRESSES *Next;
+ PCHAR AdapterName;
+ PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress;
+ PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress;
+ PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress;
+ PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress;
+ PWCHAR DnsSuffix;
+ PWCHAR Description;
+ PWCHAR FriendlyName;
+ BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH];
+ DWORD PhysicalAddressLength;
+ DWORD Flags;
+ DWORD Mtu;
+ DWORD IfType;
+ IF_OPER_STATUS OperStatus;
+ DWORD Ipv6IfIndex;
+ DWORD ZoneIndices[16];
+ PIP_ADAPTER_PREFIX FirstPrefix;
+} IP_ADAPTER_ADDRESSES, *PIP_ADAPTER_ADDRESSES;
+
+//
+// Flags used as argument to GetAdaptersAddresses().
+// "SKIP" flags are added when the default is to include the information.
+// "INCLUDE" flags are added when the default is to skip the information.
+//
+#define GAA_FLAG_SKIP_UNICAST 0x0001
+#define GAA_FLAG_SKIP_ANYCAST 0x0002
+#define GAA_FLAG_SKIP_MULTICAST 0x0004
+#define GAA_FLAG_SKIP_DNS_SERVER 0x0008
+#define GAA_FLAG_INCLUDE_PREFIX 0x0010
+#define GAA_FLAG_SKIP_FRIENDLY_NAME 0x0020
+
+//
+// IP_PER_ADAPTER_INFO - per-adapter IP information such as DNS server list.
+//
+
+typedef struct _IP_PER_ADAPTER_INFO {
+ UINT AutoconfigEnabled;
+ UINT AutoconfigActive;
+ PIP_ADDR_STRING CurrentDnsServer;
+ IP_ADDR_STRING DnsServerList;
+} IP_PER_ADAPTER_INFO, *PIP_PER_ADAPTER_INFO;
+
+//
+// FIXED_INFO - the set of IP-related information which does not depend on DHCP
+//
+
+typedef struct {
+ char HostName[MAX_HOSTNAME_LEN + 4] ;
+ char DomainName[MAX_DOMAIN_NAME_LEN + 4];
+ PIP_ADDR_STRING CurrentDnsServer;
+ IP_ADDR_STRING DnsServerList;
+ UINT NodeType;
+ char ScopeId[MAX_SCOPE_ID_LEN + 4];
+ UINT EnableRouting;
+ UINT EnableProxy;
+ UINT EnableDns;
+} FIXED_INFO, *PFIXED_INFO;
+
+typedef struct ip_interface_name_info {
+ ULONG Index; // Interface Index
+ ULONG MediaType; // Interface Types - see ipifcons.h
+ UCHAR ConnectionType;
+ UCHAR AccessType;
+ GUID DeviceGuid; // Device GUID is the guid of the device
+ // that IP exposes
+ GUID InterfaceGuid; // Interface GUID, if not GUID_NULL is the
+ // GUID for the interface mapped to the device.
+} IP_INTERFACE_NAME_INFO, *PIP_INTERFACE_NAME_INFO;
+
+typedef enum {
+ TCP_TABLE_BASIC_LISTENER,
+ TCP_TABLE_BASIC_CONNECTIONS,
+ TCP_TABLE_BASIC_ALL,
+ TCP_TABLE_OWNER_PID_LISTENER,
+ TCP_TABLE_OWNER_PID_CONNECTIONS,
+ TCP_TABLE_OWNER_PID_ALL,
+ TCP_TABLE_OWNER_MODULE_LISTENER,
+ TCP_TABLE_OWNER_MODULE_CONNECTIONS,
+ TCP_TABLE_OWNER_MODULE_ALL
+} TCP_TABLE_CLASS, *PTCP_TABLE_CLASS;
+
+typedef enum {
+ UDP_TABLE_BASIC,
+ UDP_TABLE_OWNER_PID,
+ UDP_TABLE_OWNER_MODULE
+} UDP_TABLE_CLASS, *PUDP_TABLE_CLASS;
+
+#define TCPIP_OWNING_MODULE_SIZE (16)
+#define ANY_SIZE (1)
+
+typedef enum
+{
+ MIB_TCP_STATE_CLOSED = 1,
+ MIB_TCP_STATE_LISTEN = 2,
+ MIB_TCP_STATE_SYN_SENT = 3,
+ MIB_TCP_STATE_SYN_RCVD = 4,
+ MIB_TCP_STATE_ESTAB = 5,
+ MIB_TCP_STATE_FIN_WAIT1 = 6,
+ MIB_TCP_STATE_FIN_WAIT2 = 7,
+ MIB_TCP_STATE_CLOSE_WAIT = 8,
+ MIB_TCP_STATE_CLOSING = 9,
+ MIB_TCP_STATE_LAST_ACK = 10,
+ MIB_TCP_STATE_TIME_WAIT = 11,
+ MIB_TCP_STATE_DELETE_TCB = 12
+} MIB_TCP_STATE;
+
+typedef struct _MIB_UDPROW {
+ DWORD dwLocalAddr;
+ DWORD dwLocalPort;
+} MIB_UDPROW, *PMIB_UDPROW;
+
+typedef struct _MIB_UDPTABLE {
+ DWORD dwNumEntries;
+ MIB_UDPROW table[ANY_SIZE];
+} MIB_UDPTABLE, *PMIB_UDPTABLE;
+
+typedef struct _MIB_UDPROW_OWNER_PID {
+ DWORD dwLocalAddr;
+ DWORD dwLocalPort;
+ DWORD dwOwningPid;
+} MIB_UDPROW_OWNER_PID, *PMIB_UDPROW_OWNER_PID;
+
+typedef struct _MIB_UDPTABLE_OWNER_PID {
+ DWORD dwNumEntries;
+ MIB_UDPROW_OWNER_PID table[ANY_SIZE];
+} MIB_UDPTABLE_OWNER_PID, *PMIB_UDPTABLE_OWNER_PID;
+
+typedef struct _MIB_UDPROW_OWNER_MODULE {
+ DWORD dwLocalAddr;
+ DWORD dwLocalPort;
+ DWORD dwOwningPid;
+ LARGE_INTEGER liCreateTimestamp;
+ union {
+ struct {
+ int SpecificPortBind :1;
+ };
+ int dwFlags;
+ };
+ ULONGLONG OwningModuleInfo[TCPIP_OWNING_MODULE_SIZE];
+} MIB_UDPROW_OWNER_MODULE, *PMIB_UDPROW_OWNER_MODULE;
+
+typedef struct _MIB_UDPTABLE_OWNER_MODULE {
+ DWORD dwNumEntries;
+ MIB_UDPROW_OWNER_MODULE table[ANY_SIZE];
+} MIB_UDPTABLE_OWNER_MODULE, *PMIB_UDPTABLE_OWNER_MODULE;
+
+typedef struct _MIB_TCPROW_OWNER_MODULE {
+ DWORD dwState;
+ DWORD dwLocalAddr;
+ DWORD dwLocalPort;
+ DWORD dwRemoteAddr;
+ DWORD dwRemotePort;
+ DWORD dwOwningPid;
+ LARGE_INTEGER liCreateTimestamp;
+ ULONGLONG OwningModuleInfo[TCPIP_OWNING_MODULE_SIZE];
+} MIB_TCPROW_OWNER_MODULE, *PMIB_TCPROW_OWNER_MODULE;
+
+typedef struct {
+ DWORD dwNumEntries;
+ MIB_TCPROW_OWNER_MODULE table[ANY_SIZE];
+} MIB_TCPTABLE_OWNER_MODULE, *PMIB_TCPTABLE_OWNER_MODULE;
+
+typedef struct _MIB_TCPROW_OWNER_PID {
+ DWORD dwState;
+ DWORD dwLocalAddr;
+ DWORD dwLocalPort;
+ DWORD dwRemoteAddr;
+ DWORD dwRemotePort;
+ DWORD dwOwningPid;
+} MIB_TCPROW_OWNER_PID, *PMIB_TCPROW_OWNER_PID;
+
+typedef struct {
+ DWORD dwNumEntries;
+ MIB_TCPROW_OWNER_PID table[ANY_SIZE];
+} MIB_TCPTABLE_OWNER_PID, *PMIB_TCPTABLE_OWNER_PID;
+
+#endif /* IP_TYPES_INCLUDED */
--
2.3.4
- [Qemu-devel] [PATCH 3/3] qga support process list, netstat and file stat/delete,
itamar . tal4 <=