xref: /qemu/qga/commands-posix.c (revision c5854acb75510969bc3c483f61fbddb027123173)
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