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 int64_t ret; 615 Error *err = NULL; 616 617 if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) { 618 ret = qmp_guest_fsfreeze_thaw(&err); 619 if (ret < 0 || err) { 620 slog("failed to clean up frozen filesystems"); 621 } 622 } 623 } 624 #endif /* CONFIG_FSFREEZE */ 625 626 #if defined(CONFIG_FSTRIM) 627 /* 628 * Walk list of mounted file systems in the guest, and trim them. 629 */ 630 void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) 631 { 632 int ret = 0; 633 FsMountList mounts; 634 struct FsMount *mount; 635 int fd; 636 Error *local_err = NULL; 637 struct fstrim_range r = { 638 .start = 0, 639 .len = -1, 640 .minlen = has_minimum ? minimum : 0, 641 }; 642 643 slog("guest-fstrim called"); 644 645 QTAILQ_INIT(&mounts); 646 build_fs_mount_list(&mounts, &local_err); 647 if (error_is_set(&local_err)) { 648 error_propagate(err, local_err); 649 return; 650 } 651 652 QTAILQ_FOREACH(mount, &mounts, next) { 653 fd = qemu_open(mount->dirname, O_RDONLY); 654 if (fd == -1) { 655 error_setg_errno(err, errno, "failed to open %s", mount->dirname); 656 goto error; 657 } 658 659 /* We try to cull filesytems we know won't work in advance, but other 660 * filesytems may not implement fstrim for less obvious reasons. These 661 * will report EOPNOTSUPP; we simply ignore these errors. Any other 662 * error means an unexpected error, so return it in those cases. In 663 * some other cases ENOTTY will be reported (e.g. CD-ROMs). 664 */ 665 ret = ioctl(fd, FITRIM, &r); 666 if (ret == -1) { 667 if (errno != ENOTTY && errno != EOPNOTSUPP) { 668 error_setg_errno(err, errno, "failed to trim %s", 669 mount->dirname); 670 close(fd); 671 goto error; 672 } 673 } 674 close(fd); 675 } 676 677 error: 678 free_fs_mount_list(&mounts); 679 } 680 #endif /* CONFIG_FSTRIM */ 681 682 683 #define LINUX_SYS_STATE_FILE "/sys/power/state" 684 #define SUSPEND_SUPPORTED 0 685 #define SUSPEND_NOT_SUPPORTED 1 686 687 static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg, 688 const char *sysfile_str, Error **err) 689 { 690 Error *local_err = NULL; 691 char *pmutils_path; 692 pid_t pid; 693 int status; 694 695 pmutils_path = g_find_program_in_path(pmutils_bin); 696 697 pid = fork(); 698 if (!pid) { 699 char buf[32]; /* hopefully big enough */ 700 ssize_t ret; 701 int fd; 702 703 setsid(); 704 reopen_fd_to_null(0); 705 reopen_fd_to_null(1); 706 reopen_fd_to_null(2); 707 708 if (pmutils_path) { 709 execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ); 710 } 711 712 /* 713 * If we get here either pm-utils is not installed or execle() has 714 * failed. Let's try the manual method if the caller wants it. 715 */ 716 717 if (!sysfile_str) { 718 _exit(SUSPEND_NOT_SUPPORTED); 719 } 720 721 fd = open(LINUX_SYS_STATE_FILE, O_RDONLY); 722 if (fd < 0) { 723 _exit(SUSPEND_NOT_SUPPORTED); 724 } 725 726 ret = read(fd, buf, sizeof(buf)-1); 727 if (ret <= 0) { 728 _exit(SUSPEND_NOT_SUPPORTED); 729 } 730 buf[ret] = '\0'; 731 732 if (strstr(buf, sysfile_str)) { 733 _exit(SUSPEND_SUPPORTED); 734 } 735 736 _exit(SUSPEND_NOT_SUPPORTED); 737 } else if (pid < 0) { 738 error_setg_errno(err, errno, "failed to create child process"); 739 goto out; 740 } 741 742 ga_wait_child(pid, &status, &local_err); 743 if (error_is_set(&local_err)) { 744 error_propagate(err, local_err); 745 goto out; 746 } 747 748 if (!WIFEXITED(status)) { 749 error_setg(err, "child process has terminated abnormally"); 750 goto out; 751 } 752 753 switch (WEXITSTATUS(status)) { 754 case SUSPEND_SUPPORTED: 755 goto out; 756 case SUSPEND_NOT_SUPPORTED: 757 error_setg(err, 758 "the requested suspend mode is not supported by the guest"); 759 goto out; 760 default: 761 error_setg(err, 762 "the helper program '%s' returned an unexpected exit status" 763 " code (%d)", pmutils_path, WEXITSTATUS(status)); 764 goto out; 765 } 766 767 out: 768 g_free(pmutils_path); 769 } 770 771 static void guest_suspend(const char *pmutils_bin, const char *sysfile_str, 772 Error **err) 773 { 774 Error *local_err = NULL; 775 char *pmutils_path; 776 pid_t pid; 777 int status; 778 779 pmutils_path = g_find_program_in_path(pmutils_bin); 780 781 pid = fork(); 782 if (pid == 0) { 783 /* child */ 784 int fd; 785 786 setsid(); 787 reopen_fd_to_null(0); 788 reopen_fd_to_null(1); 789 reopen_fd_to_null(2); 790 791 if (pmutils_path) { 792 execle(pmutils_path, pmutils_bin, NULL, environ); 793 } 794 795 /* 796 * If we get here either pm-utils is not installed or execle() has 797 * failed. Let's try the manual method if the caller wants it. 798 */ 799 800 if (!sysfile_str) { 801 _exit(EXIT_FAILURE); 802 } 803 804 fd = open(LINUX_SYS_STATE_FILE, O_WRONLY); 805 if (fd < 0) { 806 _exit(EXIT_FAILURE); 807 } 808 809 if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) { 810 _exit(EXIT_FAILURE); 811 } 812 813 _exit(EXIT_SUCCESS); 814 } else if (pid < 0) { 815 error_setg_errno(err, errno, "failed to create child process"); 816 goto out; 817 } 818 819 ga_wait_child(pid, &status, &local_err); 820 if (error_is_set(&local_err)) { 821 error_propagate(err, local_err); 822 goto out; 823 } 824 825 if (!WIFEXITED(status)) { 826 error_setg(err, "child process has terminated abnormally"); 827 goto out; 828 } 829 830 if (WEXITSTATUS(status)) { 831 error_setg(err, "child process has failed to suspend"); 832 goto out; 833 } 834 835 out: 836 g_free(pmutils_path); 837 } 838 839 void qmp_guest_suspend_disk(Error **err) 840 { 841 bios_supports_mode("pm-is-supported", "--hibernate", "disk", err); 842 if (error_is_set(err)) { 843 return; 844 } 845 846 guest_suspend("pm-hibernate", "disk", err); 847 } 848 849 void qmp_guest_suspend_ram(Error **err) 850 { 851 bios_supports_mode("pm-is-supported", "--suspend", "mem", err); 852 if (error_is_set(err)) { 853 return; 854 } 855 856 guest_suspend("pm-suspend", "mem", err); 857 } 858 859 void qmp_guest_suspend_hybrid(Error **err) 860 { 861 bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL, err); 862 if (error_is_set(err)) { 863 return; 864 } 865 866 guest_suspend("pm-suspend-hybrid", NULL, err); 867 } 868 869 static GuestNetworkInterfaceList * 870 guest_find_interface(GuestNetworkInterfaceList *head, 871 const char *name) 872 { 873 for (; head; head = head->next) { 874 if (strcmp(head->value->name, name) == 0) { 875 break; 876 } 877 } 878 879 return head; 880 } 881 882 /* 883 * Build information about guest interfaces 884 */ 885 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 886 { 887 GuestNetworkInterfaceList *head = NULL, *cur_item = NULL; 888 struct ifaddrs *ifap, *ifa; 889 890 if (getifaddrs(&ifap) < 0) { 891 error_setg_errno(errp, errno, "getifaddrs failed"); 892 goto error; 893 } 894 895 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 896 GuestNetworkInterfaceList *info; 897 GuestIpAddressList **address_list = NULL, *address_item = NULL; 898 char addr4[INET_ADDRSTRLEN]; 899 char addr6[INET6_ADDRSTRLEN]; 900 int sock; 901 struct ifreq ifr; 902 unsigned char *mac_addr; 903 void *p; 904 905 g_debug("Processing %s interface", ifa->ifa_name); 906 907 info = guest_find_interface(head, ifa->ifa_name); 908 909 if (!info) { 910 info = g_malloc0(sizeof(*info)); 911 info->value = g_malloc0(sizeof(*info->value)); 912 info->value->name = g_strdup(ifa->ifa_name); 913 914 if (!cur_item) { 915 head = cur_item = info; 916 } else { 917 cur_item->next = info; 918 cur_item = info; 919 } 920 } 921 922 if (!info->value->has_hardware_address && 923 ifa->ifa_flags & SIOCGIFHWADDR) { 924 /* we haven't obtained HW address yet */ 925 sock = socket(PF_INET, SOCK_STREAM, 0); 926 if (sock == -1) { 927 error_setg_errno(errp, errno, "failed to create socket"); 928 goto error; 929 } 930 931 memset(&ifr, 0, sizeof(ifr)); 932 pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->value->name); 933 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) { 934 error_setg_errno(errp, errno, 935 "failed to get MAC address of %s", 936 ifa->ifa_name); 937 goto error; 938 } 939 940 mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data; 941 942 info->value->hardware_address = 943 g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x", 944 (int) mac_addr[0], (int) mac_addr[1], 945 (int) mac_addr[2], (int) mac_addr[3], 946 (int) mac_addr[4], (int) mac_addr[5]); 947 948 info->value->has_hardware_address = true; 949 close(sock); 950 } 951 952 if (ifa->ifa_addr && 953 ifa->ifa_addr->sa_family == AF_INET) { 954 /* interface with IPv4 address */ 955 address_item = g_malloc0(sizeof(*address_item)); 956 address_item->value = g_malloc0(sizeof(*address_item->value)); 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->value->ip_address = g_strdup(addr4); 964 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4; 965 966 if (ifa->ifa_netmask) { 967 /* Count the number of set bits in netmask. 968 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 969 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr; 970 address_item->value->prefix = ctpop32(((uint32_t *) p)[0]); 971 } 972 } else if (ifa->ifa_addr && 973 ifa->ifa_addr->sa_family == AF_INET6) { 974 /* interface with IPv6 address */ 975 address_item = g_malloc0(sizeof(*address_item)); 976 address_item->value = g_malloc0(sizeof(*address_item->value)); 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->value->ip_address = g_strdup(addr6); 984 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6; 985 986 if (ifa->ifa_netmask) { 987 /* Count the number of set bits in netmask. 988 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 989 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr; 990 address_item->value->prefix = 991 ctpop32(((uint32_t *) p)[0]) + 992 ctpop32(((uint32_t *) p)[1]) + 993 ctpop32(((uint32_t *) p)[2]) + 994 ctpop32(((uint32_t *) p)[3]); 995 } 996 } 997 998 if (!address_item) { 999 continue; 1000 } 1001 1002 address_list = &info->value->ip_addresses; 1003 1004 while (*address_list && (*address_list)->next) { 1005 address_list = &(*address_list)->next; 1006 } 1007 1008 if (!*address_list) { 1009 *address_list = address_item; 1010 } else { 1011 (*address_list)->next = address_item; 1012 } 1013 1014 info->value->has_ip_addresses = true; 1015 1016 1017 } 1018 1019 freeifaddrs(ifap); 1020 return head; 1021 1022 error: 1023 freeifaddrs(ifap); 1024 qapi_free_GuestNetworkInterfaceList(head); 1025 return NULL; 1026 } 1027 1028 #else /* defined(__linux__) */ 1029 1030 void qmp_guest_suspend_disk(Error **err) 1031 { 1032 error_set(err, QERR_UNSUPPORTED); 1033 } 1034 1035 void qmp_guest_suspend_ram(Error **err) 1036 { 1037 error_set(err, QERR_UNSUPPORTED); 1038 } 1039 1040 void qmp_guest_suspend_hybrid(Error **err) 1041 { 1042 error_set(err, QERR_UNSUPPORTED); 1043 } 1044 1045 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 1046 { 1047 error_set(errp, QERR_UNSUPPORTED); 1048 return NULL; 1049 } 1050 1051 #endif 1052 1053 #if !defined(CONFIG_FSFREEZE) 1054 1055 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err) 1056 { 1057 error_set(err, QERR_UNSUPPORTED); 1058 1059 return 0; 1060 } 1061 1062 int64_t qmp_guest_fsfreeze_freeze(Error **err) 1063 { 1064 error_set(err, QERR_UNSUPPORTED); 1065 1066 return 0; 1067 } 1068 1069 int64_t qmp_guest_fsfreeze_thaw(Error **err) 1070 { 1071 error_set(err, QERR_UNSUPPORTED); 1072 1073 return 0; 1074 } 1075 #endif /* CONFIG_FSFREEZE */ 1076 1077 #if !defined(CONFIG_FSTRIM) 1078 void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) 1079 { 1080 error_set(err, QERR_UNSUPPORTED); 1081 } 1082 #endif 1083 1084 /* register init/cleanup routines for stateful command groups */ 1085 void ga_command_state_init(GAState *s, GACommandState *cs) 1086 { 1087 #if defined(CONFIG_FSFREEZE) 1088 ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); 1089 #endif 1090 ga_command_state_add(cs, guest_file_init, NULL); 1091 } 1092