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