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 static void disable_logging(void) 320 { 321 ga_disable_logging(ga_state); 322 } 323 324 static void enable_logging(void) 325 { 326 ga_enable_logging(ga_state); 327 } 328 329 typedef struct GuestFsfreezeMount { 330 char *dirname; 331 char *devtype; 332 QTAILQ_ENTRY(GuestFsfreezeMount) next; 333 } GuestFsfreezeMount; 334 335 struct { 336 GuestFsfreezeStatus status; 337 QTAILQ_HEAD(, GuestFsfreezeMount) mount_list; 338 } guest_fsfreeze_state; 339 340 /* 341 * Walk the mount table and build a list of local file systems 342 */ 343 static int guest_fsfreeze_build_mount_list(void) 344 { 345 struct mntent *ment; 346 GuestFsfreezeMount *mount, *temp; 347 char const *mtab = MOUNTED; 348 FILE *fp; 349 350 QTAILQ_FOREACH_SAFE(mount, &guest_fsfreeze_state.mount_list, next, temp) { 351 QTAILQ_REMOVE(&guest_fsfreeze_state.mount_list, mount, next); 352 g_free(mount->dirname); 353 g_free(mount->devtype); 354 g_free(mount); 355 } 356 357 fp = setmntent(mtab, "r"); 358 if (!fp) { 359 g_warning("fsfreeze: unable to read mtab"); 360 return -1; 361 } 362 363 while ((ment = getmntent(fp))) { 364 /* 365 * An entry which device name doesn't start with a '/' is 366 * either a dummy file system or a network file system. 367 * Add special handling for smbfs and cifs as is done by 368 * coreutils as well. 369 */ 370 if ((ment->mnt_fsname[0] != '/') || 371 (strcmp(ment->mnt_type, "smbfs") == 0) || 372 (strcmp(ment->mnt_type, "cifs") == 0)) { 373 continue; 374 } 375 376 mount = g_malloc0(sizeof(GuestFsfreezeMount)); 377 mount->dirname = g_strdup(ment->mnt_dir); 378 mount->devtype = g_strdup(ment->mnt_type); 379 380 QTAILQ_INSERT_TAIL(&guest_fsfreeze_state.mount_list, mount, next); 381 } 382 383 endmntent(fp); 384 385 return 0; 386 } 387 388 /* 389 * Return status of freeze/thaw 390 */ 391 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err) 392 { 393 return guest_fsfreeze_state.status; 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 struct GuestFsfreezeMount *mount, *temp; 404 int fd; 405 char err_msg[512]; 406 407 slog("guest-fsfreeze called"); 408 409 if (guest_fsfreeze_state.status == GUEST_FSFREEZE_STATUS_FROZEN) { 410 return 0; 411 } 412 413 ret = guest_fsfreeze_build_mount_list(); 414 if (ret < 0) { 415 return ret; 416 } 417 418 /* cannot risk guest agent blocking itself on a write in this state */ 419 disable_logging(); 420 421 QTAILQ_FOREACH_SAFE(mount, &guest_fsfreeze_state.mount_list, next, temp) { 422 fd = qemu_open(mount->dirname, O_RDONLY); 423 if (fd == -1) { 424 sprintf(err_msg, "failed to open %s, %s", mount->dirname, strerror(errno)); 425 error_set(err, QERR_QGA_COMMAND_FAILED, err_msg); 426 goto error; 427 } 428 429 /* we try to cull filesytems we know won't work in advance, but other 430 * filesytems may not implement fsfreeze for less obvious reasons. 431 * these will report EOPNOTSUPP, so we simply ignore them. when 432 * thawing, these filesystems will return an EINVAL instead, due to 433 * not being in a frozen state. Other filesystem-specific 434 * errors may result in EINVAL, however, so the user should check the 435 * number * of filesystems returned here against those returned by the 436 * thaw operation to determine whether everything completed 437 * successfully 438 */ 439 ret = ioctl(fd, FIFREEZE); 440 if (ret < 0 && errno != EOPNOTSUPP) { 441 sprintf(err_msg, "failed to freeze %s, %s", mount->dirname, strerror(errno)); 442 error_set(err, QERR_QGA_COMMAND_FAILED, err_msg); 443 close(fd); 444 goto error; 445 } 446 close(fd); 447 448 i++; 449 } 450 451 guest_fsfreeze_state.status = GUEST_FSFREEZE_STATUS_FROZEN; 452 return i; 453 454 error: 455 if (i > 0) { 456 qmp_guest_fsfreeze_thaw(NULL); 457 } 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 GuestFsfreezeMount *mount, *temp; 468 int fd, i = 0; 469 bool has_error = false; 470 471 QTAILQ_FOREACH_SAFE(mount, &guest_fsfreeze_state.mount_list, next, temp) { 472 fd = qemu_open(mount->dirname, O_RDONLY); 473 if (fd == -1) { 474 has_error = true; 475 continue; 476 } 477 ret = ioctl(fd, FITHAW); 478 if (ret < 0 && errno != EOPNOTSUPP && errno != EINVAL) { 479 has_error = true; 480 close(fd); 481 continue; 482 } 483 close(fd); 484 i++; 485 } 486 487 if (has_error) { 488 guest_fsfreeze_state.status = GUEST_FSFREEZE_STATUS_ERROR; 489 } else { 490 guest_fsfreeze_state.status = GUEST_FSFREEZE_STATUS_THAWED; 491 } 492 enable_logging(); 493 return i; 494 } 495 496 static void guest_fsfreeze_init(void) 497 { 498 guest_fsfreeze_state.status = GUEST_FSFREEZE_STATUS_THAWED; 499 QTAILQ_INIT(&guest_fsfreeze_state.mount_list); 500 } 501 502 static void guest_fsfreeze_cleanup(void) 503 { 504 int64_t ret; 505 Error *err = NULL; 506 507 if (guest_fsfreeze_state.status == GUEST_FSFREEZE_STATUS_FROZEN) { 508 ret = qmp_guest_fsfreeze_thaw(&err); 509 if (ret < 0 || err) { 510 slog("failed to clean up frozen filesystems"); 511 } 512 } 513 } 514 #endif /* CONFIG_FSFREEZE */ 515 516 #define LINUX_SYS_STATE_FILE "/sys/power/state" 517 #define SUSPEND_SUPPORTED 0 518 #define SUSPEND_NOT_SUPPORTED 1 519 520 /** 521 * This function forks twice and the information about the mode support 522 * status is passed to the qemu-ga process via a pipe. 523 * 524 * This approach allows us to keep the way we reap terminated children 525 * in qemu-ga quite simple. 526 */ 527 static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg, 528 const char *sysfile_str, Error **err) 529 { 530 pid_t pid; 531 ssize_t ret; 532 char *pmutils_path; 533 int status, pipefds[2]; 534 535 if (pipe(pipefds) < 0) { 536 error_set(err, QERR_UNDEFINED_ERROR); 537 return; 538 } 539 540 pmutils_path = g_find_program_in_path(pmutils_bin); 541 542 pid = fork(); 543 if (!pid) { 544 struct sigaction act; 545 546 memset(&act, 0, sizeof(act)); 547 act.sa_handler = SIG_DFL; 548 sigaction(SIGCHLD, &act, NULL); 549 550 setsid(); 551 close(pipefds[0]); 552 reopen_fd_to_null(0); 553 reopen_fd_to_null(1); 554 reopen_fd_to_null(2); 555 556 pid = fork(); 557 if (!pid) { 558 int fd; 559 char buf[32]; /* hopefully big enough */ 560 561 if (pmutils_path) { 562 execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ); 563 } 564 565 /* 566 * If we get here either pm-utils is not installed or execle() has 567 * failed. Let's try the manual method if the caller wants it. 568 */ 569 570 if (!sysfile_str) { 571 _exit(SUSPEND_NOT_SUPPORTED); 572 } 573 574 fd = open(LINUX_SYS_STATE_FILE, O_RDONLY); 575 if (fd < 0) { 576 _exit(SUSPEND_NOT_SUPPORTED); 577 } 578 579 ret = read(fd, buf, sizeof(buf)-1); 580 if (ret <= 0) { 581 _exit(SUSPEND_NOT_SUPPORTED); 582 } 583 buf[ret] = '\0'; 584 585 if (strstr(buf, sysfile_str)) { 586 _exit(SUSPEND_SUPPORTED); 587 } 588 589 _exit(SUSPEND_NOT_SUPPORTED); 590 } 591 592 if (pid > 0) { 593 wait(&status); 594 } else { 595 status = SUSPEND_NOT_SUPPORTED; 596 } 597 598 ret = write(pipefds[1], &status, sizeof(status)); 599 if (ret != sizeof(status)) { 600 _exit(EXIT_FAILURE); 601 } 602 603 _exit(EXIT_SUCCESS); 604 } 605 606 close(pipefds[1]); 607 g_free(pmutils_path); 608 609 if (pid < 0) { 610 error_set(err, QERR_UNDEFINED_ERROR); 611 goto out; 612 } 613 614 ret = read(pipefds[0], &status, sizeof(status)); 615 if (ret == sizeof(status) && WIFEXITED(status) && 616 WEXITSTATUS(status) == SUSPEND_SUPPORTED) { 617 goto out; 618 } 619 620 error_set(err, QERR_UNSUPPORTED); 621 622 out: 623 close(pipefds[0]); 624 } 625 626 static void guest_suspend(const char *pmutils_bin, const char *sysfile_str, 627 Error **err) 628 { 629 pid_t pid; 630 char *pmutils_path; 631 632 pmutils_path = g_find_program_in_path(pmutils_bin); 633 634 pid = fork(); 635 if (pid == 0) { 636 /* child */ 637 int fd; 638 639 setsid(); 640 reopen_fd_to_null(0); 641 reopen_fd_to_null(1); 642 reopen_fd_to_null(2); 643 644 if (pmutils_path) { 645 execle(pmutils_path, pmutils_bin, NULL, environ); 646 } 647 648 /* 649 * If we get here either pm-utils is not installed or execle() has 650 * failed. Let's try the manual method if the caller wants it. 651 */ 652 653 if (!sysfile_str) { 654 _exit(EXIT_FAILURE); 655 } 656 657 fd = open(LINUX_SYS_STATE_FILE, O_WRONLY); 658 if (fd < 0) { 659 _exit(EXIT_FAILURE); 660 } 661 662 if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) { 663 _exit(EXIT_FAILURE); 664 } 665 666 _exit(EXIT_SUCCESS); 667 } 668 669 g_free(pmutils_path); 670 671 if (pid < 0) { 672 error_set(err, QERR_UNDEFINED_ERROR); 673 return; 674 } 675 } 676 677 void qmp_guest_suspend_disk(Error **err) 678 { 679 bios_supports_mode("pm-is-supported", "--hibernate", "disk", err); 680 if (error_is_set(err)) { 681 return; 682 } 683 684 guest_suspend("pm-hibernate", "disk", err); 685 } 686 687 void qmp_guest_suspend_ram(Error **err) 688 { 689 bios_supports_mode("pm-is-supported", "--suspend", "mem", err); 690 if (error_is_set(err)) { 691 return; 692 } 693 694 guest_suspend("pm-suspend", "mem", err); 695 } 696 697 void qmp_guest_suspend_hybrid(Error **err) 698 { 699 bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL, err); 700 if (error_is_set(err)) { 701 return; 702 } 703 704 guest_suspend("pm-suspend-hybrid", NULL, err); 705 } 706 707 static GuestNetworkInterfaceList * 708 guest_find_interface(GuestNetworkInterfaceList *head, 709 const char *name) 710 { 711 for (; head; head = head->next) { 712 if (strcmp(head->value->name, name) == 0) { 713 break; 714 } 715 } 716 717 return head; 718 } 719 720 /* 721 * Build information about guest interfaces 722 */ 723 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 724 { 725 GuestNetworkInterfaceList *head = NULL, *cur_item = NULL; 726 struct ifaddrs *ifap, *ifa; 727 char err_msg[512]; 728 729 if (getifaddrs(&ifap) < 0) { 730 snprintf(err_msg, sizeof(err_msg), 731 "getifaddrs failed: %s", strerror(errno)); 732 error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); 733 goto error; 734 } 735 736 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 737 GuestNetworkInterfaceList *info; 738 GuestIpAddressList **address_list = NULL, *address_item = NULL; 739 char addr4[INET_ADDRSTRLEN]; 740 char addr6[INET6_ADDRSTRLEN]; 741 int sock; 742 struct ifreq ifr; 743 unsigned char *mac_addr; 744 void *p; 745 746 g_debug("Processing %s interface", ifa->ifa_name); 747 748 info = guest_find_interface(head, ifa->ifa_name); 749 750 if (!info) { 751 info = g_malloc0(sizeof(*info)); 752 info->value = g_malloc0(sizeof(*info->value)); 753 info->value->name = g_strdup(ifa->ifa_name); 754 755 if (!cur_item) { 756 head = cur_item = info; 757 } else { 758 cur_item->next = info; 759 cur_item = info; 760 } 761 } 762 763 if (!info->value->has_hardware_address && 764 ifa->ifa_flags & SIOCGIFHWADDR) { 765 /* we haven't obtained HW address yet */ 766 sock = socket(PF_INET, SOCK_STREAM, 0); 767 if (sock == -1) { 768 snprintf(err_msg, sizeof(err_msg), 769 "failed to create socket: %s", strerror(errno)); 770 error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); 771 goto error; 772 } 773 774 memset(&ifr, 0, sizeof(ifr)); 775 strncpy(ifr.ifr_name, info->value->name, IF_NAMESIZE); 776 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) { 777 snprintf(err_msg, sizeof(err_msg), 778 "failed to get MAC addres of %s: %s", 779 ifa->ifa_name, 780 strerror(errno)); 781 error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); 782 goto error; 783 } 784 785 mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data; 786 787 if (asprintf(&info->value->hardware_address, 788 "%02x:%02x:%02x:%02x:%02x:%02x", 789 (int) mac_addr[0], (int) mac_addr[1], 790 (int) mac_addr[2], (int) mac_addr[3], 791 (int) mac_addr[4], (int) mac_addr[5]) == -1) { 792 snprintf(err_msg, sizeof(err_msg), 793 "failed to format MAC: %s", strerror(errno)); 794 error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); 795 goto error; 796 } 797 798 info->value->has_hardware_address = true; 799 close(sock); 800 } 801 802 if (ifa->ifa_addr && 803 ifa->ifa_addr->sa_family == AF_INET) { 804 /* interface with IPv4 address */ 805 address_item = g_malloc0(sizeof(*address_item)); 806 address_item->value = g_malloc0(sizeof(*address_item->value)); 807 p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; 808 if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) { 809 snprintf(err_msg, sizeof(err_msg), 810 "inet_ntop failed : %s", strerror(errno)); 811 error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); 812 goto error; 813 } 814 815 address_item->value->ip_address = g_strdup(addr4); 816 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4; 817 818 if (ifa->ifa_netmask) { 819 /* Count the number of set bits in netmask. 820 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 821 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr; 822 address_item->value->prefix = ctpop32(((uint32_t *) p)[0]); 823 } 824 } else if (ifa->ifa_addr && 825 ifa->ifa_addr->sa_family == AF_INET6) { 826 /* interface with IPv6 address */ 827 address_item = g_malloc0(sizeof(*address_item)); 828 address_item->value = g_malloc0(sizeof(*address_item->value)); 829 p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; 830 if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) { 831 snprintf(err_msg, sizeof(err_msg), 832 "inet_ntop failed : %s", strerror(errno)); 833 error_set(errp, QERR_QGA_COMMAND_FAILED, err_msg); 834 goto error; 835 } 836 837 address_item->value->ip_address = g_strdup(addr6); 838 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6; 839 840 if (ifa->ifa_netmask) { 841 /* Count the number of set bits in netmask. 842 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 843 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr; 844 address_item->value->prefix = 845 ctpop32(((uint32_t *) p)[0]) + 846 ctpop32(((uint32_t *) p)[1]) + 847 ctpop32(((uint32_t *) p)[2]) + 848 ctpop32(((uint32_t *) p)[3]); 849 } 850 } 851 852 if (!address_item) { 853 continue; 854 } 855 856 address_list = &info->value->ip_addresses; 857 858 while (*address_list && (*address_list)->next) { 859 address_list = &(*address_list)->next; 860 } 861 862 if (!*address_list) { 863 *address_list = address_item; 864 } else { 865 (*address_list)->next = address_item; 866 } 867 868 info->value->has_ip_addresses = true; 869 870 871 } 872 873 freeifaddrs(ifap); 874 return head; 875 876 error: 877 freeifaddrs(ifap); 878 qapi_free_GuestNetworkInterfaceList(head); 879 return NULL; 880 } 881 882 #else /* defined(__linux__) */ 883 884 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err) 885 { 886 error_set(err, QERR_UNSUPPORTED); 887 888 return 0; 889 } 890 891 int64_t qmp_guest_fsfreeze_freeze(Error **err) 892 { 893 error_set(err, QERR_UNSUPPORTED); 894 895 return 0; 896 } 897 898 int64_t qmp_guest_fsfreeze_thaw(Error **err) 899 { 900 error_set(err, QERR_UNSUPPORTED); 901 902 return 0; 903 } 904 905 void qmp_guest_suspend_disk(Error **err) 906 { 907 error_set(err, QERR_UNSUPPORTED); 908 } 909 910 void qmp_guest_suspend_ram(Error **err) 911 { 912 error_set(err, QERR_UNSUPPORTED); 913 } 914 915 void qmp_guest_suspend_hybrid(Error **err) 916 { 917 error_set(err, QERR_UNSUPPORTED); 918 } 919 920 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 921 { 922 error_set(errp, QERR_UNSUPPORTED); 923 return NULL; 924 } 925 926 #endif 927 928 /* register init/cleanup routines for stateful command groups */ 929 void ga_command_state_init(GAState *s, GACommandState *cs) 930 { 931 #if defined(CONFIG_FSFREEZE) 932 ga_command_state_add(cs, guest_fsfreeze_init, guest_fsfreeze_cleanup); 933 #endif 934 ga_command_state_add(cs, guest_file_init, NULL); 935 } 936