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