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