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