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.
16 #if defined(__linux__)
20 #if defined(__linux__) && defined(FIFREEZE)
21 #define CONFIG_FSFREEZE
25 #include <sys/types.h>
26 #include <sys/ioctl.h>
28 #include <arpa/inet.h>
29 #include <sys/socket.h>
32 #include "qga/guest-agent-core.h"
33 #include "qga-qmp-commands.h"
35 #include "qemu-queue.h"
36 #include "host-utils.h"
38 static GAState
*ga_state
;
40 static void reopen_fd_to_null(int fd
)
44 nullfd
= open("/dev/null", O_RDWR
);
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 #if defined(CONFIG_FSFREEZE)
315 static void disable_logging(void)
317 ga_disable_logging(ga_state
);
320 static void enable_logging(void)
322 ga_enable_logging(ga_state
);
325 typedef struct GuestFsfreezeMount
{
328 QTAILQ_ENTRY(GuestFsfreezeMount
) next
;
329 } GuestFsfreezeMount
;
332 GuestFsfreezeStatus status
;
333 QTAILQ_HEAD(, GuestFsfreezeMount
) mount_list
;
334 } guest_fsfreeze_state
;
337 * Walk the mount table and build a list of local file systems
339 static int guest_fsfreeze_build_mount_list(void)
342 GuestFsfreezeMount
*mount
, *temp
;
343 char const *mtab
= MOUNTED
;
346 QTAILQ_FOREACH_SAFE(mount
, &guest_fsfreeze_state
.mount_list
, next
, temp
) {
347 QTAILQ_REMOVE(&guest_fsfreeze_state
.mount_list
, mount
, next
);
348 g_free(mount
->dirname
);
349 g_free(mount
->devtype
);
353 fp
= setmntent(mtab
, "r");
355 g_warning("fsfreeze: unable to read mtab");
359 while ((ment
= getmntent(fp
))) {
361 * An entry which device name doesn't start with a '/' is
362 * either a dummy file system or a network file system.
363 * Add special handling for smbfs and cifs as is done by
366 if ((ment
->mnt_fsname
[0] != '/') ||
367 (strcmp(ment
->mnt_type
, "smbfs") == 0) ||
368 (strcmp(ment
->mnt_type
, "cifs") == 0)) {
372 mount
= g_malloc0(sizeof(GuestFsfreezeMount
));
373 mount
->dirname
= g_strdup(ment
->mnt_dir
);
374 mount
->devtype
= g_strdup(ment
->mnt_type
);
376 QTAILQ_INSERT_TAIL(&guest_fsfreeze_state
.mount_list
, mount
, next
);
385 * Return status of freeze/thaw
387 GuestFsfreezeStatus
qmp_guest_fsfreeze_status(Error
**err
)
389 return guest_fsfreeze_state
.status
;
393 * Walk list of mounted file systems in the guest, and freeze the ones which
394 * are real local file systems.
396 int64_t qmp_guest_fsfreeze_freeze(Error
**err
)
399 struct GuestFsfreezeMount
*mount
, *temp
;
403 slog("guest-fsfreeze called");
405 if (guest_fsfreeze_state
.status
== GUEST_FSFREEZE_STATUS_FROZEN
) {
409 ret
= guest_fsfreeze_build_mount_list();
414 /* cannot risk guest agent blocking itself on a write in this state */
417 QTAILQ_FOREACH_SAFE(mount
, &guest_fsfreeze_state
.mount_list
, next
, temp
) {
418 fd
= qemu_open(mount
->dirname
, O_RDONLY
);
420 sprintf(err_msg
, "failed to open %s, %s", mount
->dirname
, strerror(errno
));
421 error_set(err
, QERR_QGA_COMMAND_FAILED
, err_msg
);
425 /* we try to cull filesytems we know won't work in advance, but other
426 * filesytems may not implement fsfreeze for less obvious reasons.
427 * these will report EOPNOTSUPP, so we simply ignore them. when
428 * thawing, these filesystems will return an EINVAL instead, due to
429 * not being in a frozen state. Other filesystem-specific
430 * errors may result in EINVAL, however, so the user should check the
431 * number * of filesystems returned here against those returned by the
432 * thaw operation to determine whether everything completed
435 ret
= ioctl(fd
, FIFREEZE
);
436 if (ret
< 0 && errno
!= EOPNOTSUPP
) {
437 sprintf(err_msg
, "failed to freeze %s, %s", mount
->dirname
, strerror(errno
));
438 error_set(err
, QERR_QGA_COMMAND_FAILED
, err_msg
);
447 guest_fsfreeze_state
.status
= GUEST_FSFREEZE_STATUS_FROZEN
;
452 qmp_guest_fsfreeze_thaw(NULL
);
458 * Walk list of frozen file systems in the guest, and thaw them.
460 int64_t qmp_guest_fsfreeze_thaw(Error
**err
)
463 GuestFsfreezeMount
*mount
, *temp
;
465 bool has_error
= false;
467 QTAILQ_FOREACH_SAFE(mount
, &guest_fsfreeze_state
.mount_list
, next
, temp
) {
468 fd
= qemu_open(mount
->dirname
, O_RDONLY
);
473 ret
= ioctl(fd
, FITHAW
);
474 if (ret
< 0 && errno
!= EOPNOTSUPP
&& errno
!= EINVAL
) {
484 guest_fsfreeze_state
.status
= GUEST_FSFREEZE_STATUS_ERROR
;
486 guest_fsfreeze_state
.status
= GUEST_FSFREEZE_STATUS_THAWED
;
492 static void guest_fsfreeze_init(void)
494 guest_fsfreeze_state
.status
= GUEST_FSFREEZE_STATUS_THAWED
;
495 QTAILQ_INIT(&guest_fsfreeze_state
.mount_list
);
498 static void guest_fsfreeze_cleanup(void)
503 if (guest_fsfreeze_state
.status
== GUEST_FSFREEZE_STATUS_FROZEN
) {
504 ret
= qmp_guest_fsfreeze_thaw(&err
);
505 if (ret
< 0 || err
) {
506 slog("failed to clean up frozen filesystems");
512 * Return status of freeze/thaw
514 GuestFsfreezeStatus
qmp_guest_fsfreeze_status(Error
**err
)
516 error_set(err
, QERR_UNSUPPORTED
);
522 * Walk list of mounted file systems in the guest, and freeze the ones which
523 * are real local file systems.
525 int64_t qmp_guest_fsfreeze_freeze(Error
**err
)
527 error_set(err
, QERR_UNSUPPORTED
);
533 * Walk list of frozen file systems in the guest, and thaw them.
535 int64_t qmp_guest_fsfreeze_thaw(Error
**err
)
537 error_set(err
, QERR_UNSUPPORTED
);
543 #define LINUX_SYS_STATE_FILE "/sys/power/state"
544 #define SUSPEND_SUPPORTED 0
545 #define SUSPEND_NOT_SUPPORTED 1
548 * This function forks twice and the information about the mode support
549 * status is passed to the qemu-ga process via a pipe.
551 * This approach allows us to keep the way we reap terminated children
552 * in qemu-ga quite simple.
554 static void bios_supports_mode(const char *pmutils_bin
, const char *pmutils_arg
,
555 const char *sysfile_str
, Error
**err
)
560 int status
, pipefds
[2];
562 if (pipe(pipefds
) < 0) {
563 error_set(err
, QERR_UNDEFINED_ERROR
);
567 pmutils_path
= g_find_program_in_path(pmutils_bin
);
571 struct sigaction act
;
573 memset(&act
, 0, sizeof(act
));
574 act
.sa_handler
= SIG_DFL
;
575 sigaction(SIGCHLD
, &act
, NULL
);
579 reopen_fd_to_null(0);
580 reopen_fd_to_null(1);
581 reopen_fd_to_null(2);
586 char buf
[32]; /* hopefully big enough */
589 execle(pmutils_path
, pmutils_bin
, pmutils_arg
, NULL
, environ
);
593 * If we get here either pm-utils is not installed or execle() has
594 * failed. Let's try the manual method if the caller wants it.
598 _exit(SUSPEND_NOT_SUPPORTED
);
601 fd
= open(LINUX_SYS_STATE_FILE
, O_RDONLY
);
603 _exit(SUSPEND_NOT_SUPPORTED
);
606 ret
= read(fd
, buf
, sizeof(buf
)-1);
608 _exit(SUSPEND_NOT_SUPPORTED
);
612 if (strstr(buf
, sysfile_str
)) {
613 _exit(SUSPEND_SUPPORTED
);
616 _exit(SUSPEND_NOT_SUPPORTED
);
622 status
= SUSPEND_NOT_SUPPORTED
;
625 ret
= write(pipefds
[1], &status
, sizeof(status
));
626 if (ret
!= sizeof(status
)) {
634 g_free(pmutils_path
);
637 error_set(err
, QERR_UNDEFINED_ERROR
);
641 ret
= read(pipefds
[0], &status
, sizeof(status
));
642 if (ret
== sizeof(status
) && WIFEXITED(status
) &&
643 WEXITSTATUS(status
) == SUSPEND_SUPPORTED
) {
647 error_set(err
, QERR_UNSUPPORTED
);
653 static void guest_suspend(const char *pmutils_bin
, const char *sysfile_str
,
659 pmutils_path
= g_find_program_in_path(pmutils_bin
);
667 reopen_fd_to_null(0);
668 reopen_fd_to_null(1);
669 reopen_fd_to_null(2);
672 execle(pmutils_path
, pmutils_bin
, NULL
, environ
);
676 * If we get here either pm-utils is not installed or execle() has
677 * failed. Let's try the manual method if the caller wants it.
684 fd
= open(LINUX_SYS_STATE_FILE
, O_WRONLY
);
689 if (write(fd
, sysfile_str
, strlen(sysfile_str
)) < 0) {
696 g_free(pmutils_path
);
699 error_set(err
, QERR_UNDEFINED_ERROR
);
704 void qmp_guest_suspend_disk(Error
**err
)
706 bios_supports_mode("pm-is-supported", "--hibernate", "disk", err
);
707 if (error_is_set(err
)) {
711 guest_suspend("pm-hibernate", "disk", err
);
714 void qmp_guest_suspend_ram(Error
**err
)
716 bios_supports_mode("pm-is-supported", "--suspend", "mem", err
);
717 if (error_is_set(err
)) {
721 guest_suspend("pm-suspend", "mem", err
);
724 void qmp_guest_suspend_hybrid(Error
**err
)
726 bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL
, err
);
727 if (error_is_set(err
)) {
731 guest_suspend("pm-suspend-hybrid", NULL
, err
);
734 static GuestNetworkInterfaceList
*
735 guest_find_interface(GuestNetworkInterfaceList
*head
,
738 for (; head
; head
= head
->next
) {
739 if (strcmp(head
->value
->name
, name
) == 0) {
748 * Build information about guest interfaces
750 GuestNetworkInterfaceList
*qmp_guest_network_get_interfaces(Error
**errp
)
752 GuestNetworkInterfaceList
*head
= NULL
, *cur_item
= NULL
;
753 struct ifaddrs
*ifap
, *ifa
;
756 if (getifaddrs(&ifap
) < 0) {
757 snprintf(err_msg
, sizeof(err_msg
),
758 "getifaddrs failed: %s", strerror(errno
));
759 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
763 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
764 GuestNetworkInterfaceList
*info
;
765 GuestIpAddressList
**address_list
= NULL
, *address_item
= NULL
;
766 char addr4
[INET_ADDRSTRLEN
];
767 char addr6
[INET6_ADDRSTRLEN
];
770 unsigned char *mac_addr
;
773 g_debug("Processing %s interface", ifa
->ifa_name
);
775 info
= guest_find_interface(head
, ifa
->ifa_name
);
778 info
= g_malloc0(sizeof(*info
));
779 info
->value
= g_malloc0(sizeof(*info
->value
));
780 info
->value
->name
= g_strdup(ifa
->ifa_name
);
783 head
= cur_item
= info
;
785 cur_item
->next
= info
;
790 if (!info
->value
->has_hardware_address
&&
791 ifa
->ifa_flags
& SIOCGIFHWADDR
) {
792 /* we haven't obtained HW address yet */
793 sock
= socket(PF_INET
, SOCK_STREAM
, 0);
795 snprintf(err_msg
, sizeof(err_msg
),
796 "failed to create socket: %s", strerror(errno
));
797 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
801 memset(&ifr
, 0, sizeof(ifr
));
802 strncpy(ifr
.ifr_name
, info
->value
->name
, IF_NAMESIZE
);
803 if (ioctl(sock
, SIOCGIFHWADDR
, &ifr
) == -1) {
804 snprintf(err_msg
, sizeof(err_msg
),
805 "failed to get MAC addres of %s: %s",
808 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
812 mac_addr
= (unsigned char *) &ifr
.ifr_hwaddr
.sa_data
;
814 if (asprintf(&info
->value
->hardware_address
,
815 "%02x:%02x:%02x:%02x:%02x:%02x",
816 (int) mac_addr
[0], (int) mac_addr
[1],
817 (int) mac_addr
[2], (int) mac_addr
[3],
818 (int) mac_addr
[4], (int) mac_addr
[5]) == -1) {
819 snprintf(err_msg
, sizeof(err_msg
),
820 "failed to format MAC: %s", strerror(errno
));
821 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
825 info
->value
->has_hardware_address
= true;
830 ifa
->ifa_addr
->sa_family
== AF_INET
) {
831 /* interface with IPv4 address */
832 address_item
= g_malloc0(sizeof(*address_item
));
833 address_item
->value
= g_malloc0(sizeof(*address_item
->value
));
834 p
= &((struct sockaddr_in
*)ifa
->ifa_addr
)->sin_addr
;
835 if (!inet_ntop(AF_INET
, p
, addr4
, sizeof(addr4
))) {
836 snprintf(err_msg
, sizeof(err_msg
),
837 "inet_ntop failed : %s", strerror(errno
));
838 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
842 address_item
->value
->ip_address
= g_strdup(addr4
);
843 address_item
->value
->ip_address_type
= GUEST_IP_ADDRESS_TYPE_IPV4
;
845 if (ifa
->ifa_netmask
) {
846 /* Count the number of set bits in netmask.
847 * This is safe as '1' and '0' cannot be shuffled in netmask. */
848 p
= &((struct sockaddr_in
*)ifa
->ifa_netmask
)->sin_addr
;
849 address_item
->value
->prefix
= ctpop32(((uint32_t *) p
)[0]);
851 } else if (ifa
->ifa_addr
&&
852 ifa
->ifa_addr
->sa_family
== AF_INET6
) {
853 /* interface with IPv6 address */
854 address_item
= g_malloc0(sizeof(*address_item
));
855 address_item
->value
= g_malloc0(sizeof(*address_item
->value
));
856 p
= &((struct sockaddr_in6
*)ifa
->ifa_addr
)->sin6_addr
;
857 if (!inet_ntop(AF_INET6
, p
, addr6
, sizeof(addr6
))) {
858 snprintf(err_msg
, sizeof(err_msg
),
859 "inet_ntop failed : %s", strerror(errno
));
860 error_set(errp
, QERR_QGA_COMMAND_FAILED
, err_msg
);
864 address_item
->value
->ip_address
= g_strdup(addr6
);
865 address_item
->value
->ip_address_type
= GUEST_IP_ADDRESS_TYPE_IPV6
;
867 if (ifa
->ifa_netmask
) {
868 /* Count the number of set bits in netmask.
869 * This is safe as '1' and '0' cannot be shuffled in netmask. */
870 p
= &((struct sockaddr_in6
*)ifa
->ifa_netmask
)->sin6_addr
;
871 address_item
->value
->prefix
=
872 ctpop32(((uint32_t *) p
)[0]) +
873 ctpop32(((uint32_t *) p
)[1]) +
874 ctpop32(((uint32_t *) p
)[2]) +
875 ctpop32(((uint32_t *) p
)[3]);
883 address_list
= &info
->value
->ip_addresses
;
885 while (*address_list
&& (*address_list
)->next
) {
886 address_list
= &(*address_list
)->next
;
889 if (!*address_list
) {
890 *address_list
= address_item
;
892 (*address_list
)->next
= address_item
;
895 info
->value
->has_ip_addresses
= true;
905 qapi_free_GuestNetworkInterfaceList(head
);
909 /* register init/cleanup routines for stateful command groups */
910 void ga_command_state_init(GAState
*s
, GACommandState
*cs
)
913 #if defined(CONFIG_FSFREEZE)
914 ga_command_state_add(cs
, guest_fsfreeze_init
, guest_fsfreeze_cleanup
);
916 ga_command_state_add(cs
, guest_file_init
, NULL
);