Re: [PATCH] qemu-guest-agent: Update the logfile path of qga-fsfreeze-hook.log

2024-08-19 Thread Dehan Meng
'/var/log/qemu-ga' is more reasonable and forward-looking to facilitate
future log management. All qga-related logs would be better placed in a
dedicated and unified log directory.

On Wed, Aug 14, 2024 at 7:54 PM Konstantin Kostiuk 
wrote:

> This bug looks specific to the RedHat SELinux configuration.
> Is this any reason to move LOGFILE except this?
>
> Best Regards,
> Konstantin Kostiuk.
>
>
> On Tue, Aug 13, 2024 at 6:11 AM Dehan Meng  wrote:
>
>> Since '/var/log/qga-fsfreeze-hook.log' is not included to proper
>> selinux context 'system_u:object_r:virt_qemu_ga_log_t:s0', it
>> should be changed to '/var/log/qemu-ga/qga-fsfreeze-hook.log'
>>
>> Jira: https://issues.redhat.com/browse/RHEL-52250
>> Signed-off-by: Dehan Meng 
>> ---
>>  scripts/qemu-guest-agent/fsfreeze-hook | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/scripts/qemu-guest-agent/fsfreeze-hook
>> b/scripts/qemu-guest-agent/fsfreeze-hook
>> index 13aafd4845..98aad5e18b 100755
>> --- a/scripts/qemu-guest-agent/fsfreeze-hook
>> +++ b/scripts/qemu-guest-agent/fsfreeze-hook
>> @@ -7,7 +7,7 @@
>>  # "freeze" argument before the filesystem is frozen. And for
>> fsfreeze-thaw
>>  # request, it is issued with "thaw" argument after filesystem is thawed.
>>
>> -LOGFILE=/var/log/qga-fsfreeze-hook.log
>> +LOGFILE=/var/log/qemu-ga/qga-fsfreeze-hook.log
>>  FSFREEZE_D=$(dirname -- "$0")/fsfreeze-hook.d
>>
>>  # Check whether file $1 is a backup or rpm-generated file and should be
>> ignored
>> --
>> 2.40.1
>>
>>


[PATCH] qemu-guest-agent: Update the logfile path of qga-fsfreeze-hook.log

2024-08-12 Thread Dehan Meng
Since '/var/log/qga-fsfreeze-hook.log' is not included to proper
selinux context 'system_u:object_r:virt_qemu_ga_log_t:s0', it
should be changed to '/var/log/qemu-ga/qga-fsfreeze-hook.log'

Jira: https://issues.redhat.com/browse/RHEL-52250
Signed-off-by: Dehan Meng 
---
 scripts/qemu-guest-agent/fsfreeze-hook | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/qemu-guest-agent/fsfreeze-hook 
b/scripts/qemu-guest-agent/fsfreeze-hook
index 13aafd4845..98aad5e18b 100755
--- a/scripts/qemu-guest-agent/fsfreeze-hook
+++ b/scripts/qemu-guest-agent/fsfreeze-hook
@@ -7,7 +7,7 @@
 # "freeze" argument before the filesystem is frozen. And for fsfreeze-thaw
 # request, it is issued with "thaw" argument after filesystem is thawed.
 
-LOGFILE=/var/log/qga-fsfreeze-hook.log
+LOGFILE=/var/log/qemu-ga/qga-fsfreeze-hook.log
 FSFREEZE_D=$(dirname -- "$0")/fsfreeze-hook.d
 
 # Check whether file $1 is a backup or rpm-generated file and should be ignored
-- 
2.40.1




[PATCH v6 0/1] Support IPv6 route info

2024-06-13 Thread Dehan Meng
v5 -> v6
- Support IPv6 route info

v4 -> v5
- Remove useless struct
- Rename 'GuestNetworkRouteStat' to 'GuestNetworkRoute'.

v3 -> v4
- Fix some indentation issues
- Update 'Since 8.2' to 'Since 9.1'
- Remove useless enum and adjust this change.

v2 -> v3
- Remove this declaration and make the function 'hexToIPAddress' as static.
- Define 'IFNAMSIZ' from kernel instead of a hardcode
- Remove 'GUEST_NETWORK_ROUTE_TYPE_LINUX'
- Set flags 'has_xxx' for checking if a field exists or has a value set

v1 -> v2
- Replace snprintf() to g_strdup_printf() to avoid memory problems.
- Remove the parameter 'char ipAddress[16]' in function 'char 
*hexToIPAddress()'.
- Add a piece of logic to skip traversing the first line of the file

Dehan Meng (1):
  qga/linux: Add new api 'guest-network-get-route'

 qga/commands-posix.c | 135 +++
 qga/commands-win32.c |   6 ++
 qga/qapi-schema.json |  71 +++
 3 files changed, 212 insertions(+)

-- 
2.40.1




[PATCH v6 1/1] qga/linux: Add new api 'guest-network-get-route'

2024-06-13 Thread Dehan Meng
The Route information of the Linux VM needs to be used
by administrators and users when debugging network problems
and troubleshooting.

Signed-off-by: Dehan Meng 
---
 qga/commands-posix.c | 135 +++
 qga/commands-win32.c |   6 ++
 qga/qapi-schema.json |  71 +++
 3 files changed, 212 insertions(+)

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 7f05996495..b85b3937bf 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -2708,6 +2708,135 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 return head;
 }
 
