2 * QEMU Guest Agent POSIX-specific command implementations
4 * Copyright IBM Corp. 2011
7 * Michael Roth <mdroth@linux.vnet.ibm.com>
8 * Michal Privoznik <mprivozn@redhat.com>
10 * This work is licensed under the terms of the GNU GPL, version 2 or later.
11 * See the COPYING file in the top-level directory.
15 #include <sys/types.h>
16 #include <sys/ioctl.h>
17 #include "qga/guest-agent-core.h"
18 #include "qga-qmp-commands.h"
20 #include "qemu-queue.h"
21 #include "host-utils.h"
23 #if defined(__linux__)
27 #include <arpa/inet.h>
28 #include <sys/socket.h>
32 #if defined(__linux__) && defined(FIFREEZE)
33 #define CONFIG_FSFREEZE
37 #if defined(__linux__)
38 /* TODO: use this in place of all post-fork() fclose(std*) callers */
39 static void reopen_fd_to_null(int fd
)
43 nullfd
= open("/dev/null", O_RDWR
);
54 #endif /* defined(__linux__) */
56 void qmp_guest_shutdown(bool has_mode
, const char *mode
, Error
**err
)
59 const char *shutdown_flag
;
61 slog("guest-shutdown called, mode: %s", mode
);
62 if (!has_mode
|| strcmp(mode
, "powerdown") == 0) {
64 } else if (strcmp(mode
, "halt") == 0) {
66 } else if (strcmp(mode
, "reboot") == 0) {
69 error_set(err
, QERR_INVALID_PARAMETER_VALUE
, "mode",
70 "halt|powerdown|reboot");
76 /* child, start the shutdown */
82 ret
= execl("/sbin/shutdown", "shutdown", shutdown_flag
, "+0",
83 "hypervisor initiated shutdown", (char*)NULL
);
85 slog("guest-shutdown failed: %s", strerror(errno
));
89 error_set(err
, QERR_UNDEFINED_ERROR
);
93 typedef struct GuestFileHandle
{
96 QTAILQ_ENTRY(GuestFileHandle
) next
;
100 QTAILQ_HEAD(, GuestFileHandle
) filehandles
;
103 static void guest_file_handle_add(FILE *fh
)
105 GuestFileHandle
*gfh
;
107 gfh
= g_malloc0(sizeof(GuestFileHandle
));
108 gfh
->id
= fileno(fh
);
110 QTAILQ_INSERT_TAIL(&guest_file_state
.filehandles
, gfh
, next
);
113 static GuestFileHandle
*guest_file_handle_find(int64_t id
)
115 GuestFileHandle
*gfh
;
117 QTAILQ_FOREACH(gfh
, &guest_file_state
.filehandles
, next
)
127 int64_t qmp_guest_file_open(const char *path
, bool has_mode
, const char *mode
, Error
**err
)
136 slog("guest-file-open called, filepath: %s, mode: %s", path
, mode
);
137 fh
= fopen(path
, mode
);
139 error_set(err
, QERR_OPEN_FILE_FAILED
, path
);
143 /* set fd non-blocking to avoid common use cases (like reading from a
144 * named pipe) from hanging the agent
147 ret
= fcntl(fd
, F_GETFL
);
148 ret
= fcntl(fd
, F_SETFL
, ret
| O_NONBLOCK
);
150 error_set(err
, QERR_QGA_COMMAND_FAILED
, "fcntl() failed");
155 guest_file_handle_add(fh
);
156 slog("guest-file-open, handle: %d", fd
);
160 void qmp_guest_file_close(int64_t handle
, Error
**err
)
162 GuestFileHandle
*gfh
= guest_file_handle_find(handle
);
165 slog("guest-file-close called, handle: %ld", handle
);
167 error_set(err
, QERR_FD_NOT_FOUND
, "handle");
171 ret
= fclose(gfh
->fh
);
173 error_set(err
, QERR_QGA_COMMAND_FAILED
, "fclose() failed");
177 QTAILQ_REMOVE(&guest_file_state
.filehandles
, gfh
, next
);
181 struct GuestFileRead
*qmp_guest_file_read(int64_t handle
, bool has_count
,
182 int64_t count
, Error
**err
)
184 GuestFileHandle
*gfh
= guest_file_handle_find(handle
);
185 GuestFileRead
*read_data
= NULL
;
191 error_set(err
, QERR_FD_NOT_FOUND
, "handle");
196 count
= QGA_READ_COUNT_DEFAULT
;
197 } else if (count
< 0) {
198 error_set(err
, QERR_INVALID_PARAMETER
, "count");
203 buf
= g_malloc0(count
+1);
204 read_count
= fread(buf
, 1, count
, fh
);
206 slog("guest-file-read failed, handle: %ld", handle
);
207 error_set(err
, QERR_QGA_COMMAND_FAILED
, "fread() failed");
210 read_data
= g_malloc0(sizeof(GuestFileRead
));
211 read_data
->count
= read_count
;
212 read_data
->eof
= feof(fh
);
214 read_data
->buf_b64
= g_base64_encode(buf
, read_count
);
223 GuestFileWrite
*qmp_guest_file_write(int64_t handle
, const char *buf_b64
,
224 bool has_count
, int64_t count
, Error
**err
)
226 GuestFileWrite
*write_data
= NULL
;
230 GuestFileHandle
*gfh
= guest_file_handle_find(handle
);
234 error_set(err
, QERR_FD_NOT_FOUND
, "handle");
239 buf
= g_base64_decode(buf_b64
, &buf_len
);
243 } else if (count
< 0 || count
> buf_len
) {
245 error_set(err
, QERR_INVALID_PARAMETER
, "count");
249 write_count
= fwrite(buf
, 1, count
, fh
);
251 slog("guest-file-write failed, handle: %ld", handle
);
252 error_set(err
, QERR_QGA_COMMAND_FAILED
, "fwrite() error");
254 write_data
= g_malloc0(sizeof(GuestFileWrite
));
255 write_data
->count
= write_count
;
256 write_data
->eof
= feof(fh
);
264 struct GuestFileSeek
*qmp_guest_file_seek(int64_t handle
, int64_t offset
,
265 int64_t whence
, Error
**err
)
267 GuestFileHandle
*gfh
= guest_file_handle_find(handle
);
268 GuestFileSeek
*seek_data
= NULL
;
273 error_set(err
, QERR_FD_NOT_FOUND
, "handle");
278 ret
= fseek(fh
, offset
, whence
);
280 error_set(err
, QERR_QGA_COMMAND_FAILED
, strerror(errno
));
282 seek_data
= g_malloc0(sizeof(GuestFileRead
));
283 seek_data
->position
= ftell(fh
);
284 seek_data
->eof
= feof(fh
);
291 void qmp_guest_file_flush(int64_t handle
, Error
**err
)
293 GuestFileHandle
*gfh
= guest_file_handle_find(handle
);
298 error_set(err
, QERR_FD_NOT_FOUND
, "handle");
305 error_set(err
, QERR_QGA_COMMAND_FAILED
, strerror(errno
));
309 static void guest_file_init(void)
311 QTAILQ_INIT(&guest_file_state
.filehandles
);
314 /* linux-specific implementations. avoid this if at all possible. */
315 #if defined(__linux__)
317 #if defined(CONFIG_FSFREEZE)
319 static void disable_logging(void)
321 ga_disable_logging(ga_state
);
324 static void enable_logging(void)
326 ga_enable_logging(ga_state
);
329 typedef struct GuestFsfreezeMount
{
332 QTAILQ_ENTRY(GuestFsfreezeMount
) next
;
333 } GuestFsfreezeMount
;
336 GuestFsfreezeStatus status
;
337 QTAILQ_HEAD(, GuestFsfreezeMount
) mount_list
;
338 } guest_fsfreeze_state
;
341 * Walk the mount table and build a list of local file systems
343 static int guest_fsfreeze_build_mount_list(void)
346 GuestFsfreezeMount
*mount
, *temp
;
347 char const *mtab
= MOUNTED
;
350 QTAILQ_FOREACH_SAFE(mount
, &guest_fsfreeze_state
.mount_list
, next
, temp
) {
351 QTAILQ_REMOVE(&guest_fsfreeze_state
.mount_list
, mount
, next
);
352 g_free(mount
->dirname
);
353 g_free(mount
->devtype
);
357 fp
= setmntent(mtab
, "r");
359 g_warning("fsfreeze: unable to read mtab");
363 while ((ment
= getmntent(fp
))) {
365 * An entry which device name doesn't start with a '/' is
366 * either a dummy file system or a network file system.
367 * Add special handling for smbfs and cifs as is done by
370 if ((ment
->mnt_fsname
[0] != '/') ||
371 (strcmp(ment
->mnt_type
, "smbfs") == 0) ||
372 (strcmp(ment
->mnt_type
, "cifs") == 0)) {
376 mount
= g_malloc0(sizeof(GuestFsfreezeMount
));
377 mount
->dirname
= g_strdup(ment
->mnt_dir
);
378 mount
->devtype
= g_strdup(ment
->mnt_type
);
380 QTAILQ_INSERT_TAIL(&guest_fsfreeze_state
.mount_list
, mount
, next
);
389 * Return status of freeze/thaw
391 GuestFsfreezeStatus
qmp_guest_fsfreeze_status(Error
**err
)
393 return guest_fsfreeze_state
.status
;
397 * Walk list of mounted file systems in the guest, and freeze the ones which
398 * are real local file systems.
400 int64_t qmp_guest_fsfreeze_freeze(Error
**err
)
403 struct GuestFsfreezeMount
*mount
, *temp
;
407 slog("guest-fsfreeze called");
409 if (guest_fsfreeze_state
.status
== GUEST_FSFREEZE_STATUS_FROZEN
) {
413 ret
= guest_fsfreeze_build_mount_list();
418 /* cannot risk guest agent blocking itself on a write in this state */
421 QTAILQ_FOREACH_SAFE(mount
, &guest_fsfreeze_state
.mount_list
, next
, temp
) {
422 fd
= qemu_open(mount
->dirname
, O_RDONLY
);
424 sprintf(err_msg
, "failed to open %s, %s", mount
->dirname
, strerror(errno
));
425 error_set(err
, QERR_QGA_COMMAND_FAILED
, err_msg
);
429 /* we try to cull filesytems we know won't work in advance, but other
430 * filesytems may not implement fsfreeze for less obvious reasons.
431 * these will report EOPNOTSUPP, so we simply ignore them. when
432 * thawing, these filesystems will return an EINVAL instead, due to
433 * not being in a frozen state. Other filesystem-specific
434 * errors may result in EINVAL, however, so the user should check the
435 * number * of filesystems returned here against those returned by the
436 * thaw operation to determine whether everything completed
439 ret
= ioctl(fd
, FIFREEZE
);
440 if (ret
< 0 && errno
!= EOPNOTSUPP
) {
441 sprintf(err_msg
, "failed to freeze %s, %s", mount
->dirname
, strerror(errno
));
442 error_set(err
, QERR_QGA_COMMAND_FAILED
, err_msg
);
451 guest_fsfreeze_state
.status
= GUEST_FSFREEZE_STATUS_FROZEN
;
456 qmp_guest_fsfreeze_thaw(NULL
);
462 * Walk list of frozen file systems in the guest, and thaw them.
464 int64_t qmp_guest_fsfreeze_thaw(Error
**err
)
467 GuestFsfreezeMount
*mount
, *temp
;
469 bool has_error
= false;
471 QTAILQ_FOREACH_SAFE(mount
, &guest_fsfreeze_state
.mount_list
, next
, temp
) {
472 fd
= qemu_open(mount
->dirname
, O_RDONLY
);
477 ret
= ioctl(fd
, FITHAW
);
478 if (ret
< 0 && errno
!= EOPNOTSUPP
&& errno
!= EINVAL
) {
488 guest_fsfreeze_state
.status
= GUEST_FSFREEZE_STATUS_ERROR
;
490 guest_fsfreeze_state
.status
= GUEST_FSFREEZE_STATUS_THAWED
;
496 static void guest_fsfreeze_init(void)
498 guest_fsfreeze_state
.status
= GUEST_FSFREEZE_STATUS_THAWED
;
499 QTAILQ_INIT(&guest_fsfreeze_state
.mount_list
);
502 static void guest_fsfreeze_cleanup(void)
507 if (guest_fsfreeze_state
.status
== GUEST_FSFREEZE_STATUS_FROZEN
) {
508 ret
= qmp_guest_fsfreeze_thaw(&err
);
509 if (ret
< 0 || err
) {
510 slog("failed to clean up frozen filesystems");
514 #endif /* CONFIG_FSFREEZE */
516 #define LINUX_SYS_STATE_FILE "/sys/power/state"
517 #define SUSPEND_SUPPORTED 0
518 #define SUSPEND_NOT_SUPPORTED 1
521 * This function forks twice and the information about the mode support
522 * status is passed to the qemu-ga process via a pipe.
524 * This approach allows us to keep the way we reap terminated children
525 * in qemu-ga quite simple.
527 static void bios_supports_mode(const char *pmutils_bin
, const char *pmutils_arg
,
528 const char *sysfile_str
, Error
**err
)
533 int status
, pipefds
[2];
535 if (pipe(pipefds
) < 0) {
536 error_set(err
, QERR_UNDEFINED_ERROR
);
540 pmutils_path
= g_find_program_in_path(pmutils_bin
);
544 struct sigaction act
;
546 memset(&act
, 0, sizeof(act
));
547 act
.sa_handler
= SIG_DFL
;
548 sigaction(SIGCHLD
, &act
, NULL
);
552 reopen_fd_to_null(0);
553 reopen_fd_to_null(1);
554 reopen_fd_to_null(2);
559 char buf
[32]; /* hopefully big enough */
562 execle(pmutils_path
, pmutils_bin
, pmutils_arg
, NULL
, environ
);
566 * If we get here either pm-utils is not installed or execle() has
567 * failed. Let's try the manual method if the caller wants it.
571 _exit(SUSPEND_NOT_SUPPORTED
);
574 fd
= open(LINUX_SYS_STATE_FILE
, O_RDONLY
);
576 _exit(SUSPEND_NOT_SUPPORTED
);
579 ret
= read(fd
, buf
, sizeof(buf
)-1);
581 _exit(SUSPEND_NOT_SUPPORTED
);
585 if (strstr(buf
, sysfile_str
)) {
586 _exit(SUSPEND_SUPPORTED
);
589 _exit(SUSPEND_NOT_SUPPORTED
);
595 status
= SUSPEND_NOT_SUPPORTED
;
598 ret
= write(pipefds
[1], &status
, sizeof(status
));
599 if (ret
!= sizeof(status
)) {
607 g_free(pmutils_path
);
610 error_set(err
, QERR_UNDEFINED_ERROR
);
614 ret
= read(pipefds
[0], &status
, sizeof(status
));
615 if (ret
== sizeof(status
) && WIFEXITED(status
) &&
616 WEXITSTATUS(status
) == SUSPEND_SUPPORTED
) {
620 error_set(err
, QERR_UNSUPPORTED
);
626 static void guest_suspend(const char *pmutils_bin
, const char *sysfile_str
,
632 pmutils_path
= g_find_program_in_path(pmutils_bin
);
640 reopen_fd_to_null(0);
641 reopen_fd_to_null(1);
642 reopen_fd_to_null(2);
645 execle(pmutils_path
, pmutils_bin
, NULL
, environ
);
649 * If we get here either pm-utils is not installed or execle() has
650 * failed. Let's try the manual method if the caller wants it.
657 fd
= open(LINUX_SYS_STATE_FILE
, O_WRONLY
);
662 if (write(fd
, sysfile_str
, strlen(sysfile_str
)) < 0) {
669 g_free(pmutils_path
);
672 error_set(err
, QERR_UNDEFINED_ERROR
);
677 void qmp_guest_suspend_disk(Error
**err
)
679 bios_supports_mode("pm-is-supported", "--hibernate", "disk", err
);
680 if (error_is_set(err
)) {
684 guest_suspend("pm-hibernate", "disk", err
);
687 void qmp_guest_suspend_ram(Error
**err
)
689 bios_supports_mode("pm-is-supported", "--suspend", "mem", err
);
690 if (error_is_set(err
)) {
694 guest_suspend("pm-suspend", "mem", err
);
697 void qmp_guest_suspend_hybrid(Error
**err
)
699 bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL
, err
);
700 if (error_is_set(err
)) {
704 guest_suspend("pm-suspend-hybrid", NULL
, err
);
707 static GuestNetworkInterfaceList
*
708 guest_find_interface(GuestNetworkInterfaceList
*head
,
711 for (; head
; head
= head
->next
) {
712 if (strcmp(head
->value
->name
, name
) == 0) {
721 * Build information about guest interfaces
723 GuestNetworkInterfaceList
*qmp_guest_network_get_interfaces(Error
**errp
)
725 GuestNetworkInterfaceList
*head
= NULL
, *cur_item
= NULL
;
726 struct ifaddrs
*ifap
, *ifa
;
729 if (getifaddrs(&ifap
) < 0) {
730 snprintf(err_msg
, sizeof(err_msg
),
731 "getifaddrs failed: %s", strerror(errno
));
732 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
736 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
737 GuestNetworkInterfaceList
*info
;
738 GuestIpAddressList
**address_list
= NULL
, *address_item
= NULL
;
739 char addr4
[INET_ADDRSTRLEN
];
740 char addr6
[INET6_ADDRSTRLEN
];
743 unsigned char *mac_addr
;
746 g_debug("Processing %s interface", ifa
->ifa_name
);
748 info
= guest_find_interface(head
, ifa
->ifa_name
);
751 info
= g_malloc0(sizeof(*info
));
752 info
->value
= g_malloc0(sizeof(*info
->value
));
753 info
->value
->name
= g_strdup(ifa
->ifa_name
);
756 head
= cur_item
= info
;
758 cur_item
->next
= info
;
763 if (!info
->value
->has_hardware_address
&&
764 ifa
->ifa_flags
& SIOCGIFHWADDR
) {
765 /* we haven't obtained HW address yet */
766 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
768 snprintf(err_msg
, sizeof(err_msg
),
769 "failed to create socket: %s", strerror(errno
));
770 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
774 memset(&ifr
, 0, sizeof(ifr
));
775 strncpy(ifr
.ifr_name
, info
->value
->name
, IF_NAMESIZE
);
776 if (ioctl(sock
, SIOCGIFHWADDR
, &ifr
) == -1) {
777 snprintf(err_msg
, sizeof(err_msg
),
778 "failed to get MAC addres of %s: %s",
781 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
785 mac_addr
= (unsigned char *) &ifr
.ifr_hwaddr
.sa_data
;
787 if (asprintf(&info
->value
->hardware_address
,
788 "%02x:%02x:%02x:%02x:%02x:%02x",
789 (int) mac_addr
[0], (int) mac_addr
[1],
790 (int) mac_addr
[2], (int) mac_addr
[3],
791 (int) mac_addr
[4], (int) mac_addr
[5]) == -1) {
792 snprintf(err_msg
, sizeof(err_msg
),
793 "failed to format MAC: %s", strerror(errno
));
794 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
798 info
->value
->has_hardware_address
= true;
803 ifa
->ifa_addr
->sa_family
== AF_INET
) {
804 /* interface with IPv4 address */
805 address_item
= g_malloc0(sizeof(*address_item
));
806 address_item
->value
= g_malloc0(sizeof(*address_item
->value
));
807 p
= &((struct sockaddr_in
*)ifa
->ifa_addr
)->sin_addr
;
808 if (!inet_ntop(AF_INET
, p
, addr4
, sizeof(addr4
))) {
809 snprintf(err_msg
, sizeof(err_msg
),
810 "inet_ntop failed : %s", strerror(errno
));
811 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
815 address_item
->value
->ip_address
= g_strdup(addr4
);
816 address_item
->value
->ip_address_type
= GUEST_IP_ADDRESS_TYPE_IPV4
;
818 if (ifa
->ifa_netmask
) {
819 /* Count the number of set bits in netmask.
820 * This is safe as '1' and '0' cannot be shuffled in netmask. */
821 p
= &((struct sockaddr_in
*)ifa
->ifa_netmask
)->sin_addr
;
822 address_item
->value
->prefix
= ctpop32(((uint32_t *) p
)[0]);
824 } else if (ifa
->ifa_addr
&&
825 ifa
->ifa_addr
->sa_family
== AF_INET6
) {
826 /* interface with IPv6 address */
827 address_item
= g_malloc0(sizeof(*address_item
));
828 address_item
->value
= g_malloc0(sizeof(*address_item
->value
));
829 p
= &((struct sockaddr_in6
*)ifa
->ifa_addr
)->sin6_addr
;
830 if (!inet_ntop(AF_INET6
, p
, addr6
, sizeof(addr6
))) {
831 snprintf(err_msg
, sizeof(err_msg
),
832 "inet_ntop failed : %s", strerror(errno
));
833 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
837 address_item
->value
->ip_address
= g_strdup(addr6
);
838 address_item
->value
->ip_address_type
= GUEST_IP_ADDRESS_TYPE_IPV6
;
840 if (ifa
->ifa_netmask
) {
841 /* Count the number of set bits in netmask.
842 * This is safe as '1' and '0' cannot be shuffled in netmask. */
843 p
= &((struct sockaddr_in6
*)ifa
->ifa_netmask
)->sin6_addr
;
844 address_item
->value
->prefix
=
845 ctpop32(((uint32_t *) p
)[0]) +
846 ctpop32(((uint32_t *) p
)[1]) +
847 ctpop32(((uint32_t *) p
)[2]) +
848 ctpop32(((uint32_t *) p
)[3]);
856 address_list
= &info
->value
->ip_addresses
;
858 while (*address_list
&& (*address_list
)->next
) {
859 address_list
= &(*address_list
)->next
;
862 if (!*address_list
) {
863 *address_list
= address_item
;
865 (*address_list
)->next
= address_item
;
868 info
->value
->has_ip_addresses
= true;
878 qapi_free_GuestNetworkInterfaceList(head
);
882 #else /* defined(__linux__) */
884 GuestFsfreezeStatus
qmp_guest_fsfreeze_status(Error
**err
)
886 error_set(err
, QERR_UNSUPPORTED
);
891 int64_t qmp_guest_fsfreeze_freeze(Error
**err
)
893 error_set(err
, QERR_UNSUPPORTED
);
898 int64_t qmp_guest_fsfreeze_thaw(Error
**err
)
900 error_set(err
, QERR_UNSUPPORTED
);
905 void qmp_guest_suspend_disk(Error
**err
)
907 error_set(err
, QERR_UNSUPPORTED
);
910 void qmp_guest_suspend_ram(Error
**err
)
912 error_set(err
, QERR_UNSUPPORTED
);
915 void qmp_guest_suspend_hybrid(Error
**err
)
917 error_set(err
, QERR_UNSUPPORTED
);
920 GuestNetworkInterfaceList
*qmp_guest_network_get_interfaces(Error
**errp
)
922 error_set(errp
, QERR_UNSUPPORTED
);
928 /* register init/cleanup routines for stateful command groups */
929 void ga_command_state_init(GAState
*s
, GACommandState
*cs
)
931 #if defined(CONFIG_FSFREEZE)
932 ga_command_state_add(cs
, guest_fsfreeze_init
, guest_fsfreeze_cleanup
);
934 ga_command_state_add(cs
, guest_file_init
, NULL
);