target-xtensa: implement ATOMCTL SR
[qemu/agraf.git] / qga / commands-posix.c
blob726930a909371e1daf3f57458f62e43b5a793def
1 /*
2 * QEMU Guest Agent POSIX-specific command implementations
4 * Copyright IBM Corp. 2011
6 * Authors:
7 * Michael Roth <mdroth@linux.vnet.ibm.com>
8 * Michal Privoznik <mprivozn@redhat.com>
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.
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"
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
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>
41 #ifdef FIFREEZE
42 #define CONFIG_FSFREEZE
43 #endif
44 #ifdef FITRIM
45 #define CONFIG_FSTRIM
46 #endif
47 #endif
49 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
51 const char *shutdown_flag;
52 pid_t rpid, pid;
53 int status;
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;
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);
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;
83 do {
84 rpid = waitpid(pid, &status, 0);
85 } while (rpid == -1 && errno == EINTR);
86 if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) {
87 return;
90 exit_err:
91 error_set(err, QERR_UNDEFINED_ERROR);
94 typedef struct GuestFileHandle {
95 uint64_t id;
96 FILE *fh;
97 QTAILQ_ENTRY(GuestFileHandle) next;
98 } GuestFileHandle;
100 static struct {
101 QTAILQ_HEAD(, GuestFileHandle) filehandles;
102 } guest_file_state;
104 static void guest_file_handle_add(FILE *fh)
106 GuestFileHandle *gfh;
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);
114 static GuestFileHandle *guest_file_handle_find(int64_t id)
116 GuestFileHandle *gfh;
118 QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next)
120 if (gfh->id == id) {
121 return gfh;
125 return NULL;
128 int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **err)
130 FILE *fh;
131 int fd;
132 int64_t ret = -1;
134 if (!has_mode) {
135 mode = "r";
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;
144 /* set fd non-blocking to avoid common use cases (like reading from a
145 * named pipe) from hanging the agent
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;
156 guest_file_handle_add(fh);
157 slog("guest-file-open, handle: %d", fd);
158 return fd;
161 void qmp_guest_file_close(int64_t handle, Error **err)
163 GuestFileHandle *gfh = guest_file_handle_find(handle);
164 int ret;
166 slog("guest-file-close called, handle: %ld", handle);
167 if (!gfh) {
168 error_set(err, QERR_FD_NOT_FOUND, "handle");
169 return;
172 ret = fclose(gfh->fh);
173 if (ret == -1) {
174 error_set(err, QERR_QGA_COMMAND_FAILED, "fclose() failed");
175 return;
178 QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next);
179 g_free(gfh);
182 struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
183 int64_t count, Error **err)
185 GuestFileHandle *gfh = guest_file_handle_find(handle);
186 GuestFileRead *read_data = NULL;
187 guchar *buf;
188 FILE *fh;
189 size_t read_count;
191 if (!gfh) {
192 error_set(err, QERR_FD_NOT_FOUND, "handle");
193 return NULL;
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;
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);
218 g_free(buf);
219 clearerr(fh);
221 return read_data;
224 GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64,
225 bool has_count, int64_t count, Error **err)
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;
234 if (!gfh) {
235 error_set(err, QERR_FD_NOT_FOUND, "handle");
236 return NULL;
239 fh = gfh->fh;
240 buf = g_base64_decode(buf_b64, &buf_len);
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;
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);
259 g_free(buf);
260 clearerr(fh);
262 return write_data;
265 struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
266 int64_t whence, Error **err)
268 GuestFileHandle *gfh = guest_file_handle_find(handle);
269 GuestFileSeek *seek_data = NULL;
270 FILE *fh;
271 int ret;
273 if (!gfh) {
274 error_set(err, QERR_FD_NOT_FOUND, "handle");
275 return NULL;
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);
287 clearerr(fh);
289 return seek_data;
292 void qmp_guest_file_flush(int64_t handle, Error **err)
294 GuestFileHandle *gfh = guest_file_handle_find(handle);
295 FILE *fh;
296 int ret;
298 if (!gfh) {
299 error_set(err, QERR_FD_NOT_FOUND, "handle");
300 return;
303 fh = gfh->fh;
304 ret = fflush(fh);
305 if (ret == EOF) {
306 error_set(err, QERR_QGA_COMMAND_FAILED, strerror(errno));
310 static void guest_file_init(void)
312 QTAILQ_INIT(&guest_file_state.filehandles);
315 /* linux-specific implementations. avoid this if at all possible. */
316 #if defined(__linux__)
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;
325 typedef QTAILQ_HEAD(, FsMount) FsMountList;
327 static void free_fs_mount_list(FsMountList *mounts)
329 FsMount *mount, *temp;
331 if (!mounts) {
332 return;
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);
344 * Walk the mount table and build a list of local file systems
346 static int build_fs_mount_list(FsMountList *mounts)
348 struct mntent *ment;
349 FsMount *mount;
350 char const *mtab = "/proc/self/mounts";
351 FILE *fp;
353 fp = setmntent(mtab, "r");
354 if (!fp) {
355 g_warning("fsfreeze: unable to read mtab");
356 return -1;
359 while ((ment = getmntent(fp))) {
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.
366 if ((ment->mnt_fsname[0] != '/') ||
367 (strcmp(ment->mnt_type, "smbfs") == 0) ||
368 (strcmp(ment->mnt_type, "cifs") == 0)) {
369 continue;
372 mount = g_malloc0(sizeof(FsMount));
373 mount->dirname = g_strdup(ment->mnt_dir);
374 mount->devtype = g_strdup(ment->mnt_type);
376 QTAILQ_INSERT_TAIL(mounts, mount, next);
379 endmntent(fp);
381 return 0;
383 #endif
385 #if defined(CONFIG_FSFREEZE)
388 * Return status of freeze/thaw
390 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
392 if (ga_is_frozen(ga_state)) {
393 return GUEST_FSFREEZE_STATUS_FROZEN;
396 return GUEST_FSFREEZE_STATUS_THAWED;
400 * Walk list of mounted file systems in the guest, and freeze the ones which
401 * are real local file systems.
403 int64_t qmp_guest_fsfreeze_freeze(Error **err)
405 int ret = 0, i = 0;
406 FsMountList mounts;
407 struct FsMount *mount;
408 int fd;
409 char err_msg[512];
411 slog("guest-fsfreeze called");
413 QTAILQ_INIT(&mounts);
414 ret = build_fs_mount_list(&mounts);
415 if (ret < 0) {
416 return ret;
419 /* cannot risk guest agent blocking itself on a write in this state */
420 ga_set_frozen(ga_state);
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;
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.
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.
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;
449 } else {
450 i++;
452 close(fd);
455 free_fs_mount_list(&mounts);
456 return i;
458 error:
459 free_fs_mount_list(&mounts);
460 qmp_guest_fsfreeze_thaw(NULL);
461 return 0;
465 * Walk list of frozen file systems in the guest, and thaw them.
467 int64_t qmp_guest_fsfreeze_thaw(Error **err)
469 int ret;
470 FsMountList mounts;
471 FsMount *mount;
472 int fd, i = 0, logged;
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;
482 QTAILQ_FOREACH(mount, &mounts, next) {
483 logged = false;
484 fd = qemu_open(mount->dirname, O_RDONLY);
485 if (fd == -1) {
486 continue;
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.
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).
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.
504 do {
505 ret = ioctl(fd, FITHAW);
506 if (ret == 0 && !logged) {
507 i++;
508 logged = true;
510 } while (ret == 0);
511 close(fd);
514 ga_unset_frozen(ga_state);
515 free_fs_mount_list(&mounts);
516 return i;
519 static void guest_fsfreeze_cleanup(void)
521 int64_t ret;
522 Error *err = NULL;
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");
531 #endif /* CONFIG_FSFREEZE */
533 #if defined(CONFIG_FSTRIM)
535 * Walk list of mounted file systems in the guest, and trim them.
537 void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
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,
550 slog("guest-fstrim called");
552 QTAILQ_INIT(&mounts);
553 ret = build_fs_mount_list(&mounts);
554 if (ret < 0) {
555 return;
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;
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).
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;
583 close(fd);
586 error:
587 free_fs_mount_list(&mounts);
589 #endif /* CONFIG_FSTRIM */
592 #define LINUX_SYS_STATE_FILE "/sys/power/state"
593 #define SUSPEND_SUPPORTED 0
594 #define SUSPEND_NOT_SUPPORTED 1
596 static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg,
597 const char *sysfile_str, Error **err)
599 char *pmutils_path;
600 pid_t pid, rpid;
601 int status;
603 pmutils_path = g_find_program_in_path(pmutils_bin);
605 pid = fork();
606 if (!pid) {
607 char buf[32]; /* hopefully big enough */
608 ssize_t ret;
609 int fd;
611 setsid();
612 reopen_fd_to_null(0);
613 reopen_fd_to_null(1);
614 reopen_fd_to_null(2);
616 if (pmutils_path) {
617 execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
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.
625 if (!sysfile_str) {
626 _exit(SUSPEND_NOT_SUPPORTED);
629 fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
630 if (fd < 0) {
631 _exit(SUSPEND_NOT_SUPPORTED);
634 ret = read(fd, buf, sizeof(buf)-1);
635 if (ret <= 0) {
636 _exit(SUSPEND_NOT_SUPPORTED);
638 buf[ret] = '\0';
640 if (strstr(buf, sysfile_str)) {
641 _exit(SUSPEND_SUPPORTED);
644 _exit(SUSPEND_NOT_SUPPORTED);
647 g_free(pmutils_path);
649 if (pid < 0) {
650 goto undef_err;
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;
668 undef_err:
669 error_set(err, QERR_UNDEFINED_ERROR);
672 static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
673 Error **err)
675 char *pmutils_path;
676 pid_t rpid, pid;
677 int status;
679 pmutils_path = g_find_program_in_path(pmutils_bin);
681 pid = fork();
682 if (pid == 0) {
683 /* child */
684 int fd;
686 setsid();
687 reopen_fd_to_null(0);
688 reopen_fd_to_null(1);
689 reopen_fd_to_null(2);
691 if (pmutils_path) {
692 execle(pmutils_path, pmutils_bin, NULL, environ);
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.
700 if (!sysfile_str) {
701 _exit(EXIT_FAILURE);
704 fd = open(LINUX_SYS_STATE_FILE, O_WRONLY);
705 if (fd < 0) {
706 _exit(EXIT_FAILURE);
709 if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) {
710 _exit(EXIT_FAILURE);
713 _exit(EXIT_SUCCESS);
716 g_free(pmutils_path);
718 if (pid < 0) {
719 goto exit_err;
722 do {
723 rpid = waitpid(pid, &status, 0);
724 } while (rpid == -1 && errno == EINTR);
725 if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) {
726 return;
729 exit_err:
730 error_set(err, QERR_UNDEFINED_ERROR);
733 void qmp_guest_suspend_disk(Error **err)
735 bios_supports_mode("pm-is-supported", "--hibernate", "disk", err);
736 if (error_is_set(err)) {
737 return;
740 guest_suspend("pm-hibernate", "disk", err);
743 void qmp_guest_suspend_ram(Error **err)
745 bios_supports_mode("pm-is-supported", "--suspend", "mem", err);
746 if (error_is_set(err)) {
747 return;
750 guest_suspend("pm-suspend", "mem", err);
753 void qmp_guest_suspend_hybrid(Error **err)
755 bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL, err);
756 if (error_is_set(err)) {
757 return;
760 guest_suspend("pm-suspend-hybrid", NULL, err);
763 static GuestNetworkInterfaceList *
764 guest_find_interface(GuestNetworkInterfaceList *head,
765 const char *name)
767 for (; head; head = head->next) {
768 if (strcmp(head->value->name, name) == 0) {
769 break;
773 return head;
777 * Build information about guest interfaces
779 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
781 GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
782 struct ifaddrs *ifap, *ifa;
783 char err_msg[512];
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;
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;
802 g_debug("Processing %s interface", ifa->ifa_name);
804 info = guest_find_interface(head, ifa->ifa_name);
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);
811 if (!cur_item) {
812 head = cur_item = info;
813 } else {
814 cur_item->next = info;
815 cur_item = info;
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;
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;
841 mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
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;
854 info->value->has_hardware_address = true;
855 close(sock);
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;
871 address_item->value->ip_address = g_strdup(addr4);
872 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4;
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]);
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;
893 address_item->value->ip_address = g_strdup(addr6);
894 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6;
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]);
908 if (!address_item) {
909 continue;
912 address_list = &info->value->ip_addresses;
914 while (*address_list && (*address_list)->next) {
915 address_list = &(*address_list)->next;
918 if (!*address_list) {
919 *address_list = address_item;
920 } else {
921 (*address_list)->next = address_item;
924 info->value->has_ip_addresses = true;
929 freeifaddrs(ifap);
930 return head;
932 error:
933 freeifaddrs(ifap);
934 qapi_free_GuestNetworkInterfaceList(head);
935 return NULL;
938 #else /* defined(__linux__) */
940 void qmp_guest_suspend_disk(Error **err)
942 error_set(err, QERR_UNSUPPORTED);
945 void qmp_guest_suspend_ram(Error **err)
947 error_set(err, QERR_UNSUPPORTED);
950 void qmp_guest_suspend_hybrid(Error **err)
952 error_set(err, QERR_UNSUPPORTED);
955 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
957 error_set(errp, QERR_UNSUPPORTED);
958 return NULL;
961 #endif
963 #if !defined(CONFIG_FSFREEZE)
965 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
967 error_set(err, QERR_UNSUPPORTED);
969 return 0;
972 int64_t qmp_guest_fsfreeze_freeze(Error **err)
974 error_set(err, QERR_UNSUPPORTED);
976 return 0;
979 int64_t qmp_guest_fsfreeze_thaw(Error **err)
981 error_set(err, QERR_UNSUPPORTED);
983 return 0;
985 #endif /* CONFIG_FSFREEZE */
987 #if !defined(CONFIG_FSTRIM)
988 void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
990 error_set(err, QERR_UNSUPPORTED);
992 #endif
994 /* register init/cleanup routines for stateful command groups */
995 void ga_command_state_init(GAState *s, GACommandState *cs)
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);