+static char *hexToIPAddress(const void *hexValue, int is_ipv6)
+{
+if (is_ipv6) {
+char addr[INET6_ADDRSTRLEN];
+struct in6_addr in6;
+const char *hexStr = (const char *)hexValue;
+int i;
+
+for (i = 0; i < 16; i++) {
+sscanf(&hexStr[i * 2], "%02hhx", &in6.s6_addr[i]);
+}
+inet_ntop(AF_INET6, &in6, addr, INET6_ADDRSTRLEN);
+
+return g_strdup(addr);
+} else {
+unsigned int hexInt = *(unsigned int *)hexValue;
+unsigned int byte1 = (hexInt >> 24) & 0xFF;
+unsigned int byte2 = (hexInt >> 16) & 0xFF;
+unsigned int byte3 = (hexInt >> 8) & 0xFF;
+unsigned int byte4 = hexInt & 0xFF;
+
+return g_strdup_printf("%u.%u.%u.%u", byte4, byte3, byte2, byte1);
+}
+}
+
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+GuestNetworkRouteList *head = NULL, **tail = &head;
+const char *routeFiles[] = {"/proc/net/route", "/proc/net/ipv6_route"};
+FILE *fp;
+size_t n;
+char *line = NULL;
+int firstLine;
+int is_ipv6;
+int i;
+
+for (i = 0; i < 2; i++) {
+firstLine = 1;
+is_ipv6 = (i == 1);
+fp = fopen(routeFiles[i], "r");
+if (fp == NULL) {
+error_setg_errno(errp, errno, "open(\"%s\")", routeFiles[i]);
+free(line);
+continue;
+}
+
+while (getline(&line, &n, fp) != -1) {
+if (firstLine && !is_ipv6) {
+firstLine = 0;
+continue;
+}
+GuestNetworkRoute *route = NULL;
+GuestNetworkRoute *networkroute;
+char Iface[IFNAMSIZ];
+if (is_ipv6) {
+char Destination[33], Source[33], NextHop[33];
+int DesPrefixlen, SrcPrefixlen, Metric, RefCnt, Use, Flags;
+
+/* Parse the line and extract the values */
+if (sscanf(line, "%32s %x %32s %x %32s %x %x %x %x %32s",
+   Destination, &DesPrefixlen, Source,
+   &SrcPrefixlen, NextHop, &Metric, &RefCnt,
+   &Use, &Flags, Iface) != 10) {
+continue;
+}
+
+route = g_new0(GuestNetworkRoute, 1);
+networkroute = route;
+networkroute->iface = g_strdup(Iface);
+networkroute->destination = hexToIPAddress(Destination, 1);
+networkroute->metric = Metric;
+networkroute->source = hexToIPAddress(Source, 1);
+networkroute->desprefixlen = g_strdup_printf(
+"%d", DesPrefixlen
+);
+networkroute->srcprefixlen = g_strdup_printf(
+"%d", SrcPrefixlen
+);
+networkroute->nexthop = hexToIPAddress(NextHop, 1);
+networkroute->has_flags = true;
+networkroute->flags = Flags;
+networkroute->has_refcnt = true;
+networkroute->refcnt = RefCnt;
+networkroute->has_use = true;
+networkroute->use = Use;
+networkroute->version = 6;
+} else {
+unsigned int Destination, Gateway, Mask, Flags;
+int RefCnt, Use, Metric, MTU, Window, IRTT;
+
+/* Parse the line and extract the values */
+if (sscanf(line, "%s %X %X %x %d %d %d %X %d %d %d",
+   Iface, &Destination, &Gateway, &Flags, &RefCnt,
+   &Use, &Metric, &Mask, &MTU, &Window, &IRTT) != 11) {
+continue;
+}
+
+route = g_new0(GuestNetworkRoute, 1);
+networkroute = route;
+networkroute->iface = g_strdup(Iface);
+networkroute->destination = hexToIPAddress(&Destination, 0);
+networkroute->gateway = hexToIPAddress(&Gateway, 0);
+networkroute->mask = hexToIPAddress(&Mask, 0);
+

[PATCH v5 0/1] qga/linux: Add new api 'guest-network-get-route'

2024-06-12 Thread Dehan Meng
v4 -> v5
- Remove useless struct
- Rename 'GuestNetworkRouteStat' to 'GuestNetworkRoute'.

v3 -> v4
- Fix some indentation issues
- Update 'Since 8.2' to 'Since 9.1'
- Remove useless enum and adjust this change.

v2 -> v3
- Remove this declaration and make the function 'hexToIPAddress' as static.
- Define 'IFNAMSIZ' from kernel instead of a hardcode
- Remove 'GUEST_NETWORK_ROUTE_TYPE_LINUX'
- Set flags 'has_xxx' for checking if a field exists or has a value set

v1 -> v2
- Replace snprintf() to g_strdup_printf() to avoid memory problems.
- Remove the parameter 'char ipAddress[16]' in function 'char 
*hexToIPAddress()'.
- Add a piece of logic to skip traversing the first line of the file

Dehan Meng (1):
  qga/linux: Add new api 'guest-network-get-route'

 qga/commands-posix.c | 81 
 qga/commands-win32.c |  6 
 qga/qapi-schema.json | 56 ++
 3 files changed, 143 insertions(+)

-- 
2.40.1




[PATCH v5 1/1] qga/linux: Add new api 'guest-network-get-route'

2024-06-12 Thread Dehan Meng
The Route information of the Linux VM needs to be used
by administrators and users when debugging network problems
and troubleshooting.

Signed-off-by: Dehan Meng 
---
 qga/commands-posix.c | 81 
 qga/commands-win32.c |  6 
 qga/qapi-schema.json | 56 ++
 3 files changed, 143 insertions(+)

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 7f05996495..b1f65716e9 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -2708,6 +2708,81 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 return head;
 }
 
+static char *hexToIPAddress(unsigned int hexValue)
+{
+unsigned int byte1 = (hexValue >> 24) & 0xFF;
+unsigned int byte2 = (hexValue >> 16) & 0xFF;
+unsigned int byte3 = (hexValue >> 8) & 0xFF;
+unsigned int byte4 = hexValue & 0xFF;
+
+return g_strdup_printf("%u.%u.%u.%u", byte4, byte3, byte2, byte1);
+}
+
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+GuestNetworkRouteList *head = NULL, **tail = &head;
+const char *routeFile = "/proc/net/route";
+FILE *fp;
+size_t n;
+char *line = NULL;
+int firstLine = 1;
+
+fp = fopen(routeFile, "r");
+if (fp == NULL) {
+error_setg_errno(errp, errno, "open(\"%s\")", routeFile);
+free(line);
+return NULL;
+}
+
+while (getline(&line, &n, fp) != -1) {
+if (firstLine) {
+firstLine = 0;
+continue;
+}
+GuestNetworkRoute *route = NULL;
+GuestNetworkRoute *networkroute;
+int i;
+char Iface[IFNAMSIZ];
+unsigned int Destination, Gateway, Mask, Flags;
+int RefCnt, Use, Metric, MTU, Window, IRTT;
+
+/* Parse the line and extract the values */
+i = (sscanf(line, "%s %X %X %x %d %d %d %X %d %d %d",
+Iface, &Destination, &Gateway, &Flags, &RefCnt,
+&Use, &Metric, &Mask, &MTU, &Window, &IRTT) == 11);
+if (i == EOF) {
+continue;
+}
+
+route = g_new0(GuestNetworkRoute, 1);
+
+networkroute = route;
+networkroute->iface = g_strdup(Iface);
+networkroute->destination = hexToIPAddress(Destination);
+networkroute->gateway = hexToIPAddress(Gateway);
+networkroute->mask = hexToIPAddress(Mask);
+networkroute->metric = Metric;
+networkroute->has_flags = true;
+networkroute->flags = Flags;
+networkroute->has_refcnt = true;
+networkroute->refcnt = RefCnt;
+networkroute->has_use = true;
+networkroute->use = Use;
+networkroute->has_mtu = true;
+networkroute->mtu = MTU;
+networkroute->has_window = true;
+networkroute->window = Window;
+networkroute->has_irtt = true;
+networkroute->irtt = IRTT;
+
+QAPI_LIST_APPEND(tail, route);
+}
+
+free(line);
+fclose(fp);
+return head;
+}
+
 #else /* defined(__linux__) */
 
 void qmp_guest_suspend_disk(Error **errp)
@@ -3079,6 +3154,12 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 return NULL;
 }
 
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
+
 #endif /* CONFIG_FSFREEZE */
 
 #if !defined(CONFIG_FSTRIM)
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 0d1b836e87..91289bc9ab 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -2517,3 +2517,9 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 error_setg(errp, QERR_UNSUPPORTED);
 return NULL;
 }
+
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index b3de1fb6b3..58f51aecbb 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -1800,3 +1800,59 @@
 { 'command': 'guest-get-cpustats',
   'returns': ['GuestCpuStats']
 }
