1 /* 2 * QEMU Guest Agent POSIX-specific command implementations 3 * 4 * Copyright IBM Corp. 2011 5 * 6 * Authors: 7 * Michael Roth <mdroth@linux.vnet.ibm.com> 8 * Michal Privoznik <mprivozn@redhat.com> 9 * 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. 12 */ 13 14 #include <glib.h> 15 #include <sys/types.h> 16 #include <sys/ioctl.h> 17 #include <sys/wait.h> 18 #include "qga/guest-agent-core.h" 19 #include "qga-qmp-commands.h" 20 #include "qapi/qmp/qerror.h" 21 #include "qemu/queue.h" 22 #include "qemu/host-utils.h" 23 24 #ifndef CONFIG_HAS_ENVIRON 25 #ifdef __APPLE__ 26 #include <crt_externs.h> 27 #define environ (*_NSGetEnviron()) 28 #else 29 extern char **environ; 30 #endif 31 #endif 32 33 #if defined(__linux__) 34 #include <mntent.h> 35 #include <linux/fs.h> 36 #include <ifaddrs.h> 37 #include <arpa/inet.h> 38 #include <sys/socket.h> 39 #include <net/if.h> 40 41 #ifdef FIFREEZE 42 #define CONFIG_FSFREEZE 43 #endif 44 #ifdef FITRIM 45 #define CONFIG_FSTRIM 46 #endif 47 #endif 48 49 static void ga_wait_child(pid_t pid, int *status, Error **err) 50 { 51 pid_t rpid; 52 53 *status = 0; 54 55 do { 56 rpid = waitpid(pid, status, 0); 57 } while (rpid == -1 && errno == EINTR); 58 59 if (rpid == -1) { 60 error_setg_errno(err, errno, "failed to wait for child (pid: %d)", pid); 61 return; 62 } 63 64 g_assert(rpid == pid); 65 } 66 67 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err) 68 { 69 const char *shutdown_flag; 70 Error *local_err = NULL; 71 pid_t pid; 72 int status; 73 74 slog("guest-shutdown called, mode: %s", mode); 75 if (!has_mode || strcmp(mode, "powerdown") == 0) { 76 shutdown_flag = "-P"; 77 } else if (strcmp(mode, "halt") == 0) { 78 shutdown_flag = "-H"; 79 } else if (strcmp(mode, "reboot") == 0) { 80 shutdown_flag = "-r"; 81 } else { 82 error_setg(err, 83 "mode is invalid (valid values are: halt|powerdown|reboot"); 84 return; 85 } 86 87 pid = fork(); 88 if (pid == 0) { 89 /* child, start the shutdown */ 90 setsid(); 91 reopen_fd_to_null(0); 92 reopen_fd_to_null(1); 93 reopen_fd_to_null(2); 94 95 execle("/sbin/shutdown", "shutdown", shutdown_flag, "+0", 96 "hypervisor initiated shutdown", (char*)NULL, environ); 97 _exit(EXIT_FAILURE); 98 } else if (pid < 0) { 99 error_setg_errno(err, errno, "failed to create child process"); 100 return; 101 } 102 103 ga_wait_child(pid, &status, &local_err); 104 if (error_is_set(&local_err)) { 105 error_propagate(err, local_err); 106 return; 107 } 108 109 if (!WIFEXITED(status)) { 110 error_setg(err, "child process has terminated abnormally"); 111 return; 112 } 113 114 if (WEXITSTATUS(status)) { 115 error_setg(err, "child process has failed to shutdown"); 116 return; 117 } 118 119 /* succeded */ 120 } 121 122 typedef struct GuestFileHandle { 123 uint64_t id; 124 FILE *fh; 125 QTAILQ_ENTRY(GuestFileHandle) next; 126 } GuestFileHandle; 127 128 static struct { 129 QTAILQ_HEAD(, GuestFileHandle) filehandles; 130 } guest_file_state; 131 132 static void guest_file_handle_add(FILE *fh) 133 { 134 GuestFileHandle *gfh; 135 136 gfh = g_malloc0(sizeof(GuestFileHandle)); 137 gfh->id = fileno(fh); 138 gfh->fh = fh; 139 QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next); 140 } 141 142 static GuestFileHandle *guest_file_handle_find(int64_t id, Error **err) 143 { 144 GuestFileHandle *gfh; 145 146 QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next) 147 { 148 if (gfh->id == id) { 149 return gfh; 150 } 151 } 152 153 error_setg(err, "handle '%" PRId64 "' has not been found", id); 154 return NULL; 155 } 156 157 int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **err) 158 { 159 FILE *fh; 160 int fd; 161 int64_t ret = -1; 162 163 if (!has_mode) { 164 mode = "r"; 165 } 166 slog("guest-file-open called, filepath: %s, mode: %s", path, mode); 167 fh = fopen(path, mode); 168 if (!fh) { 169 error_setg_errno(err, errno, "failed to open file '%s' (mode: '%s')", 170 path, mode); 171 return -1; 172 } 173 174 /* set fd non-blocking to avoid common use cases (like reading from a 175 * named pipe) from hanging the agent 176 */ 177 fd = fileno(fh); 178 ret = fcntl(fd, F_GETFL); 179 ret = fcntl(fd, F_SETFL, ret | O_NONBLOCK); 180 if (ret == -1) { 181 error_setg_errno(err, errno, "failed to make file '%s' non-blocking", 182 path); 183 fclose(fh); 184 return -1; 185 } 186 187 guest_file_handle_add(fh); 188 slog("guest-file-open, handle: %d", fd); 189 return fd; 190 } 191 192 void qmp_guest_file_close(int64_t handle, Error **err) 193 { 194 GuestFileHandle *gfh = guest_file_handle_find(handle, err); 195 int ret; 196 197 slog("guest-file-close called, handle: %ld", handle); 198 if (!gfh) { 199 return; 200 } 201 202 ret = fclose(gfh->fh); 203 if (ret == EOF) { 204 error_setg_errno(err, errno, "failed to close handle"); 205 return; 206 } 207 208 QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next); 209 g_free(gfh); 210 } 211 212 struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count, 213 int64_t count, Error **err) 214 { 215 GuestFileHandle *gfh = guest_file_handle_find(handle, err); 216 GuestFileRead *read_data = NULL; 217 guchar *buf; 218 FILE *fh; 219 size_t read_count; 220 221 if (!gfh) { 222 return NULL; 223 } 224 225 if (!has_count) { 226 count = QGA_READ_COUNT_DEFAULT; 227 } else if (count < 0) { 228 error_setg(err, "value '%" PRId64 "' is invalid for argument count", 229 count); 230 return NULL; 231 } 232 233 fh = gfh->fh; 234 buf = g_malloc0(count+1); 235 read_count = fread(buf, 1, count, fh); 236 if (ferror(fh)) { 237 error_setg_errno(err, errno, "failed to read file"); 238 slog("guest-file-read failed, handle: %ld", handle); 239 } else { 240 buf[read_count] = 0; 241 read_data = g_malloc0(sizeof(GuestFileRead)); 242 read_data->count = read_count; 243 read_data->eof = feof(fh); 244 if (read_count) { 245 read_data->buf_b64 = g_base64_encode(buf, read_count); 246 } 247 } 248 g_free(buf); 249 clearerr(fh); 250 251 return read_data; 252 } 253 254 GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64, 255 bool has_count, int64_t count, Error **err) 256 { 257 GuestFileWrite *write_data = NULL; 258 guchar *buf; 259 gsize buf_len; 260 int write_count; 261 GuestFileHandle *gfh = guest_file_handle_find(handle, err); 262 FILE *fh; 263 264 if (!gfh) { 265 return NULL; 266 } 267 268 fh = gfh->fh; 269 buf = g_base64_decode(buf_b64, &buf_len); 270 271 if (!has_count) { 272 count = buf_len; 273 } else if (count < 0 || count > buf_len) { 274 error_setg(err, "value '%" PRId64 "' is invalid for argument count", 275 count); 276 g_free(buf); 277 return NULL; 278 } 279 280 write_count = fwrite(buf, 1, count, fh); 281 if (ferror(fh)) { 282 error_setg_errno(err, errno, "failed to write to file"); 283 slog("guest-file-write failed, handle: %ld", handle); 284 } else { 285 write_data = g_malloc0(sizeof(GuestFileWrite)); 286 write_data->count = write_count; 287 write_data->eof = feof(fh); 288 } 289 g_free(buf); 290 clearerr(fh); 291 292 return write_data; 293 } 294 295 struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset, 296 int64_t whence, Error **err) 297 { 298 GuestFileHandle *gfh = guest_file_handle_find(handle, err); 299 GuestFileSeek *seek_data = NULL; 300 FILE *fh; 301 int ret; 302 303 if (!gfh) { 304 return NULL; 305 } 306 307 fh = gfh->fh; 308 ret = fseek(fh, offset, whence); 309 if (ret == -1) { 310 error_setg_errno(err, errno, "failed to seek file"); 311 } else { 312 seek_data = g_malloc0(sizeof(GuestFileRead)); 313 seek_data->position = ftell(fh); 314 seek_data->eof = feof(fh); 315 } 316 clearerr(fh); 317 318 return seek_data; 319 } 320 321 void qmp_guest_file_flush(int64_t handle, Error **err) 322 { 323 GuestFileHandle *gfh = guest_file_handle_find(handle, err); 324 FILE *fh; 325 int ret; 326 327 if (!gfh) { 328 return; 329 } 330 331 fh = gfh->fh; 332 ret = fflush(fh); 333 if (ret == EOF) { 334 error_setg_errno(err, errno, "failed to flush file"); 335 } 336 } 337 338 static void guest_file_init(void) 339 { 340 QTAILQ_INIT(&guest_file_state.filehandles); 341 } 342 343 /* linux-specific implementations. avoid this if at all possible. */ 344 #if defined(__linux__) 345 346 #if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM) 347 typedef struct FsMount { 348 char *dirname; 349 char *devtype; 350 QTAILQ_ENTRY(FsMount) next; 351 } FsMount; 352 353 typedef QTAILQ_HEAD(, FsMount) FsMountList; 354 355 static void free_fs_mount_list(FsMountList *mounts) 356 { 357 FsMount *mount, *temp; 358 359 if (!mounts) { 360 return; 361 } 362 363 QTAILQ_FOREACH_SAFE(mount, mounts, next, temp) { 364 QTAILQ_REMOVE(mounts, mount, next); 365 g_free(mount->dirname); 366 g_free(mount->devtype); 367 g_free(mount); 368 } 369 } 370 371 /* 372 * Walk the mount table and build a list of local file systems 373 */ 374 static void build_fs_mount_list(FsMountList *mounts, Error **err) 375 { 376 struct mntent *ment; 377 FsMount *mount; 378 char const *mtab = "/proc/self/mounts"; 379 FILE *fp; 380 381 fp = setmntent(mtab, "r"); 382 if (!fp) { 383 error_setg(err, "failed to open mtab file: '%s'", mtab); 384 return; 385 } 386 387 while ((ment = getmntent(fp))) { 388 /* 389 * An entry which device name doesn't start with a '/' is 390 * either a dummy file system or a network file system. 391 * Add special handling for smbfs and cifs as is done by 392 * coreutils as well. 393 */ 394 if ((ment->mnt_fsname[0] != '/') || 395 (strcmp(ment->mnt_type, "smbfs") == 0) || 396 (strcmp(ment->mnt_type, "cifs") == 0)) { 397 continue; 398 } 399 400 mount = g_malloc0(sizeof(FsMount)); 401 mount->dirname = g_strdup(ment->mnt_dir); 402 mount->devtype = g_strdup(ment->mnt_type); 403 404 QTAILQ_INSERT_TAIL(mounts, mount, next); 405 } 406 407 endmntent(fp); 408 } 409 #endif 410 411 #if defined(CONFIG_FSFREEZE) 412 413 typedef enum { 414 FSFREEZE_HOOK_THAW = 0, 415 FSFREEZE_HOOK_FREEZE, 416 } FsfreezeHookArg; 417 418 const char *fsfreeze_hook_arg_string[] = { 419 "thaw", 420 "freeze", 421 }; 422 423 static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **err) 424 { 425 int status; 426 pid_t pid; 427 const char *hook; 428 const char *arg_str = fsfreeze_hook_arg_string[arg]; 429 Error *local_err = NULL; 430 431 hook = ga_fsfreeze_hook(ga_state); 432 if (!hook) { 433 return; 434 } 435 if (access(hook, X_OK) != 0) { 436 error_setg_errno(err, errno, "can't access fsfreeze hook '%s'", hook); 437 return; 438 } 439 440 slog("executing fsfreeze hook with arg '%s'", arg_str); 441 pid = fork(); 442 if (pid == 0) { 443 setsid(); 444 reopen_fd_to_null(0); 445 reopen_fd_to_null(1); 446 reopen_fd_to_null(2); 447 448 execle(hook, hook, arg_str, NULL, environ); 449 _exit(EXIT_FAILURE); 450 } else if (pid < 0) { 451 error_setg_errno(err, errno, "failed to create child process"); 452 return; 453 } 454 455 ga_wait_child(pid, &status, &local_err); 456 if (error_is_set(&local_err)) { 457 error_propagate(err, local_err); 458 return; 459 } 460 461 if (!WIFEXITED(status)) { 462 error_setg(err, "fsfreeze hook has terminated abnormally"); 463 return; 464 } 465 466 status = WEXITSTATUS(status); 467 if (status) { 468 error_setg(err, "fsfreeze hook has failed with status %d", status); 469 return; 470 } 471 } 472 473 /* 474 * Return status of freeze/thaw 475 */ 476 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err) 477 { 478 if (ga_is_frozen(ga_state)) { 479 return GUEST_FSFREEZE_STATUS_FROZEN; 480 } 481 482 return GUEST_FSFREEZE_STATUS_THAWED; 483 } 484 485 /* 486 * Walk list of mounted file systems in the guest, and freeze the ones which 487 * are real local file systems. 488 */ 489 int64_t qmp_guest_fsfreeze_freeze(Error **err) 490 { 491 int ret = 0, i = 0; 492 FsMountList mounts; 493 struct FsMount *mount; 494 Error *local_err = NULL; 495 int fd; 496 497 slog("guest-fsfreeze called"); 498 499 execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err); 500 if (error_is_set(&local_err)) { 501 error_propagate(err, local_err); 502 return -1; 503 } 504 505 QTAILQ_INIT(&mounts); 506 build_fs_mount_list(&mounts, &local_err); 507 if (error_is_set(&local_err)) { 508 error_propagate(err, local_err); 509 return -1; 510 } 511 512 /* cannot risk guest agent blocking itself on a write in this state */ 513 ga_set_frozen(ga_state); 514 515 QTAILQ_FOREACH(mount, &mounts, next) { 516 fd = qemu_open(mount->dirname, O_RDONLY); 517 if (fd == -1) { 518 error_setg_errno(err, errno, "failed to open %s", mount->dirname); 519 goto error; 520 } 521 522 /* we try to cull filesytems we know won't work in advance, but other 523 * filesytems may not implement fsfreeze for less obvious reasons. 524 * these will report EOPNOTSUPP. we simply ignore these when tallying 525 * the number of frozen filesystems. 526 * 527 * any other error means a failure to freeze a filesystem we 528 * expect to be freezable, so return an error in those cases 529 * and return system to thawed state. 530 */ 531 ret = ioctl(fd, FIFREEZE); 532 if (ret == -1) { 533 if (errno != EOPNOTSUPP) { 534 error_setg_errno(err, errno, "failed to freeze %s", 535 mount->dirname); 536 close(fd); 537 goto error; 538 } 539 } else { 540 i++; 541 } 542 close(fd); 543 } 544 545 free_fs_mount_list(&mounts); 546 return i; 547 548 error: 549 free_fs_mount_list(&mounts); 550 qmp_guest_fsfreeze_thaw(NULL); 551 return 0; 552 } 553 554 /* 555 * Walk list of frozen file systems in the guest, and thaw them. 556 */ 557 int64_t qmp_guest_fsfreeze_thaw(Error **err) 558 { 559 int ret; 560 FsMountList mounts; 561 FsMount *mount; 562 int fd, i = 0, logged; 563 Error *local_err = NULL; 564 565 QTAILQ_INIT(&mounts); 566 build_fs_mount_list(&mounts, &local_err); 567 if (error_is_set(&local_err)) { 568 error_propagate(err, local_err); 569 return 0; 570 } 571 572 QTAILQ_FOREACH(mount, &mounts, next) { 573 logged = false; 574 fd = qemu_open(mount->dirname, O_RDONLY); 575 if (fd == -1) { 576 continue; 577 } 578 /* we have no way of knowing whether a filesystem was actually unfrozen 579 * as a result of a successful call to FITHAW, only that if an error 580 * was returned the filesystem was *not* unfrozen by that particular 581 * call. 582 * 583 * since multiple preceding FIFREEZEs require multiple calls to FITHAW 584 * to unfreeze, continuing issuing FITHAW until an error is returned, 585 * in which case either the filesystem is in an unfreezable state, or, 586 * more likely, it was thawed previously (and remains so afterward). 587 * 588 * also, since the most recent successful call is the one that did 589 * the actual unfreeze, we can use this to provide an accurate count 590 * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which 591 * may * be useful for determining whether a filesystem was unfrozen 592 * during the freeze/thaw phase by a process other than qemu-ga. 593 */ 594 do { 595 ret = ioctl(fd, FITHAW); 596 if (ret == 0 && !logged) { 597 i++; 598 logged = true; 599 } 600 } while (ret == 0); 601 close(fd); 602 } 603 604 ga_unset_frozen(ga_state); 605 free_fs_mount_list(&mounts); 606 607 execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, err); 608 609 return i; 610 } 611 612 static void guest_fsfreeze_cleanup(void) 613 { 614 Error *err = NULL; 615 616 if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) { 617 qmp_guest_fsfreeze_thaw(&err); 618 if (err) { 619 slog("failed to clean up frozen filesystems: %s", 620 error_get_pretty(err)); 621 error_free(err); 622 } 623 } 624 } 625 #endif /* CONFIG_FSFREEZE */ 626 627 #if defined(CONFIG_FSTRIM) 628 /* 629 * Walk list of mounted file systems in the guest, and trim them. 630 */ 631 void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) 632 { 633 int ret = 0; 634 FsMountList mounts; 635 struct FsMount *mount; 636 int fd; 637 Error *local_err = NULL; 638 struct fstrim_range r = { 639 .start = 0, 640 .len = -1, 641 .minlen = has_minimum ? minimum : 0, 642 }; 643 644 slog("guest-fstrim called"); 645 646 QTAILQ_INIT(&mounts); 647 build_fs_mount_list(&mounts, &local_err); 648 if (error_is_set(&local_err)) { 649 error_propagate(err, local_err); 650 return; 651 } 652 653 QTAILQ_FOREACH(mount, &mounts, next) { 654 fd = qemu_open(mount->dirname, O_RDONLY); 655 if (fd == -1) { 656 error_setg_errno(err, errno, "failed to open %s", mount->dirname); 657 goto error; 658 } 659 660 /* We try to cull filesytems we know won't work in advance, but other 661 * filesytems may not implement fstrim for less obvious reasons. These 662 * will report EOPNOTSUPP; we simply ignore these errors. Any other 663 * error means an unexpected error, so return it in those cases. In 664 * some other cases ENOTTY will be reported (e.g. CD-ROMs). 665 */ 666 ret = ioctl(fd, FITRIM, &r); 667 if (ret == -1) { 668 if (errno != ENOTTY && errno != EOPNOTSUPP) { 669 error_setg_errno(err, errno, "failed to trim %s", 670 mount->dirname); 671 close(fd); 672 goto error; 673 } 674 } 675 close(fd); 676 } 677 678 error: 679 free_fs_mount_list(&mounts); 680 } 681 #endif /* CONFIG_FSTRIM */ 682 683 684 #define LINUX_SYS_STATE_FILE "/sys/power/state" 685 #define SUSPEND_SUPPORTED 0 686 #define SUSPEND_NOT_SUPPORTED 1 687 688 static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg, 689 const char *sysfile_str, Error **err) 690 { 691 Error *local_err = NULL; 692 char *pmutils_path; 693 pid_t pid; 694 int status; 695 696 pmutils_path = g_find_program_in_path(pmutils_bin); 697 698 pid = fork(); 699 if (!pid) { 700 char buf[32]; /* hopefully big enough */ 701 ssize_t ret; 702 int fd; 703 704 setsid(); 705 reopen_fd_to_null(0); 706 reopen_fd_to_null(1); 707 reopen_fd_to_null(2); 708 709 if (pmutils_path) { 710 execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ); 711 } 712 713 /* 714 * If we get here either pm-utils is not installed or execle() has 715 * failed. Let's try the manual method if the caller wants it. 716 */ 717 718 if (!sysfile_str) { 719 _exit(SUSPEND_NOT_SUPPORTED); 720 } 721 722 fd = open(LINUX_SYS_STATE_FILE, O_RDONLY); 723 if (fd < 0) { 724 _exit(SUSPEND_NOT_SUPPORTED); 725 } 726 727 ret = read(fd, buf, sizeof(buf)-1); 728 if (ret <= 0) { 729 _exit(SUSPEND_NOT_SUPPORTED); 730 } 731 buf[ret] = '\0'; 732 733 if (strstr(buf, sysfile_str)) { 734 _exit(SUSPEND_SUPPORTED); 735 } 736 737 _exit(SUSPEND_NOT_SUPPORTED); 738 } else if (pid < 0) { 739 error_setg_errno(err, errno, "failed to create child process"); 740 goto out; 741 } 742 743 ga_wait_child(pid, &status, &local_err); 744 if (error_is_set(&local_err)) { 745 error_propagate(err, local_err); 746 goto out; 747 } 748 749 if (!WIFEXITED(status)) { 750 error_setg(err, "child process has terminated abnormally"); 751 goto out; 752 } 753 754 switch (WEXITSTATUS(status)) { 755 case SUSPEND_SUPPORTED: 756 goto out; 757 case SUSPEND_NOT_SUPPORTED: 758 error_setg(err, 759 "the requested suspend mode is not supported by the guest"); 760 goto out; 761 default: 762 error_setg(err, 763 "the helper program '%s' returned an unexpected exit status" 764 " code (%d)", pmutils_path, WEXITSTATUS(status)); 765 goto out; 766 } 767 768 out: 769 g_free(pmutils_path); 770 } 771 772 static void guest_suspend(const char *pmutils_bin, const char *sysfile_str, 773 Error **err) 774 { 775 Error *local_err = NULL; 776 char *pmutils_path; 777 pid_t pid; 778 int status; 779 780 pmutils_path = g_find_program_in_path(pmutils_bin); 781 782 pid = fork(); 783 if (pid == 0) { 784 /* child */ 785 int fd; 786 787 setsid(); 788 reopen_fd_to_null(0); 789 reopen_fd_to_null(1); 790 reopen_fd_to_null(2); 791 792 if (pmutils_path) { 793 execle(pmutils_path, pmutils_bin, NULL, environ); 794 } 795 796 /* 797 * If we get here either pm-utils is not installed or execle() has 798 * failed. Let's try the manual method if the caller wants it. 799 */ 800 801 if (!sysfile_str) { 802 _exit(EXIT_FAILURE); 803 } 804 805 fd = open(LINUX_SYS_STATE_FILE, O_WRONLY); 806 if (fd < 0) { 807 _exit(EXIT_FAILURE); 808 } 809 810 if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) { 811 _exit(EXIT_FAILURE); 812 } 813 814 _exit(EXIT_SUCCESS); 815 } else if (pid < 0) { 816 error_setg_errno(err, errno, "failed to create child process"); 817 goto out; 818 } 819 820 ga_wait_child(pid, &status, &local_err); 821 if (error_is_set(&local_err)) { 822 error_propagate(err, local_err); 823 goto out; 824 } 825 826 if (!WIFEXITED(status)) { 827 error_setg(err, "child process has terminated abnormally"); 828 goto out; 829 } 830 831 if (WEXITSTATUS(status)) { 832 error_setg(err, "child process has failed to suspend"); 833 goto out; 834 } 835 836 out: 837 g_free(pmutils_path); 838 } 839 840 void qmp_guest_suspend_disk(Error **err) 841 { 842 bios_supports_mode("pm-is-supported", "--hibernate", "disk", err); 843 if (error_is_set(err)) { 844 return; 845 } 846 847 guest_suspend("pm-hibernate", "disk", err); 848 } 849 850 void qmp_guest_suspend_ram(Error **err) 851 { 852 bios_supports_mode("pm-is-supported", "--suspend", "mem", err); 853 if (error_is_set(err)) { 854 return; 855 } 856 857 guest_suspend("pm-suspend", "mem", err); 858 } 859 860 void qmp_guest_suspend_hybrid(Error **err) 861 { 862 bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL, err); 863 if (error_is_set(err)) { 864 return; 865 } 866 867 guest_suspend("pm-suspend-hybrid", NULL, err); 868 } 869 870 static GuestNetworkInterfaceList * 871 guest_find_interface(GuestNetworkInterfaceList *head, 872 const char *name) 873 { 874 for (; head; head = head->next) { 875 if (strcmp(head->value->name, name) == 0) { 876 break; 877 } 878 } 879 880 return head; 881 } 882 883 /* 884 * Build information about guest interfaces 885 */ 886 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 887 { 888 GuestNetworkInterfaceList *head = NULL, *cur_item = NULL; 889 struct ifaddrs *ifap, *ifa; 890 891 if (getifaddrs(&ifap) < 0) { 892 error_setg_errno(errp, errno, "getifaddrs failed"); 893 goto error; 894 } 895 896 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 897 GuestNetworkInterfaceList *info; 898 GuestIpAddressList **address_list = NULL, *address_item = NULL; 899 char addr4[INET_ADDRSTRLEN]; 900 char addr6[INET6_ADDRSTRLEN]; 901 int sock; 902 struct ifreq ifr; 903 unsigned char *mac_addr; 904 void *p; 905 906 g_debug("Processing %s interface", ifa->ifa_name); 907 908 info = guest_find_interface(head, ifa->ifa_name); 909 910 if (!info) { 911 info = g_malloc0(sizeof(*info)); 912 info->value = g_malloc0(sizeof(*info->value)); 913 info->value->name = g_strdup(ifa->ifa_name); 914 915 if (!cur_item) { 916 head = cur_item = info; 917 } else { 918 cur_item->next = info; 919 cur_item = info; 920 } 921 } 922 923 if (!info->value->has_hardware_address && 924 ifa->ifa_flags & SIOCGIFHWADDR) { 925 /* we haven't obtained HW address yet */ 926 sock = socket(PF_INET, SOCK_STREAM, 0); 927 if (sock == -1) { 928 error_setg_errno(errp, errno, "failed to create socket"); 929 goto error; 930 } 931 932 memset(&ifr, 0, sizeof(ifr)); 933 pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->value->name); 934 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) { 935 error_setg_errno(errp, errno, 936 "failed to get MAC address of %s", 937 ifa->ifa_name); 938 close(sock); 939 goto error; 940 } 941 942 close(sock); 943 mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data; 944 945 info->value->hardware_address = 946 g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x", 947 (int) mac_addr[0], (int) mac_addr[1], 948 (int) mac_addr[2], (int) mac_addr[3], 949 (int) mac_addr[4], (int) mac_addr[5]); 950 951 info->value->has_hardware_address = true; 952 } 953 954 if (ifa->ifa_addr && 955 ifa->ifa_addr->sa_family == AF_INET) { 956 /* interface with IPv4 address */ 957 p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; 958 if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) { 959 error_setg_errno(errp, errno, "inet_ntop failed"); 960 goto error; 961 } 962 963 address_item = g_malloc0(sizeof(*address_item)); 964 address_item->value = g_malloc0(sizeof(*address_item->value)); 965 address_item->value->ip_address = g_strdup(addr4); 966 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4; 967 968 if (ifa->ifa_netmask) { 969 /* Count the number of set bits in netmask. 970 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 971 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr; 972 address_item->value->prefix = ctpop32(((uint32_t *) p)[0]); 973 } 974 } else if (ifa->ifa_addr && 975 ifa->ifa_addr->sa_family == AF_INET6) { 976 /* interface with IPv6 address */ 977 p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; 978 if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) { 979 error_setg_errno(errp, errno, "inet_ntop failed"); 980 goto error; 981 } 982 983 address_item = g_malloc0(sizeof(*address_item)); 984 address_item->value = g_malloc0(sizeof(*address_item->value)); 985 address_item->value->ip_address = g_strdup(addr6); 986 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6; 987 988 if (ifa->ifa_netmask) { 989 /* Count the number of set bits in netmask. 990 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 991 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr; 992 address_item->value->prefix = 993 ctpop32(((uint32_t *) p)[0]) + 994 ctpop32(((uint32_t *) p)[1]) + 995 ctpop32(((uint32_t *) p)[2]) + 996 ctpop32(((uint32_t *) p)[3]); 997 } 998 } 999 1000 if (!address_item) { 1001 continue; 1002 } 1003 1004 address_list = &info->value->ip_addresses; 1005 1006 while (*address_list && (*address_list)->next) { 1007 address_list = &(*address_list)->next; 1008 } 1009 1010 if (!*address_list) { 1011 *address_list = address_item; 1012 } else { 1013 (*address_list)->next = address_item; 1014 } 1015 1016 info->value->has_ip_addresses = true; 1017 1018 1019 } 1020 1021 freeifaddrs(ifap); 1022 return head; 1023 1024 error: 1025 freeifaddrs(ifap); 1026 qapi_free_GuestNetworkInterfaceList(head); 1027 return NULL; 1028 } 1029 1030 #else /* defined(__linux__) */ 1031 1032 void qmp_guest_suspend_disk(Error **err) 1033 { 1034 error_set(err, QERR_UNSUPPORTED); 1035 } 1036 1037 void qmp_guest_suspend_ram(Error **err) 1038 { 1039 error_set(err, QERR_UNSUPPORTED); 1040 } 1041 1042 void qmp_guest_suspend_hybrid(Error **err) 1043 { 1044 error_set(err, QERR_UNSUPPORTED); 1045 } 1046 1047 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 1048 { 1049 error_set(errp, QERR_UNSUPPORTED); 1050 return NULL; 1051 } 1052 1053 #endif 1054 1055 #if !defined(CONFIG_FSFREEZE) 1056 1057 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err) 1058 { 1059 error_set(err, QERR_UNSUPPORTED); 1060 1061 return 0; 1062 } 1063 1064 int64_t qmp_guest_fsfreeze_freeze(Error **err) 1065 { 1066 error_set(err, QERR_UNSUPPORTED); 1067 1068 return 0; 1069 } 1070 1071 int64_t qmp_guest_fsfreeze_thaw(Error **err) 1072 { 1073 error_set(err, QERR_UNSUPPORTED); 1074 1075 return 0; 1076 } 1077 #endif /* CONFIG_FSFREEZE */ 1078 1079 #if !defined(CONFIG_FSTRIM) 1080 void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) 1081 { 1082 error_set(err, QERR_UNSUPPORTED); 1083 } 1084 #endif 1085 1086 /* register init/cleanup routines for stateful command groups */ 1087 void ga_command_state_init(GAState *s, GACommandState *cs) 1088 { 1089 #if defined(CONFIG_FSFREEZE) 1090 ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); 1091 #endif 1092 ga_command_state_add(cs, guest_file_init, NULL); 1093 } 1094