xref: /qemu/qga/commands-posix.c (revision d35d4cb5)
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 void qmp_guest_suspend_disk(Error **err)
885 {
886     error_set(err, QERR_UNSUPPORTED);
887 }
888 
889 void qmp_guest_suspend_ram(Error **err)
890 {
891     error_set(err, QERR_UNSUPPORTED);
892 }
893 
894 void qmp_guest_suspend_hybrid(Error **err)
895 {
896     error_set(err, QERR_UNSUPPORTED);
897 }
898 
899 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
900 {
901     error_set(errp, QERR_UNSUPPORTED);
902     return NULL;
903 }
904 
905 #endif
906 
907 #if !defined(CONFIG_FSFREEZE)
908 
909 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
910 {
911     error_set(err, QERR_UNSUPPORTED);
912 
913     return 0;
914 }
915 
916 int64_t qmp_guest_fsfreeze_freeze(Error **err)
917 {
918     error_set(err, QERR_UNSUPPORTED);
919 
920     return 0;
921 }
922 
923 int64_t qmp_guest_fsfreeze_thaw(Error **err)
924 {
925     error_set(err, QERR_UNSUPPORTED);
926 
927     return 0;
928 }
929 
930 #endif
931 
932 /* register init/cleanup routines for stateful command groups */
933 void ga_command_state_init(GAState *s, GACommandState *cs)
934 {
935 #if defined(CONFIG_FSFREEZE)
936     ga_command_state_add(cs, guest_fsfreeze_init, guest_fsfreeze_cleanup);
937 #endif
938     ga_command_state_add(cs, guest_file_init, NULL);
939 }
940