+
+##
+# @GuestNetworkRoute:
+#
+# Route information, currently, only linux supported.
+#
+# @iface: The destination network or host's egress network interface in the 
routing table
+#
+# @destination: The IP address of the target network or host, The final 
destination of the packet
+#
+# @gateway: The IP address of the next hop router
+#
+# @mask: Subnet Mask
+#
+# @metric: Route metric
+#
+# @flags: Route flags (not for windows)
+#
+# @irtt: Initial round-trip delay (not for windows)
+#
+# @refcnt: The route's reference count (not for windows)
+#
+# @use: Route usage count (not for windows)
+#
+# @window: TCP window size, used for flow control (not for windows)
+#
+# @mtu: Data link layer maximum packet size (

[PATCH v4 1/1] qga/linux: Add new api 'guest-network-get-route'

2024-06-11 Thread Dehan Meng
The Route information of the Linux VM needs to be used
by administrators and users when debugging network problems
and troubleshooting.

Signed-off-by: Dehan Meng 
---
 qga/commands-posix.c | 73 
 qga/commands-win32.c |  6 
 qga/qapi-schema.json | 68 +
 3 files changed, 147 insertions(+)

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 6169bbf7a0..ffae88ca69 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -2747,6 +2747,73 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 return head;
 }
 
+char *hexToIPAddress(unsigned int hexValue, char ipAddress[16]);
+char *hexToIPAddress(unsigned int hexValue, char ipAddress[16])
+{
+unsigned int byte1 = (hexValue >> 24) & 0xFF;
+unsigned int byte2 = (hexValue >> 16) & 0xFF;
+unsigned int byte3 = (hexValue >> 8) & 0xFF;
+unsigned int byte4 = hexValue & 0xFF;
+
+snprintf(ipAddress, 16, "%u.%u.%u.%u", byte4, byte3, byte2, byte1);
+
+return ipAddress;
+}
+
+GuestNetworkRouteStatList *qmp_guest_network_get_route(Error **errp)
+{
+GuestNetworkRouteStatList *head = NULL, **tail = &head;
+const char *routeFile = "/proc/net/route";
+FILE *fp;
+size_t n;
+char *line = NULL;
+
+fp = fopen(routeFile, "r");
+if (fp == NULL) {
+error_setg_errno(errp, errno, "open(\"%s\")", routeFile);
+return NULL;
+}
+
+while (getline(&line, &n, fp) != -1) {
+GuestNetworkRouteStat *networkroute;
+int i;
+char Iface[16];
+unsigned int Destination, Gateway, Mask, Flags;
+int RefCnt, Use, Metric, MTU, Window, IRTT;
+
+i = (sscanf(line, "%s %X %X %x %d %d %d %X %d %d %d",
+Iface, &Destination, &Gateway, &Flags, &RefCnt,
+&Use, &Metric, &Mask, &MTU, &Window, &IRTT) == 11);
+if (i == EOF) {
+continue;
+}
+
+networkroute = g_new0(GuestNetworkRouteStat, 1);
+
+char DestAddress[16];
+char GateAddress[16];
+char MaskAddress[16];
+
+networkroute->iface = g_strdup(Iface);
+networkroute->destination = g_strdup(hexToIPAddress(Destination, 
DestAddress));
+networkroute->gateway = g_strdup(hexToIPAddress(Gateway, GateAddress));
+networkroute->mask = g_strdup(hexToIPAddress(Mask, MaskAddress));
+networkroute->metric = Metric;
+networkroute->flags = Flags;
+networkroute->refcnt = RefCnt;
+networkroute->use = Use;
+networkroute->mtu = MTU;
+networkroute->window = Window;
+networkroute->irtt = IRTT;
+
+QAPI_LIST_APPEND(tail, networkroute);
+}
+
+free(line);
+fclose(fp);
+return head;
+}
+
 #else /* defined(__linux__) */
 
 void qmp_guest_suspend_disk(Error **errp)
@@ -3118,6 +3185,12 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 return NULL;
 }
 
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
+
 #endif /* CONFIG_FSFREEZE */
 
 #if !defined(CONFIG_FSTRIM)
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 697c65507c..e62c04800a 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -2522,3 +2522,9 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 error_setg(errp, QERR_UNSUPPORTED);
 return NULL;
 }
+
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 876e2a8ea8..195f6cd4e7 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -1789,3 +1789,71 @@
 { 'command': 'guest-get-cpustats',
   'returns': ['GuestCpuStats']
 }
