]> Git Repo - qemu.git/blob - qga/commands-posix.c
qemu-ga: add guest-sync-delimited
[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      <[email protected]>
8  *  Michal Privoznik  <[email protected]>
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 }
This page took 0.077138 seconds and 4 git commands to generate.