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