+
+##
+# @GuestNetworkRouteStat:
+#
+# Route information, currently, only linux supported.
+#
+# @iface: The destination network or host's egress network interface in the 
routing table
+#
+# @destination: The IP address of the target network or host, The final 
destination of the packet
+#
+# @gateway: The IP address of the next hop router
+#
+# @mask: Subnet Mask
+#
+# @metric: Route metricls
+#
+# @flags: Route flags (not for windows)
+#
+# @irtt: Initial round-trip delay (not for windows)
+#
+# @refcnt: The route's reference count (not for windows)
+#
+# @use: Route usage count (not for windows)
+#
+# @window: TCP window size, used for flow control (not for windows)
+#
+# @mtu: Data link layer maximum packet size (not for windows)
+#
+# Since: 9.1
+
+##
+{ 'struct': 'GuestNetworkRouteStat',
+  'data': {'iface': 'str',
+   'destination': 'str',
+ 

[PATCH v4 0/1] qga/linux: Add new api 'guest-network-get-route'

2024-06-11 Thread Dehan Meng
v3 -> v4
- Fix some indentation issues
- Update 'Since 8.2' to 'Since 9.1'
- Remove useless enum and adjust this change.

v2 -> v3
- Remove this declaration and make the function 'hexToIPAddress' as static.
- Define 'IFNAMSIZ' from kernel instead of a hardcode
- Remove 'GUEST_NETWORK_ROUTE_TYPE_LINUX'
- Set flags 'has_xxx' for checking if a field exists or has a value set

v1 -> v2
- Replace snprintf() to g_strdup_printf() to avoid memory problems.
- Remove the parameter 'char ipAddress[16]' in function 'char 
*hexToIPAddress()'.
- Add a piece of logic to skip traversing the first line of the file

Dehan Meng (1):
  qga/linux: Add new api 'guest-network-get-route'

 qga/commands-posix.c | 73 
 qga/commands-win32.c |  6 
 qga/qapi-schema.json | 68 +
 3 files changed, 147 insertions(+)

-- 
2.40.1




Re: [PATCH v8 2/2] Implement SSH commands in QEMU GA for Windows

2024-04-24 Thread Dehan Meng
Dehan Meng 
4:55 PM (15 minutes ago)
to aidaleuc, qemu-devel, kkostiuk

QE tested this series's patches. SSH-relevant commands work and
password-free login can be achieved.

Tested-by: Dehan Meng 

On Tue, Apr 23, 2024 at 11:03 PM  wrote:

> From: aidaleuc 
>
> Signed-off-by: aidaleuc 
> ---
>  qga/commands-windows-ssh.c | 712 +
>  qga/commands-windows-ssh.h |  26 ++
>  qga/meson.build|   5 +-
>  qga/qapi-schema.json   |  17 +-
>  4 files changed, 749 insertions(+), 11 deletions(-)
>  create mode 100644 qga/commands-windows-ssh.c
>  create mode 100644 qga/commands-windows-ssh.h
>
> diff --git a/qga/commands-windows-ssh.c b/qga/commands-windows-ssh.c
> new file mode 100644
> index 00..6a642e3ba8
> --- /dev/null
> +++ b/qga/commands-windows-ssh.c
> @@ -0,0 +1,712 @@
> +/*
> + * QEMU Guest Agent win32-specific command implementations for SSH keys.
> + * The implementation is opinionated and expects the SSH implementation to
> + * be OpenSSH.
> + *
> + * Copyright Schweitzer Engineering Laboratories. 2024
> + *
> + * Authors:
> + *  Aidan Leuck 
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or
> later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include 
> +#include 
> +
> +#include "commands-common-ssh.h"
> +#include "commands-windows-ssh.h"
> +#include "guest-agent-core.h"
> +#include "limits.h"
> +#include "lmaccess.h"
> +#include "lmapibuf.h"
> +#include "lmerr.h"
> +#include "qapi/error.h"
> +
> +#include "qga-qapi-commands.h"
> +#include "sddl.h"
> +#include "shlobj.h"
> +#include "userenv.h"
> +
> +#define AUTHORIZED_KEY_FILE "authorized_keys"
> +#define AUTHORIZED_KEY_FILE_ADMIN "administrators_authorized_keys"
> +#define LOCAL_SYSTEM_SID "S-1-5-18"
> +#define ADMIN_SID "S-1-5-32-544"
> +
> +/*
> + * Frees userInfo structure. This implements the g_auto cleanup
> + * for the structure.
> + */
> +void free_userInfo(PWindowsUserInfo info)
> +{
> +g_free(info->sshDirectory);
> +g_free(info->authorizedKeyFile);
> +LocalFree(info->SSID);
> +g_free(info->username);
> +g_free(info);
> +}
> +
> +/*
> + * Gets the admin SSH folder for OpenSSH. OpenSSH does not store
> + * the authorized_key file in the users home directory for security
> reasons and
> + * instead stores it at %PROGRAMDATA%/ssh. This function returns the path
> to
> + * that directory on the users machine
> + *
> + * parameters:
> + * errp -> error structure to set when an error occurs
> + * returns: The path to the ssh folder in %PROGRAMDATA% or NULL if an
> error
> + * occurred.
> + */
> +static char *get_admin_ssh_folder(Error **errp)
> +{
> +/* Allocate memory for the program data path */
> +g_autofree char *programDataPath = NULL;
> +char *authkeys_path = NULL;
> +PWSTR pgDataW = NULL;
> +g_autoptr(GError) gerr = NULL;
> +
> +/* Get the KnownFolderPath on the machine. */
> +HRESULT folderResult =
> +SHGetKnownFolderPath(&FOLDERID_ProgramData, 0, NULL, &pgDataW);
> +if (folderResult != S_OK) {
> +error_setg(errp, "Failed to retrieve ProgramData folder");
> +return NULL;
> +}
> +
> +/* Convert from a wide string back to a standard character string. */
> +programDataPath = g_utf16_to_utf8(pgDataW, -1, NULL, NULL, &gerr);
> +CoTaskMemFree(pgDataW);
> +if (!programDataPath) {
> +error_setg(errp,
> +   "Failed converting ProgramData folder path to UTF-16
> %s",
> +   gerr->message);
> +return NULL;
> +}
> +
> +/* Build the path to the file. */
> +authkeys_path = g_build_filename(programDataPath, "ssh", NULL);
> +return authkeys_path;
> +}
> +
> +/*
> + * Gets the path to the SSH folder for the specified user. If the user is
> an
> + * admin it returns the ssh folder located at %PROGRAMDATA%/ssh. If the
> user is
> + * not an admin it returns %USERPROFILE%/.ssh
> + *
> + * parameters:
> + * username -> Username to get the SSH folder for
> + * isAdmin -> Whether the user is an admin or not
> + * errp -> Error structure to set any errors that occur.
> + * returns: path to the ssh folder as a string.
> + */
> +static char *get_ssh_folder(const char *username, const bool isAdmin,
> +Error **errp)
> +{

Re: [PATCH v8 2/2] Implement SSH commands in QEMU GA for Windows

2024-04-24 Thread Dehan Meng
QE tested this series's patches. SSH-relevant commands work and
password-free login can be achieved.

Tested-by: Dehan Meng 

On Tue, Apr 23, 2024 at 11:03 PM  wrote:

> From: aidaleuc 
>
> Signed-off-by: aidaleuc 
> ---
>  qga/commands-windows-ssh.c | 712 +
>  qga/commands-windows-ssh.h |  26 ++
>  qga/meson.build|   5 +-
>  qga/qapi-schema.json   |  17 +-
>  4 files changed, 749 insertions(+), 11 deletions(-)
>  create mode 100644 qga/commands-windows-ssh.c
>  create mode 100644 qga/commands-windows-ssh.h
>
> diff --git a/qga/commands-windows-ssh.c b/qga/commands-windows-ssh.c
> new file mode 100644
> index 00..6a642e3ba8
> --- /dev/null
> +++ b/qga/commands-windows-ssh.c
> @@ -0,0 +1,712 @@
> +/*
> + * QEMU Guest Agent win32-specific command implementations for SSH keys.
> + * The implementation is opinionated and expects the SSH implementation to
> + * be OpenSSH.
> + *
> + * Copyright Schweitzer Engineering Laboratories. 2024
> + *
> + * Authors:
> + *  Aidan Leuck 
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or
> later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include 
> +#include 
> +
> +#include "commands-common-ssh.h"
> +#include "commands-windows-ssh.h"
> +#include "guest-agent-core.h"
> +#include "limits.h"
> +#include "lmaccess.h"
> +#include "lmapibuf.h"
> +#include "lmerr.h"
> +#include "qapi/error.h"
> +
> +#include "qga-qapi-commands.h"
> +#include "sddl.h"
> +#include "shlobj.h"
> +#include "userenv.h"
> +
> +#define AUTHORIZED_KEY_FILE "authorized_keys"
> +#define AUTHORIZED_KEY_FILE_ADMIN "administrators_authorized_keys"
> +#define LOCAL_SYSTEM_SID "S-1-5-18"
> +#define ADMIN_SID "S-1-5-32-544"
> +
> +/*
> + * Frees userInfo structure. This implements the g_auto cleanup
> + * for the structure.
> + */
> +void free_userInfo(PWindowsUserInfo info)
> +{
> +g_free(info->sshDirectory);
> +g_free(info->authorizedKeyFile);
> +LocalFree(info->SSID);
> +g_free(info->username);
> +g_free(info);
> +}
> +
> +/*
> + * Gets the admin SSH folder for OpenSSH. OpenSSH does not store
> + * the authorized_key file in the users home directory for security
> reasons and
> + * instead stores it at %PROGRAMDATA%/ssh. This function returns the path
> to
> + * that directory on the users machine
> + *
> + * parameters:
> + * errp -> error structure to set when an error occurs
> + * returns: The path to the ssh folder in %PROGRAMDATA% or NULL if an
> error
> + * occurred.
> + */
> +static char *get_admin_ssh_folder(Error **errp)
> +{
> +/* Allocate memory for the program data path */
> +g_autofree char *programDataPath = NULL;
> +char *authkeys_path = NULL;
> +PWSTR pgDataW = NULL;
> +g_autoptr(GError) gerr = NULL;
> +
> +/* Get the KnownFolderPath on the machine. */
> +HRESULT folderResult =
> +SHGetKnownFolderPath(&FOLDERID_ProgramData, 0, NULL, &pgDataW);
> +if (folderResult != S_OK) {
> +error_setg(errp, "Failed to retrieve ProgramData folder");
> +return NULL;
> +}
> +
> +/* Convert from a wide string back to a standard character string. */
> +programDataPath = g_utf16_to_utf8(pgDataW, -1, NULL, NULL, &gerr);
> +CoTaskMemFree(pgDataW);
> +if (!programDataPath) {
> +error_setg(errp,
> +   "Failed converting ProgramData folder path to UTF-16
> %s",
> +   gerr->message);
> +return NULL;
> +}
> +
> +/* Build the path to the file. */
> +authkeys_path = g_build_filename(programDataPath, "ssh", NULL);
> +return authkeys_path;
> +}
> +
> +/*
> + * Gets the path to the SSH folder for the specified user. If the user is
> an
> + * admin it returns the ssh folder located at %PROGRAMDATA%/ssh. If the
> user is
> + * not an admin it returns %USERPROFILE%/.ssh
> + *
> + * parameters:
> + * username -> Username to get the SSH folder for
> + * isAdmin -> Whether the user is an admin or not
> + * errp -> Error structure to set any errors that occur.
> + * returns: path to the ssh folder as a string.
> + */
> +static char *get_ssh_folder(const char *username, const bool isAdmin,
> +Error **errp)
> +{
> +DWORD maxSize = MAX_PATH;
> +g_autofree char *profilesD

Re: [PATCH v2 0/7] qga/commands-posix: replace code duplicating commands with a helper

2024-03-04 Thread Dehan Meng
QE tested this series's patches. qga-related commands worked successfully.

Tested-by: Dehan Meng 


On Mon, Mar 4, 2024 at 8:00 PM Konstantin Kostiuk 
wrote:

> For series
> Reviewed-by: Konstantin Kostiuk 
>
> On Fri, Mar 1, 2024 at 7:29 PM Andrey Drobyshev <
> andrey.drobys...@virtuozzo.com> wrote:
>
>> v1 --> v2:
>>  * Replace commit for guest-get-fsinfo: instead of reporting statvfs(3)
>>values directly, keep the old ones but add an additional optional
>>field 'total-bytes-root', only reported in POSIX.  Also tweak the
>>fields description in qga/qapi-schema.json to document where the
>>values come from.
>>
>> v1:
>> https://lists.nongnu.org/archive/html/qemu-devel/2024-02/msg05766.html
>>
>> Andrey Drobyshev (7):
>>   qga: guest-get-fsinfo: add optional 'total-bytes-root' field
>>   qga: introduce ga_run_command() helper for guest cmd execution
>>   qga/commands-posix: qmp_guest_shutdown: use ga_run_command helper
>>   qga/commands-posix: qmp_guest_set_time: use ga_run_command helper
>>   qga/commands-posix: execute_fsfreeze_hook: use ga_run_command helper
>>   qga/commands-posix: use ga_run_command helper when suspending via
>> sysfs
>>   qga/commands-posix: qmp_guest_set_user_password: use ga_run_command
>> helper
>>
>>  qga/commands-posix.c | 389 +++
>>  qga/commands-win32.c |   1 +
>>  qga/qapi-schema.json |  12 +-
>>  3 files changed, 182 insertions(+), 220 deletions(-)
>>
>> --
>> 2.39.3
>>
>>


[PATCH v3 0/1] Optimize Code

2024-02-28 Thread Dehan Meng
v2 -> v3
- Remove this declaration and make the function 'hexToIPAddress' as static.
- Define 'IFNAMSIZ' from kernel instead of a hardcode
- Remove 'GUEST_NETWORK_ROUTE_TYPE_LINUX'
- Set flags 'has_xxx' for checking if a field exists or has a value set

v1 -> v2
- Replace snprintf() to g_strdup_printf() to avoid memory problems.
- Remove the parameter 'char ipAddress[16]' in function 'char 
*hexToIPAddress()'.
- Add a piece of logic to skip traversing the first line of the file

Dehan Meng (1):
  qga/linux: Add new api 'guest-network-get-route'

 qga/commands-posix.c | 81 
 qga/commands-win32.c |  6 
 qga/qapi-schema.json | 80 +++
 3 files changed, 167 insertions(+)

-- 
2.40.1




[PATCH v3 1/1] qga/linux: Add new api 'guest-network-get-route'

2024-02-28 Thread Dehan Meng
The Route information of the Linux VM needs to be used
by administrators and users when debugging network problems
and troubleshooting.

Signed-off-by: Dehan Meng 
---
 qga/commands-posix.c | 81 
 qga/commands-win32.c |  6 
 qga/qapi-schema.json | 80 +++
 3 files changed, 167 insertions(+)

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 6169bbf7a0..3ac517423f 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -2747,6 +2747,81 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 return head;
 }
 
+static char *hexToIPAddress(unsigned int hexValue)
+{
+unsigned int byte1 = (hexValue >> 24) & 0xFF;
+unsigned int byte2 = (hexValue >> 16) & 0xFF;
+unsigned int byte3 = (hexValue >> 8) & 0xFF;
+unsigned int byte4 = hexValue & 0xFF;
+
+return g_strdup_printf("%u.%u.%u.%u", byte4, byte3, byte2, byte1);
+}
+
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+GuestNetworkRouteList *head = NULL, **tail = &head;
+const char *routeFile = "/proc/net/route";
+FILE *fp;
+size_t n;
+char *line = NULL;
+int firstLine = 1;
+
+fp = fopen(routeFile, "r");
+if (fp == NULL) {
+error_setg_errno(errp, errno, "open(\"%s\")", routeFile);
+free(line);
+return NULL;
+}
+
+while (getline(&line, &n, fp) != -1) {
+if (firstLine) {
+firstLine = 0;
+continue;
+}
+GuestNetworkRoute *route = NULL;
+GuestNetworkRouteStat *networkroute;
+int i;
+   char Iface[IFNAMSIZ];
+unsigned int Destination, Gateway, Mask, Flags;
+int RefCnt, Use, Metric, MTU, Window, IRTT;
+
+/* Parse the line and extract the values */
+i = (sscanf(line, "%s %X %X %x %d %d %d %X %d %d %d",
+Iface, &Destination, &Gateway, &Flags, &RefCnt,
+&Use, &Metric, &Mask, &MTU, &Window, &IRTT) == 11);
+if (i == EOF) {
+continue;
+}
+
+route = g_new0(GuestNetworkRoute, 1);
+
+networkroute = &route->u.q_linux;
+networkroute->iface = g_strdup(Iface);
+networkroute->destination = hexToIPAddress(Destination);
+networkroute->gateway = hexToIPAddress(Gateway);
+networkroute->mask = hexToIPAddress(Mask);
+networkroute->metric = Metric;
+   networkroute->has_flags = true;
+networkroute->flags = Flags;
+networkroute->has_refcnt = true;
+networkroute->refcnt = RefCnt;
+networkroute->has_use = true;
+networkroute->use = Use;
+networkroute->has_mtu = true;
+networkroute->mtu = MTU;
+networkroute->has_window = true;
+networkroute->window = Window;
+networkroute->has_irtt = true;
+networkroute->irtt = IRTT;
+
+QAPI_LIST_APPEND(tail, route);
+}
+
+free(line);
+fclose(fp);
+return head;
+}
+
 #else /* defined(__linux__) */
 
 void qmp_guest_suspend_disk(Error **errp)
@@ -3118,6 +3193,12 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 return NULL;
 }
 
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
+
 #endif /* CONFIG_FSFREEZE */
 
 #if !defined(CONFIG_FSTRIM)
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 697c65507c..e62c04800a 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -2522,3 +2522,9 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 error_setg(errp, QERR_UNSUPPORTED);
 return NULL;
 }
