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