Re: [PATCH] qemu-guest-agent: Update the logfile path of qga-fsfreeze-hook.log
'/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
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
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'
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'
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'
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'
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'
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
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
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
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
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'
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
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
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
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
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
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'
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'
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
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'
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'
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'
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