+
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 876e2a8ea8..eed9539bb7 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -1789,3 +1789,83 @@
 { 'command': 'guest-get-cpustats',
   'returns': ['GuestCpuStats']
 }
+
+##
+# @GuestNetworkRouteType:
+#
+# An enumeration of OS type
+#
+# Since: 8.2
+##
+{ 'enum': 'GuestNetworkRouteType',
+  'data': [ 'linux' ] }
+
+##
+# @GuestNetworkRouteStat:
+#
+# Route information, currently, only linux supported.
+#
+# @iface: The destination network or host's egress network interface in the 
routing table
+#
+# @destination: The IP address of the target network or host, The final 
destination of the packet
+#
+# @gateway: The IP address of the next hop router
+#
+# @mask: Subnet Mask
+#
+# @metric: Route metric
+#
+# @flags: Route flags (not for windows)
+#
+# @irtt: Initial round-trip delay (not for windows)
+#
+# @refcnt: T

Re: [PATCH] qga-win: Add support of Windows Server 2025 in get-osinfo command

2024-02-21 Thread Dehan Meng
Done. thanks.

On Wed, Feb 21, 2024 at 6:00 PM Konstantin Kostiuk 
wrote:

>
>
> On Wed, Feb 21, 2024 at 11:51 AM Dehan Meng  wrote:
>
>> Add support of Windows Server 2025 in get-osinfo command
>>
>> Signed-off-by: Dehan Meng 
>> ---
>>  qga/commands-win32.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/qga/commands-win32.c b/qga/commands-win32.c
>> index 697c65507c..f3c7e604c9 100644
>> --- a/qga/commands-win32.c
>> +++ b/qga/commands-win32.c
>> @@ -2154,6 +2154,7 @@ static ga_win_10_0_t const
>> WIN_10_0_SERVER_VERSION_MATRIX[4] = {
>>
>
> You don't update the array size, there are out of range elements
>
>
>>  {14393, "Microsoft Windows Server 2016","2016"},
>>  {17763, "Microsoft Windows Server 2019","2019"},
>>  {20344, "Microsoft Windows Server 2022","2022"},
>> +{26040, "MIcrosoft Windows Server 2025","2025"},
>>  {0, 0}
>>  };
>>
>> --
>> 2.35.1
>>
>>


