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