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