[PATCH v2 0/1] update the array size

2024-02-21 Thread Dehan Meng
v1 -> v2
update the array size "WIN_10_0_SERVER_VERSION_MATRIX" in case 
array out of range elements.

Dehan Meng (1):
  qga-win: Add support of Windows Server 2025 in get-osinfo command

 qga/commands-win32.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

-- 
2.35.1




[PATCH v2 1/1] qga-win: Add support of Windows Server 2025 in get-osinfo command

2024-02-21 Thread Dehan Meng
Add support of Windows Server 2025 in get-osinfo command

Signed-off-by: Dehan Meng 
---
 qga/commands-win32.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 697c65507c..b37fa7b5ba 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -2150,10 +2150,11 @@ typedef struct _ga_win_10_0_t {
 char const *version_id;
 } ga_win_10_0_t;
 
-static ga_win_10_0_t const WIN_10_0_SERVER_VERSION_MATRIX[4] = {
+static ga_win_10_0_t const WIN_10_0_SERVER_VERSION_MATRIX[5] = {
 {14393, "Microsoft Windows Server 2016","2016"},
 {17763, "Microsoft Windows Server 2019","2019"},
 {20344, "Microsoft Windows Server 2022","2022"},
+{26040, "MIcrosoft Windows Server 2025","2025"},
 {0, 0}
 };
 
-- 
2.35.1




[PATCH v2 1/1] qga-win: Add support of Windows Server 2025 in get-osinfo command

2024-02-21 Thread Dehan Meng
Add support of Windows Server 2025 in get-osinfo command

Signed-off-by: Dehan Meng 
---
 qga/commands-win32.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 697c65507c..b37fa7b5ba 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -2150,10 +2150,11 @@ typedef struct _ga_win_10_0_t {
 char const *version_id;
 } ga_win_10_0_t;
 
-static ga_win_10_0_t const WIN_10_0_SERVER_VERSION_MATRIX[4] = {
+static ga_win_10_0_t const WIN_10_0_SERVER_VERSION_MATRIX[5] = {
 {14393, "Microsoft Windows Server 2016","2016"},
 {17763, "Microsoft Windows Server 2019","2019"},
 {20344, "Microsoft Windows Server 2022","2022"},
+{26040, "MIcrosoft Windows Server 2025","2025"},
 {0, 0}
 };
 
-- 
2.35.1




[PATCH v2 0/1] update the array size

2024-02-21 Thread Dehan Meng
v1 -> v2
update the array size "WIN_10_0_SERVER_VERSION_MATRIX" in case 
array out of range elements.

Dehan Meng (1):
  qga-win: Add support of Windows Server 2025 in get-osinfo command

 qga/commands-win32.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

-- 
2.35.1




[PATCH v2 1/1] qga/linux: Add new api 'guest-network-get-route'

2024-02-21 Thread Dehan Meng
The Route information of the Linux VM needs to be used
by administrators and users when debugging network problems
and troubleshooting.

Signed-off-by: Dehan Meng 
---
 qga/commands-posix.c | 78 ++
 qga/commands-win32.c |  6 
 qga/qapi-schema.json | 80 
 3 files changed, 164 insertions(+)

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 6169bbf7a0..894cc43fce 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -2747,6 +2747,78 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 return head;
 }
 
+char *hexToIPAddress(unsigned int hexValue);
+
+char *hexToIPAddress(unsigned int hexValue)
+{
+unsigned int byte1 = (hexValue >> 24) & 0xFF;
+unsigned int byte2 = (hexValue >> 16) & 0xFF;
+unsigned int byte3 = (hexValue >> 8) & 0xFF;
+unsigned int byte4 = hexValue & 0xFF;
+
+return g_strdup_printf("%u.%u.%u.%u", byte4, byte3, byte2, byte1);
+}
+
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+GuestNetworkRouteList *head = NULL, **tail = &head;
+const char *routeFile = "/proc/net/route";
+FILE *fp;
+size_t n;
+char *line = NULL;
+int firstLine = 1;
+
+fp = fopen(routeFile, "r");
+if (fp == NULL) {
+error_setg_errno(errp, errno, "open(\"%s\")", routeFile);
+free(line);
+return NULL;
+}
+
+while (getline(&line, &n, fp) != -1) {
+if (firstLine) {
+firstLine = 0;
+continue;
+}
+GuestNetworkRoute *route = NULL;
+GuestNetworkRouteStat *networkroute;
+int i;
+char Iface[16];
+unsigned int Destination, Gateway, Mask, Flags;
+int RefCnt, Use, Metric, MTU, Window, IRTT;
+
+/* Parse the line and extract the values */
+i = (sscanf(line, "%s %X %X %x %d %d %d %X %d %d %d",
+Iface, &Destination, &Gateway, &Flags, &RefCnt,
+&Use, &Metric, &Mask, &MTU, &Window, &IRTT) == 11);
+if (i == EOF) {
+continue;
+}
+
+route = g_new0(GuestNetworkRoute, 1);
+route->type = GUEST_NETWORK_ROUTE_TYPE_LINUX;
+
+networkroute = &route->u.q_linux;
+networkroute->iface = g_strdup(Iface);
+networkroute->destination = hexToIPAddress(Destination);
+networkroute->gateway = hexToIPAddress(Gateway);
+networkroute->mask = hexToIPAddress(Mask);
+networkroute->metric = Metric;
+networkroute->flags = Flags;
+networkroute->refcnt = RefCnt;
+networkroute->use = Use;
+networkroute->mtu = MTU;
+networkroute->window = Window;
+networkroute->irtt = IRTT;
+
+QAPI_LIST_APPEND(tail, route);
+}
+
+free(line);
+fclose(fp);
+return head;
+}
+
 #else /* defined(__linux__) */
 
 void qmp_guest_suspend_disk(Error **errp)
