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