@@ -3118,6 +3190,12 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 return NULL;
 }
 
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
+
 #endif /* CONFIG_FSFREEZE */
 
 #if !defined(CONFIG_FSTRIM)
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 697c65507c..e62c04800a 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -2522,3 +2522,9 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 error_setg(errp, QERR_UNSUPPORTED);
 return NULL;
 }
+
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 876e2a8ea8..eed9539bb7 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -1789,3 +1789,83 @@
 { 'command': 'guest-get-cpustats',
   'returns': ['GuestCpuStats']
 }
+
+##
+# @GuestNetworkRouteType:
+#
+# An enumeration of OS type
+#
+# Since: 8.2
+##
+{ 'enum': 'GuestNetworkRouteType',
+  'data': [ 'linux' ] }
+
+##
+# @GuestNetworkRouteStat:
+#
+# Route information, currently, only linux supported.
+#
+# @iface: The destination network or host's egress network interface in the 
routing table
+#
+# @destination: The IP address of the target network or host, The final 
destination of the packet
+#
+# @gateway: The IP address of the next hop router
+#
+# @mask: Subnet Mask
+#
+# @metric: Route metric
+#
+# @flags: Route flags (not for windows)
+#
+# @irtt: Initial round-trip delay (not for windows)
+#
+# @refcnt: The route's reference count (not for windows)
+#
+# @use: Route usage count (not for windows)
+#
+# @window: TCP window size, used for flow control (not for wi

[PATCH 1/1] qga/linux: Add new api 'guest-network-get-route'

2024-02-21 Thread Dehan Meng
v1 -> v2
- Replace snprintf() to g_strdup_printf() to avoid memory problems.
- Remove the parameter 'char ipAddress[16]' in function 'char 
*hexToIPAddress()'.
- Add a piece of logic to skip traversing the first line of the file

Dehan Meng (1):
  qga/linux: Add new api 'guest-network-get-route'

 qga/commands-posix.c | 78 ++
 qga/commands-win32.c |  6 
 qga/qapi-schema.json | 80 
 3 files changed, 164 insertions(+)

-- 
2.35.1




[PATCH] qga-win: Add support of Windows Server 2025 in get-osinfo command

2024-02-21 Thread Dehan Meng
Add support of Windows Server 2025 in get-osinfo command

Signed-off-by: Dehan Meng 
---
 qga/commands-win32.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 697c65507c..f3c7e604c9 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -2154,6 +2154,7 @@ static ga_win_10_0_t const 
WIN_10_0_SERVER_VERSION_MATRIX[4] = {
 {14393, "Microsoft Windows Server 2016","2016"},
 {17763, "Microsoft Windows Server 2019","2019"},
 {20344, "Microsoft Windows Server 2022","2022"},
+{26040, "MIcrosoft Windows Server 2025","2025"},
 {0, 0}
 };
 
-- 
2.35.1




[PATCH 1/1] qga/linux: Add new api 'guest-network-get-route'

2023-11-23 Thread Dehan Meng
v1 -> v2
- Replace snprintf() to g_strdup_printf() to avoid memory problems.
- Remove the parameter 'char ipAddress[16]' in function 'char 
*hexToIPAddress()'.
- Add a piece of logic to skip traversing the first line of the file

Dehan Meng (1):
  qga/linux: Add new api 'guest-network-get-route'

 qga/commands-posix.c | 78 ++
 qga/commands-win32.c |  6 
 qga/qapi-schema.json | 80 
 3 files changed, 164 insertions(+)

-- 
2.35.1




[PATCH v2 1/1] qga/linux: Add new api 'guest-network-get-route'

2023-11-23 Thread Dehan Meng
The Route information of the Linux VM needs to be used
by administrators and users when debugging network problems
and troubleshooting.

Signed-off-by: Dehan Meng 
---
 qga/commands-posix.c | 78 ++
 qga/commands-win32.c |  6 
 qga/qapi-schema.json | 80 
 3 files changed, 164 insertions(+)

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 6169bbf7a0..894cc43fce 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -2747,6 +2747,78 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 return head;
 }
 
+char *hexToIPAddress(unsigned int hexValue);
+
+char *hexToIPAddress(unsigned int hexValue)
+{
+unsigned int byte1 = (hexValue >> 24) & 0xFF;
+unsigned int byte2 = (hexValue >> 16) & 0xFF;
+unsigned int byte3 = (hexValue >> 8) & 0xFF;
+unsigned int byte4 = hexValue & 0xFF;
+
+return g_strdup_printf("%u.%u.%u.%u", byte4, byte3, byte2, byte1);
+}
+
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+GuestNetworkRouteList *head = NULL, **tail = &head;
+const char *routeFile = "/proc/net/route";
+FILE *fp;
+size_t n;
+char *line = NULL;
+int firstLine = 1;
+
+fp = fopen(routeFile, "r");
+if (fp == NULL) {
+error_setg_errno(errp, errno, "open(\"%s\")", routeFile);
+free(line);
+return NULL;
+}
+
+while (getline(&line, &n, fp) != -1) {
+if (firstLine) {
+firstLine = 0;
+continue;
+}
+GuestNetworkRoute *route = NULL;
+GuestNetworkRouteStat *networkroute;
+int i;
+char Iface[16];
+unsigned int Destination, Gateway, Mask, Flags;
+int RefCnt, Use, Metric, MTU, Window, IRTT;
+
+/* Parse the line and extract the values */
+i = (sscanf(line, "%s %X %X %x %d %d %d %X %d %d %d",
+Iface, &Destination, &Gateway, &Flags, &RefCnt,
+&Use, &Metric, &Mask, &MTU, &Window, &IRTT) == 11);
+if (i == EOF) {
+continue;
+}
+
+route = g_new0(GuestNetworkRoute, 1);
+route->type = GUEST_NETWORK_ROUTE_TYPE_LINUX;
+
+networkroute = &route->u.q_linux;
+networkroute->iface = g_strdup(Iface);
+networkroute->destination = hexToIPAddress(Destination);
+networkroute->gateway = hexToIPAddress(Gateway);
+networkroute->mask = hexToIPAddress(Mask);
+networkroute->metric = Metric;
+networkroute->flags = Flags;
+networkroute->refcnt = RefCnt;
+networkroute->use = Use;
+networkroute->mtu = MTU;
+networkroute->window = Window;
+networkroute->irtt = IRTT;
+
+QAPI_LIST_APPEND(tail, route);
+}
+
+free(line);
+fclose(fp);
+return head;
+}
+
 #else /* defined(__linux__) */
 
 void qmp_guest_suspend_disk(Error **errp)
@@ -3118,6 +3190,12 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 return NULL;
 }
 
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
+
 #endif /* CONFIG_FSFREEZE */
 
 #if !defined(CONFIG_FSTRIM)
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 697c65507c..e62c04800a 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -2522,3 +2522,9 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 error_setg(errp, QERR_UNSUPPORTED);
 return NULL;
 }
+
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 876e2a8ea8..eed9539bb7 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -1789,3 +1789,83 @@
 { 'command': 'guest-get-cpustats',
   'returns': ['GuestCpuStats']
 }
+
+##
+# @GuestNetworkRouteType:
+#
+# An enumeration of OS type
+#
+# Since: 8.2
+##
+{ 'enum': 'GuestNetworkRouteType',
+  'data': [ 'linux' ] }
+
+##
+# @GuestNetworkRouteStat:
+#
+# Route information, currently, only linux supported.
+#
+# @iface: The destination network or host's egress network interface in the 
routing table
+#
+# @destination: The IP address of the target network or host, The final 
destination of the packet
+#
+# @gateway: The IP address of the next hop router
+#
+# @mask: Subnet Mask
+#
+# @metric: Route metric
+#
+# @flags: Route flags (not for windows)
+#
+# @irtt: Initial round-trip delay (not for windows)
+#
+# @refcnt: The route's reference count (not for windows)
+#
+# @use: Route usage count (not for windows)
+#
+# @window: TCP window size, used for flow control (not for wi

[PATCH] qga/linux: Add new api 'guest-network-get-route'

2023-11-17 Thread Dehan Meng
The Route information of the Linux VM needs to be used
by administrators and users when debugging network problems
and troubleshooting.

Signed-off-by: Dehan Meng 
---
 qga/commands-posix.c | 82 
 qga/commands-win32.c |  6 
 qga/qapi-schema.json | 80 ++
 3 files changed, 168 insertions(+)

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 6169bbf7a0..83a3c46b3c 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -2747,6 +2747,82 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 return head;
 }
 
+char *hexToIPAddress(unsigned int hexValue, char ipAddress[16]);
+
+char *hexToIPAddress(unsigned int hexValue, char ipAddress[16])
+{
+unsigned int byte1 = (hexValue >> 24) & 0xFF;
+unsigned int byte2 = (hexValue >> 16) & 0xFF;
+unsigned int byte3 = (hexValue >> 8) & 0xFF;
+unsigned int byte4 = hexValue & 0xFF;
+
+snprintf(ipAddress, 16, "%u.%u.%u.%u", byte4, byte3, byte2, byte1);
+
+return ipAddress;
+}
+
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+GuestNetworkRouteList *head = NULL, **tail = &head;
+const char *routeFile = "/proc/net/route";
+FILE *fp;
+size_t n;
+char *line = NULL;
+
+fp = fopen(routeFile, "r");
+if (fp == NULL) {
+error_setg_errno(errp, errno, "open(\"%s\")", routeFile);
+return NULL;
+}
+
+while (getline(&line, &n, fp) != -1) {
+GuestNetworkRoute *route = NULL;
+GuestNetworkRouteStat *networkroute;
+int i;
+char Iface[16];
+unsigned int Destination, Gateway, Mask, Flags;
+int RefCnt, Use, Metric, MTU, Window, IRTT;
+
+/* Parse the line and extract the values */
+i = (sscanf(line, "%s %X %X %x %d %d %d %X %d %d %d",
+Iface, &Destination, &Gateway, &Flags, &RefCnt,
+&Use, &Metric, &Mask, &MTU, &Window, &IRTT) == 11);
+if (i == EOF) {
+continue;
+}
+
+route = g_new0(GuestNetworkRoute, 1);
+route->type = GUEST_NETWORK_ROUTE_TYPE_LINUX;
+
+/*
+ *Additional logic to convert hex values to
+ *decimal and IP address format
+ */
+char DestAddress[16];
+char GateAddress[16];
+char MaskAddress[16];
+
+networkroute = &route->u.q_linux;
+networkroute->iface = g_strdup(Iface);
+networkroute->destination = hexToIPAddress(Destination, DestAddress);
+networkroute->gateway = hexToIPAddress(Gateway, GateAddress);
+networkroute->mask = hexToIPAddress(Mask, MaskAddress);
+networkroute->metric = Metric;
+networkroute->flags = Flags;
+networkroute->refcnt = RefCnt;
+networkroute->use = Use;
+networkroute->mtu = MTU;
+networkroute->window = Window;
+networkroute->irtt = IRTT;
+
+QAPI_LIST_APPEND(tail, route);
+}
+
+free(line);
+fclose(fp);
+return head;
+}
+
 #else /* defined(__linux__) */
 
 void qmp_guest_suspend_disk(Error **errp)
@@ -3118,6 +3194,12 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 return NULL;
 }
 
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
+
 #endif /* CONFIG_FSFREEZE */
 
 #if !defined(CONFIG_FSTRIM)
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 697c65507c..e62c04800a 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -2522,3 +2522,9 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
 error_setg(errp, QERR_UNSUPPORTED);
 return NULL;
 }
+
+GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
+{
+error_setg(errp, QERR_UNSUPPORTED);
+return NULL;
+}
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 876e2a8ea8..eed9539bb7 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -1789,3 +1789,83 @@
 { 'command': 'guest-get-cpustats',
   'returns': ['GuestCpuStats']
 }
+
+##
+# @GuestNetworkRouteType:
+#
+# An enumeration of OS type
+#
+# Since: 8.2
+##
+{ 'enum': 'GuestNetworkRouteType',
+  'data': [ 'linux' ] }
+
+##
+# @GuestNetworkRouteStat:
+#
+# Route information, currently, only linux supported.
+#
+# @iface: The destination network or host's egress network interface in the 
routing table
+#
+# @destination: The IP address of the target network or host, The final 
destination of the packet
+#
+# @gateway: The IP address of the next hop router
+#
+# @mask: Subnet Mask
+#
+# @metric: Route metric
+#
+# @flags: Route flags (not for windows)
+#
+# @irtt: Initial round-trip delay (not fo