blob: c253f97fa7792d9b10ffc51720919eeb37917eda [file] [log] [blame]
Michael Rothe3d4d252011-07-19 15:41:55 -05001/*
Michael Roth42074a92012-01-19 22:19:27 -06002 * QEMU Guest Agent POSIX-specific command implementations
Michael Rothe3d4d252011-07-19 15:41:55 -05003 *
4 * Copyright IBM Corp. 2011
5 *
6 * Authors:
7 * Michael Roth <mdroth@linux.vnet.ibm.com>
Michal Privoznik3424fc92012-02-29 17:02:23 +01008 * Michal Privoznik <mprivozn@redhat.com>
Michael Rothe3d4d252011-07-19 15:41:55 -05009 *
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>
Michael Rothe3d4d252011-07-19 15:41:55 -050015#include <sys/types.h>
16#include <sys/ioctl.h>
Luiz Capitulino2c02cbf2012-05-23 15:48:05 -030017#include <sys/wait.h>
Michael Rothe3d4d252011-07-19 15:41:55 -050018#include "qga/guest-agent-core.h"
19#include "qga-qmp-commands.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010020#include "qapi/qmp/qerror.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010021#include "qemu/queue.h"
22#include "qemu/host-utils.h"
Michael Rothe3d4d252011-07-19 15:41:55 -050023
Luiz Capitulino2c02cbf2012-05-23 15:48:05 -030024#ifndef CONFIG_HAS_ENVIRON
Andreas Färbereecae142012-05-27 17:02:20 +020025#ifdef __APPLE__
26#include <crt_externs.h>
27#define environ (*_NSGetEnviron())
28#else
Luiz Capitulino2c02cbf2012-05-23 15:48:05 -030029extern char **environ;
30#endif
Andreas Färbereecae142012-05-27 17:02:20 +020031#endif
Luiz Capitulino2c02cbf2012-05-23 15:48:05 -030032
Michael Rothe72c3f22012-03-25 13:59:41 -050033#if defined(__linux__)
34#include <mntent.h>
35#include <linux/fs.h>
36#include <ifaddrs.h>
37#include <arpa/inet.h>
38#include <sys/socket.h>
39#include <net/if.h>
Michael Rothe72c3f22012-03-25 13:59:41 -050040
Paolo Bonzinieab5fd52012-06-13 07:41:28 +020041#ifdef FIFREEZE
Michael Rothe72c3f22012-03-25 13:59:41 -050042#define CONFIG_FSFREEZE
43#endif
Paolo Bonzinieab5fd52012-06-13 07:41:28 +020044#ifdef FITRIM
45#define CONFIG_FSTRIM
46#endif
Michael Rothe72c3f22012-03-25 13:59:41 -050047#endif
48
Luiz Capitulinod220a6d2012-11-27 11:01:58 -020049static void ga_wait_child(pid_t pid, int *status, Error **err)
50{
51 pid_t rpid;
52
53 *status = 0;
54
55 do {
56 rpid = waitpid(pid, status, 0);
57 } while (rpid == -1 && errno == EINTR);
58
59 if (rpid == -1) {
60 error_setg_errno(err, errno, "failed to wait for child (pid: %d)", pid);
61 return;
62 }
63
64 g_assert(rpid == pid);
65}
66
Michael Rothe3d4d252011-07-19 15:41:55 -050067void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
68{
Michael Rothe3d4d252011-07-19 15:41:55 -050069 const char *shutdown_flag;
Luiz Capitulinod220a6d2012-11-27 11:01:58 -020070 Error *local_err = NULL;
71 pid_t pid;
Luiz Capitulino36748382012-05-14 15:25:20 -030072 int status;
Michael Rothe3d4d252011-07-19 15:41:55 -050073
74 slog("guest-shutdown called, mode: %s", mode);
75 if (!has_mode || strcmp(mode, "powerdown") == 0) {
76 shutdown_flag = "-P";
77 } else if (strcmp(mode, "halt") == 0) {
78 shutdown_flag = "-H";
79 } else if (strcmp(mode, "reboot") == 0) {
80 shutdown_flag = "-r";
81 } else {
Luiz Capitulinod220a6d2012-11-27 11:01:58 -020082 error_setg(err,
83 "mode is invalid (valid values are: halt|powerdown|reboot");
Michael Rothe3d4d252011-07-19 15:41:55 -050084 return;
85 }
86
Luiz Capitulinod5dd3492012-05-11 16:19:47 -030087 pid = fork();
88 if (pid == 0) {
Michael Rothe3d4d252011-07-19 15:41:55 -050089 /* child, start the shutdown */
90 setsid();
Luiz Capitulino36748382012-05-14 15:25:20 -030091 reopen_fd_to_null(0);
92 reopen_fd_to_null(1);
93 reopen_fd_to_null(2);
Michael Rothe3d4d252011-07-19 15:41:55 -050094
Luiz Capitulino36748382012-05-14 15:25:20 -030095 execle("/sbin/shutdown", "shutdown", shutdown_flag, "+0",
96 "hypervisor initiated shutdown", (char*)NULL, environ);
97 _exit(EXIT_FAILURE);
Luiz Capitulinod5dd3492012-05-11 16:19:47 -030098 } else if (pid < 0) {
Luiz Capitulinod220a6d2012-11-27 11:01:58 -020099 error_setg_errno(err, errno, "failed to create child process");
Luiz Capitulinod5dd3492012-05-11 16:19:47 -0300100 return;
101 }
102
Luiz Capitulinod220a6d2012-11-27 11:01:58 -0200103 ga_wait_child(pid, &status, &local_err);
104 if (error_is_set(&local_err)) {
105 error_propagate(err, local_err);
106 return;
107 }
108
109 if (!WIFEXITED(status)) {
110 error_setg(err, "child process has terminated abnormally");
111 return;
112 }
113
114 if (WEXITSTATUS(status)) {
115 error_setg(err, "child process has failed to shutdown");
116 return;
117 }
118
119 /* succeded */
Michael Rothe3d4d252011-07-19 15:41:55 -0500120}
121
Lei Li6912e6a2013-03-05 17:39:11 +0800122int64_t qmp_guest_get_time(Error **errp)
123{
124 int ret;
125 qemu_timeval tq;
126 int64_t time_ns;
127
128 ret = qemu_gettimeofday(&tq);
129 if (ret < 0) {
130 error_setg_errno(errp, errno, "Failed to get time");
131 return -1;
132 }
133
134 time_ns = tq.tv_sec * 1000000000LL + tq.tv_usec * 1000;
135 return time_ns;
136}
137
Lei Lia1bca572013-03-05 17:39:12 +0800138void qmp_guest_set_time(int64_t time_ns, Error **errp)
139{
140 int ret;
141 int status;
142 pid_t pid;
143 Error *local_err = NULL;
144 struct timeval tv;
145
146 /* year-2038 will overflow in case time_t is 32bit */
147 if (time_ns / 1000000000 != (time_t)(time_ns / 1000000000)) {
148 error_setg(errp, "Time %" PRId64 " is too large", time_ns);
149 return;
150 }
151
152 tv.tv_sec = time_ns / 1000000000;
153 tv.tv_usec = (time_ns % 1000000000) / 1000;
154
155 ret = settimeofday(&tv, NULL);
156 if (ret < 0) {
157 error_setg_errno(errp, errno, "Failed to set time to guest");
158 return;
159 }
160
161 /* Set the Hardware Clock to the current System Time. */
162 pid = fork();
163 if (pid == 0) {
164 setsid();
165 reopen_fd_to_null(0);
166 reopen_fd_to_null(1);
167 reopen_fd_to_null(2);
168
169 execle("/sbin/hwclock", "hwclock", "-w", NULL, environ);
170 _exit(EXIT_FAILURE);
171 } else if (pid < 0) {
172 error_setg_errno(errp, errno, "failed to create child process");
173 return;
174 }
175
176 ga_wait_child(pid, &status, &local_err);
177 if (error_is_set(&local_err)) {
178 error_propagate(errp, local_err);
179 return;
180 }
181
182 if (!WIFEXITED(status)) {
183 error_setg(errp, "child process has terminated abnormally");
184 return;
185 }
186
187 if (WEXITSTATUS(status)) {
188 error_setg(errp, "hwclock failed to set hardware clock to system time");
189 return;
190 }
191}
192
Michael Rothe3d4d252011-07-19 15:41:55 -0500193typedef struct GuestFileHandle {
194 uint64_t id;
195 FILE *fh;
196 QTAILQ_ENTRY(GuestFileHandle) next;
197} GuestFileHandle;
198
199static struct {
200 QTAILQ_HEAD(, GuestFileHandle) filehandles;
201} guest_file_state;
202
Michael Roth39097da2013-03-01 11:40:27 -0600203static int64_t guest_file_handle_add(FILE *fh, Error **errp)
Michael Rothe3d4d252011-07-19 15:41:55 -0500204{
205 GuestFileHandle *gfh;
Michael Roth39097da2013-03-01 11:40:27 -0600206 int64_t handle;
207
208 handle = ga_get_fd_handle(ga_state, errp);
209 if (error_is_set(errp)) {
210 return 0;
211 }
Michael Rothe3d4d252011-07-19 15:41:55 -0500212
Anthony Liguori7267c092011-08-20 22:09:37 -0500213 gfh = g_malloc0(sizeof(GuestFileHandle));
Michael Roth39097da2013-03-01 11:40:27 -0600214 gfh->id = handle;
Michael Rothe3d4d252011-07-19 15:41:55 -0500215 gfh->fh = fh;
216 QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next);
Michael Roth39097da2013-03-01 11:40:27 -0600217
218 return handle;
Michael Rothe3d4d252011-07-19 15:41:55 -0500219}
220
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200221static GuestFileHandle *guest_file_handle_find(int64_t id, Error **err)
Michael Rothe3d4d252011-07-19 15:41:55 -0500222{
223 GuestFileHandle *gfh;
224
225 QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next)
226 {
227 if (gfh->id == id) {
228 return gfh;
229 }
230 }
231
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200232 error_setg(err, "handle '%" PRId64 "' has not been found", id);
Michael Rothe3d4d252011-07-19 15:41:55 -0500233 return NULL;
234}
235
236int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **err)
237{
238 FILE *fh;
239 int fd;
Michael Roth39097da2013-03-01 11:40:27 -0600240 int64_t ret = -1, handle;
Michael Rothe3d4d252011-07-19 15:41:55 -0500241
242 if (!has_mode) {
243 mode = "r";
244 }
245 slog("guest-file-open called, filepath: %s, mode: %s", path, mode);
246 fh = fopen(path, mode);
247 if (!fh) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200248 error_setg_errno(err, errno, "failed to open file '%s' (mode: '%s')",
249 path, mode);
Michael Rothe3d4d252011-07-19 15:41:55 -0500250 return -1;
251 }
252
253 /* set fd non-blocking to avoid common use cases (like reading from a
254 * named pipe) from hanging the agent
255 */
256 fd = fileno(fh);
257 ret = fcntl(fd, F_GETFL);
258 ret = fcntl(fd, F_SETFL, ret | O_NONBLOCK);
259 if (ret == -1) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200260 error_setg_errno(err, errno, "failed to make file '%s' non-blocking",
261 path);
Michael Rothe3d4d252011-07-19 15:41:55 -0500262 fclose(fh);
263 return -1;
264 }
265
Michael Roth39097da2013-03-01 11:40:27 -0600266 handle = guest_file_handle_add(fh, err);
267 if (error_is_set(err)) {
268 fclose(fh);
269 return -1;
270 }
271
272 slog("guest-file-open, handle: %d", handle);
273 return handle;
Michael Rothe3d4d252011-07-19 15:41:55 -0500274}
275
276void qmp_guest_file_close(int64_t handle, Error **err)
277{
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200278 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500279 int ret;
280
281 slog("guest-file-close called, handle: %ld", handle);
282 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500283 return;
284 }
285
286 ret = fclose(gfh->fh);
Luiz Capitulino3ac4b7c2012-11-27 11:01:56 -0200287 if (ret == EOF) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200288 error_setg_errno(err, errno, "failed to close handle");
Michael Rothe3d4d252011-07-19 15:41:55 -0500289 return;
290 }
291
292 QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next);
Anthony Liguori7267c092011-08-20 22:09:37 -0500293 g_free(gfh);
Michael Rothe3d4d252011-07-19 15:41:55 -0500294}
295
296struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
297 int64_t count, Error **err)
298{
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200299 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500300 GuestFileRead *read_data = NULL;
301 guchar *buf;
302 FILE *fh;
303 size_t read_count;
304
305 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500306 return NULL;
307 }
308
309 if (!has_count) {
310 count = QGA_READ_COUNT_DEFAULT;
311 } else if (count < 0) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200312 error_setg(err, "value '%" PRId64 "' is invalid for argument count",
313 count);
Michael Rothe3d4d252011-07-19 15:41:55 -0500314 return NULL;
315 }
316
317 fh = gfh->fh;
Anthony Liguori7267c092011-08-20 22:09:37 -0500318 buf = g_malloc0(count+1);
Michael Rothe3d4d252011-07-19 15:41:55 -0500319 read_count = fread(buf, 1, count, fh);
320 if (ferror(fh)) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200321 error_setg_errno(err, errno, "failed to read file");
Michael Rothe3d4d252011-07-19 15:41:55 -0500322 slog("guest-file-read failed, handle: %ld", handle);
Michael Rothe3d4d252011-07-19 15:41:55 -0500323 } else {
324 buf[read_count] = 0;
Anthony Liguori7267c092011-08-20 22:09:37 -0500325 read_data = g_malloc0(sizeof(GuestFileRead));
Michael Rothe3d4d252011-07-19 15:41:55 -0500326 read_data->count = read_count;
327 read_data->eof = feof(fh);
328 if (read_count) {
329 read_data->buf_b64 = g_base64_encode(buf, read_count);
330 }
331 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500332 g_free(buf);
Michael Rothe3d4d252011-07-19 15:41:55 -0500333 clearerr(fh);
334
335 return read_data;
336}
337
338GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64,
339 bool has_count, int64_t count, Error **err)
340{
341 GuestFileWrite *write_data = NULL;
342 guchar *buf;
343 gsize buf_len;
344 int write_count;
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200345 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500346 FILE *fh;
347
348 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500349 return NULL;
350 }
351
352 fh = gfh->fh;
353 buf = g_base64_decode(buf_b64, &buf_len);
354
355 if (!has_count) {
356 count = buf_len;
357 } else if (count < 0 || count > buf_len) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200358 error_setg(err, "value '%" PRId64 "' is invalid for argument count",
359 count);
Anthony Liguori7267c092011-08-20 22:09:37 -0500360 g_free(buf);
Michael Rothe3d4d252011-07-19 15:41:55 -0500361 return NULL;
362 }
363
364 write_count = fwrite(buf, 1, count, fh);
365 if (ferror(fh)) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200366 error_setg_errno(err, errno, "failed to write to file");
Michael Rothe3d4d252011-07-19 15:41:55 -0500367 slog("guest-file-write failed, handle: %ld", handle);
Michael Rothe3d4d252011-07-19 15:41:55 -0500368 } else {
Anthony Liguori7267c092011-08-20 22:09:37 -0500369 write_data = g_malloc0(sizeof(GuestFileWrite));
Michael Rothe3d4d252011-07-19 15:41:55 -0500370 write_data->count = write_count;
371 write_data->eof = feof(fh);
372 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500373 g_free(buf);
Michael Rothe3d4d252011-07-19 15:41:55 -0500374 clearerr(fh);
375
376 return write_data;
377}
378
379struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
380 int64_t whence, Error **err)
381{
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200382 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500383 GuestFileSeek *seek_data = NULL;
384 FILE *fh;
385 int ret;
386
387 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500388 return NULL;
389 }
390
391 fh = gfh->fh;
392 ret = fseek(fh, offset, whence);
393 if (ret == -1) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200394 error_setg_errno(err, errno, "failed to seek file");
Michael Rothe3d4d252011-07-19 15:41:55 -0500395 } else {
Anthony Liguori7267c092011-08-20 22:09:37 -0500396 seek_data = g_malloc0(sizeof(GuestFileRead));
Michael Rothe3d4d252011-07-19 15:41:55 -0500397 seek_data->position = ftell(fh);
398 seek_data->eof = feof(fh);
399 }
400 clearerr(fh);
401
402 return seek_data;
403}
404
405void qmp_guest_file_flush(int64_t handle, Error **err)
406{
Luiz Capitulinoa9de6d02012-11-27 11:01:55 -0200407 GuestFileHandle *gfh = guest_file_handle_find(handle, err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500408 FILE *fh;
409 int ret;
410
411 if (!gfh) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500412 return;
413 }
414
415 fh = gfh->fh;
416 ret = fflush(fh);
417 if (ret == EOF) {
Luiz Capitulinodb3edb62012-11-27 11:01:57 -0200418 error_setg_errno(err, errno, "failed to flush file");
Michael Rothe3d4d252011-07-19 15:41:55 -0500419 }
420}
421
422static void guest_file_init(void)
423{
424 QTAILQ_INIT(&guest_file_state.filehandles);
425}
426
Michael Rothe72c3f22012-03-25 13:59:41 -0500427/* linux-specific implementations. avoid this if at all possible. */
428#if defined(__linux__)
429
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200430#if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
Paolo Bonziniaf022032012-06-13 07:41:27 +0200431typedef struct FsMount {
Michael Rothe3d4d252011-07-19 15:41:55 -0500432 char *dirname;
433 char *devtype;
Paolo Bonziniaf022032012-06-13 07:41:27 +0200434 QTAILQ_ENTRY(FsMount) next;
435} FsMount;
Michael Rothe3d4d252011-07-19 15:41:55 -0500436
Paolo Bonziniaf022032012-06-13 07:41:27 +0200437typedef QTAILQ_HEAD(, FsMount) FsMountList;
Michael Roth9e8aded432012-04-16 19:52:17 -0500438
Paolo Bonziniaf022032012-06-13 07:41:27 +0200439static void free_fs_mount_list(FsMountList *mounts)
Michael Roth9e8aded432012-04-16 19:52:17 -0500440{
Paolo Bonziniaf022032012-06-13 07:41:27 +0200441 FsMount *mount, *temp;
Michael Roth9e8aded432012-04-16 19:52:17 -0500442
443 if (!mounts) {
444 return;
445 }
446
447 QTAILQ_FOREACH_SAFE(mount, mounts, next, temp) {
448 QTAILQ_REMOVE(mounts, mount, next);
449 g_free(mount->dirname);
450 g_free(mount->devtype);
451 g_free(mount);
452 }
453}
454
Michael Rothe3d4d252011-07-19 15:41:55 -0500455/*
456 * Walk the mount table and build a list of local file systems
457 */
Luiz Capitulino261551d2012-11-29 15:29:11 -0200458static void build_fs_mount_list(FsMountList *mounts, Error **err)
Michael Rothe3d4d252011-07-19 15:41:55 -0500459{
460 struct mntent *ment;
Paolo Bonziniaf022032012-06-13 07:41:27 +0200461 FsMount *mount;
Michael Roth9e2fa412012-05-29 10:08:50 -0500462 char const *mtab = "/proc/self/mounts";
Michael Rothe3d4d252011-07-19 15:41:55 -0500463 FILE *fp;
464
Michael Rothe3d4d252011-07-19 15:41:55 -0500465 fp = setmntent(mtab, "r");
466 if (!fp) {
Luiz Capitulino261551d2012-11-29 15:29:11 -0200467 error_setg(err, "failed to open mtab file: '%s'", mtab);
468 return;
Michael Rothe3d4d252011-07-19 15:41:55 -0500469 }
470
471 while ((ment = getmntent(fp))) {
472 /*
473 * An entry which device name doesn't start with a '/' is
474 * either a dummy file system or a network file system.
475 * Add special handling for smbfs and cifs as is done by
476 * coreutils as well.
477 */
478 if ((ment->mnt_fsname[0] != '/') ||
479 (strcmp(ment->mnt_type, "smbfs") == 0) ||
480 (strcmp(ment->mnt_type, "cifs") == 0)) {
481 continue;
482 }
483
Paolo Bonziniaf022032012-06-13 07:41:27 +0200484 mount = g_malloc0(sizeof(FsMount));
Anthony Liguori7267c092011-08-20 22:09:37 -0500485 mount->dirname = g_strdup(ment->mnt_dir);
486 mount->devtype = g_strdup(ment->mnt_type);
Michael Rothe3d4d252011-07-19 15:41:55 -0500487
Michael Roth9e8aded432012-04-16 19:52:17 -0500488 QTAILQ_INSERT_TAIL(mounts, mount, next);
Michael Rothe3d4d252011-07-19 15:41:55 -0500489 }
490
491 endmntent(fp);
Michael Rothe3d4d252011-07-19 15:41:55 -0500492}
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200493#endif
494
495#if defined(CONFIG_FSFREEZE)
Michael Rothe3d4d252011-07-19 15:41:55 -0500496
Tomoki Sekiyamaec0f6942012-12-12 12:55:55 +0900497typedef enum {
498 FSFREEZE_HOOK_THAW = 0,
499 FSFREEZE_HOOK_FREEZE,
500} FsfreezeHookArg;
501
502const char *fsfreeze_hook_arg_string[] = {
503 "thaw",
504 "freeze",
505};
506
507static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **err)
508{
509 int status;
510 pid_t pid;
511 const char *hook;
512 const char *arg_str = fsfreeze_hook_arg_string[arg];
513 Error *local_err = NULL;
514
515 hook = ga_fsfreeze_hook(ga_state);
516 if (!hook) {
517 return;
518 }
519 if (access(hook, X_OK) != 0) {
520 error_setg_errno(err, errno, "can't access fsfreeze hook '%s'", hook);
521 return;
522 }
523
524 slog("executing fsfreeze hook with arg '%s'", arg_str);
525 pid = fork();
526 if (pid == 0) {
527 setsid();
528 reopen_fd_to_null(0);
529 reopen_fd_to_null(1);
530 reopen_fd_to_null(2);
531
532 execle(hook, hook, arg_str, NULL, environ);
533 _exit(EXIT_FAILURE);
534 } else if (pid < 0) {
535 error_setg_errno(err, errno, "failed to create child process");
536 return;
537 }
538
539 ga_wait_child(pid, &status, &local_err);
540 if (error_is_set(&local_err)) {
541 error_propagate(err, local_err);
542 return;
543 }
544
545 if (!WIFEXITED(status)) {
546 error_setg(err, "fsfreeze hook has terminated abnormally");
547 return;
548 }
549
550 status = WEXITSTATUS(status);
551 if (status) {
552 error_setg(err, "fsfreeze hook has failed with status %d", status);
553 return;
554 }
555}
556
Michael Rothe3d4d252011-07-19 15:41:55 -0500557/*
558 * Return status of freeze/thaw
559 */
560GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
561{
Michael Rothf22d85e2012-04-17 19:01:45 -0500562 if (ga_is_frozen(ga_state)) {
563 return GUEST_FSFREEZE_STATUS_FROZEN;
564 }
565
566 return GUEST_FSFREEZE_STATUS_THAWED;
Michael Rothe3d4d252011-07-19 15:41:55 -0500567}
568
569/*
570 * Walk list of mounted file systems in the guest, and freeze the ones which
571 * are real local file systems.
572 */
573int64_t qmp_guest_fsfreeze_freeze(Error **err)
574{
575 int ret = 0, i = 0;
Paolo Bonziniaf022032012-06-13 07:41:27 +0200576 FsMountList mounts;
577 struct FsMount *mount;
Luiz Capitulino261551d2012-11-29 15:29:11 -0200578 Error *local_err = NULL;
Michael Rothe3d4d252011-07-19 15:41:55 -0500579 int fd;
Michael Rothe3d4d252011-07-19 15:41:55 -0500580
581 slog("guest-fsfreeze called");
582
Tomoki Sekiyamaec0f6942012-12-12 12:55:55 +0900583 execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err);
584 if (error_is_set(&local_err)) {
585 error_propagate(err, local_err);
586 return -1;
587 }
588
Michael Roth9e8aded432012-04-16 19:52:17 -0500589 QTAILQ_INIT(&mounts);
Luiz Capitulino261551d2012-11-29 15:29:11 -0200590 build_fs_mount_list(&mounts, &local_err);
591 if (error_is_set(&local_err)) {
592 error_propagate(err, local_err);
593 return -1;
Michael Rothe3d4d252011-07-19 15:41:55 -0500594 }
595
596 /* cannot risk guest agent blocking itself on a write in this state */
Michael Rothf22d85e2012-04-17 19:01:45 -0500597 ga_set_frozen(ga_state);
Michael Rothe3d4d252011-07-19 15:41:55 -0500598
Michael Roth9e8aded432012-04-16 19:52:17 -0500599 QTAILQ_FOREACH(mount, &mounts, next) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500600 fd = qemu_open(mount->dirname, O_RDONLY);
601 if (fd == -1) {
Luiz Capitulino617fbbc2012-11-27 11:02:00 -0200602 error_setg_errno(err, errno, "failed to open %s", mount->dirname);
Michael Rothe3d4d252011-07-19 15:41:55 -0500603 goto error;
604 }
605
606 /* we try to cull filesytems we know won't work in advance, but other
607 * filesytems may not implement fsfreeze for less obvious reasons.
Michael Roth9e8aded432012-04-16 19:52:17 -0500608 * these will report EOPNOTSUPP. we simply ignore these when tallying
609 * the number of frozen filesystems.
610 *
611 * any other error means a failure to freeze a filesystem we
612 * expect to be freezable, so return an error in those cases
613 * and return system to thawed state.
Michael Rothe3d4d252011-07-19 15:41:55 -0500614 */
615 ret = ioctl(fd, FIFREEZE);
Michael Roth9e8aded432012-04-16 19:52:17 -0500616 if (ret == -1) {
617 if (errno != EOPNOTSUPP) {
Luiz Capitulino617fbbc2012-11-27 11:02:00 -0200618 error_setg_errno(err, errno, "failed to freeze %s",
619 mount->dirname);
Michael Roth9e8aded432012-04-16 19:52:17 -0500620 close(fd);
621 goto error;
622 }
623 } else {
624 i++;
Michael Rothe3d4d252011-07-19 15:41:55 -0500625 }
626 close(fd);
Michael Rothe3d4d252011-07-19 15:41:55 -0500627 }
628
Paolo Bonziniaf022032012-06-13 07:41:27 +0200629 free_fs_mount_list(&mounts);
Michael Rothe3d4d252011-07-19 15:41:55 -0500630 return i;
631
632error:
Paolo Bonziniaf022032012-06-13 07:41:27 +0200633 free_fs_mount_list(&mounts);
Michael Roth9e8aded432012-04-16 19:52:17 -0500634 qmp_guest_fsfreeze_thaw(NULL);
Michael Rothe3d4d252011-07-19 15:41:55 -0500635 return 0;
636}
637
638/*
639 * Walk list of frozen file systems in the guest, and thaw them.
640 */
641int64_t qmp_guest_fsfreeze_thaw(Error **err)
642{
643 int ret;
Paolo Bonziniaf022032012-06-13 07:41:27 +0200644 FsMountList mounts;
645 FsMount *mount;
Michael Roth9e8aded432012-04-16 19:52:17 -0500646 int fd, i = 0, logged;
Luiz Capitulino261551d2012-11-29 15:29:11 -0200647 Error *local_err = NULL;
Michael Rothe3d4d252011-07-19 15:41:55 -0500648
Michael Roth9e8aded432012-04-16 19:52:17 -0500649 QTAILQ_INIT(&mounts);
Luiz Capitulino261551d2012-11-29 15:29:11 -0200650 build_fs_mount_list(&mounts, &local_err);
651 if (error_is_set(&local_err)) {
652 error_propagate(err, local_err);
Michael Roth9e8aded432012-04-16 19:52:17 -0500653 return 0;
654 }
655
656 QTAILQ_FOREACH(mount, &mounts, next) {
657 logged = false;
Michael Rothe3d4d252011-07-19 15:41:55 -0500658 fd = qemu_open(mount->dirname, O_RDONLY);
659 if (fd == -1) {
Michael Rothe3d4d252011-07-19 15:41:55 -0500660 continue;
661 }
Michael Roth9e8aded432012-04-16 19:52:17 -0500662 /* we have no way of knowing whether a filesystem was actually unfrozen
663 * as a result of a successful call to FITHAW, only that if an error
664 * was returned the filesystem was *not* unfrozen by that particular
665 * call.
666 *
Jim Meyeringa31f0532012-05-09 05:12:04 +0000667 * since multiple preceding FIFREEZEs require multiple calls to FITHAW
Michael Roth9e8aded432012-04-16 19:52:17 -0500668 * to unfreeze, continuing issuing FITHAW until an error is returned,
669 * in which case either the filesystem is in an unfreezable state, or,
670 * more likely, it was thawed previously (and remains so afterward).
671 *
672 * also, since the most recent successful call is the one that did
673 * the actual unfreeze, we can use this to provide an accurate count
674 * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which
675 * may * be useful for determining whether a filesystem was unfrozen
676 * during the freeze/thaw phase by a process other than qemu-ga.
677 */
678 do {
679 ret = ioctl(fd, FITHAW);
680 if (ret == 0 && !logged) {
681 i++;
682 logged = true;
683 }
684 } while (ret == 0);
Michael Rothe3d4d252011-07-19 15:41:55 -0500685 close(fd);
Michael Rothe3d4d252011-07-19 15:41:55 -0500686 }
687
Michael Rothf22d85e2012-04-17 19:01:45 -0500688 ga_unset_frozen(ga_state);
Paolo Bonziniaf022032012-06-13 07:41:27 +0200689 free_fs_mount_list(&mounts);
Tomoki Sekiyamaec0f6942012-12-12 12:55:55 +0900690
691 execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, err);
692
Michael Rothe3d4d252011-07-19 15:41:55 -0500693 return i;
694}
695
Michael Rothe3d4d252011-07-19 15:41:55 -0500696static void guest_fsfreeze_cleanup(void)
697{
Michael Rothe3d4d252011-07-19 15:41:55 -0500698 Error *err = NULL;
699
Michael Rothf22d85e2012-04-17 19:01:45 -0500700 if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) {
Markus Armbruster6f686742013-01-16 18:15:08 +0100701 qmp_guest_fsfreeze_thaw(&err);
702 if (err) {
703 slog("failed to clean up frozen filesystems: %s",
704 error_get_pretty(err));
705 error_free(err);
Michael Rothe3d4d252011-07-19 15:41:55 -0500706 }
707 }
708}
Michael Rothe72c3f22012-03-25 13:59:41 -0500709#endif /* CONFIG_FSFREEZE */
Michael Rothe3d4d252011-07-19 15:41:55 -0500710
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200711#if defined(CONFIG_FSTRIM)
712/*
713 * Walk list of mounted file systems in the guest, and trim them.
714 */
715void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
716{
717 int ret = 0;
718 FsMountList mounts;
719 struct FsMount *mount;
720 int fd;
Luiz Capitulino261551d2012-11-29 15:29:11 -0200721 Error *local_err = NULL;
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200722 struct fstrim_range r = {
723 .start = 0,
724 .len = -1,
725 .minlen = has_minimum ? minimum : 0,
726 };
727
728 slog("guest-fstrim called");
729
730 QTAILQ_INIT(&mounts);
Luiz Capitulino261551d2012-11-29 15:29:11 -0200731 build_fs_mount_list(&mounts, &local_err);
732 if (error_is_set(&local_err)) {
733 error_propagate(err, local_err);
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200734 return;
735 }
736
737 QTAILQ_FOREACH(mount, &mounts, next) {
738 fd = qemu_open(mount->dirname, O_RDONLY);
739 if (fd == -1) {
Luiz Capitulino071673b2012-11-27 11:02:01 -0200740 error_setg_errno(err, errno, "failed to open %s", mount->dirname);
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200741 goto error;
742 }
743
744 /* We try to cull filesytems we know won't work in advance, but other
745 * filesytems may not implement fstrim for less obvious reasons. These
746 * will report EOPNOTSUPP; we simply ignore these errors. Any other
747 * error means an unexpected error, so return it in those cases. In
748 * some other cases ENOTTY will be reported (e.g. CD-ROMs).
749 */
750 ret = ioctl(fd, FITRIM, &r);
751 if (ret == -1) {
752 if (errno != ENOTTY && errno != EOPNOTSUPP) {
Luiz Capitulino071673b2012-11-27 11:02:01 -0200753 error_setg_errno(err, errno, "failed to trim %s",
754 mount->dirname);
Paolo Bonzinieab5fd52012-06-13 07:41:28 +0200755 close(fd);
756 goto error;
757 }
758 }
759 close(fd);
760 }
761
762error:
763 free_fs_mount_list(&mounts);
764}
765#endif /* CONFIG_FSTRIM */
766
767
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300768#define LINUX_SYS_STATE_FILE "/sys/power/state"
769#define SUSPEND_SUPPORTED 0
770#define SUSPEND_NOT_SUPPORTED 1
771
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300772static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg,
773 const char *sysfile_str, Error **err)
774{
Luiz Capitulino6b26e832012-11-27 11:02:03 -0200775 Error *local_err = NULL;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300776 char *pmutils_path;
Luiz Capitulino6b26e832012-11-27 11:02:03 -0200777 pid_t pid;
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300778 int status;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300779
780 pmutils_path = g_find_program_in_path(pmutils_bin);
781
782 pid = fork();
783 if (!pid) {
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300784 char buf[32]; /* hopefully big enough */
785 ssize_t ret;
786 int fd;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300787
788 setsid();
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300789 reopen_fd_to_null(0);
790 reopen_fd_to_null(1);
791 reopen_fd_to_null(2);
792
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300793 if (pmutils_path) {
794 execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
795 }
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300796
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300797 /*
798 * If we get here either pm-utils is not installed or execle() has
799 * failed. Let's try the manual method if the caller wants it.
800 */
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300801
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300802 if (!sysfile_str) {
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300803 _exit(SUSPEND_NOT_SUPPORTED);
804 }
805
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300806 fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
807 if (fd < 0) {
808 _exit(SUSPEND_NOT_SUPPORTED);
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300809 }
810
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300811 ret = read(fd, buf, sizeof(buf)-1);
812 if (ret <= 0) {
813 _exit(SUSPEND_NOT_SUPPORTED);
814 }
815 buf[ret] = '\0';
816
817 if (strstr(buf, sysfile_str)) {
818 _exit(SUSPEND_SUPPORTED);
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300819 }
820
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300821 _exit(SUSPEND_NOT_SUPPORTED);
Luiz Capitulino6b26e832012-11-27 11:02:03 -0200822 } else if (pid < 0) {
823 error_setg_errno(err, errno, "failed to create child process");
824 goto out;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300825 }
826
Luiz Capitulino6b26e832012-11-27 11:02:03 -0200827 ga_wait_child(pid, &status, &local_err);
828 if (error_is_set(&local_err)) {
829 error_propagate(err, local_err);
830 goto out;
831 }
832
833 if (!WIFEXITED(status)) {
834 error_setg(err, "child process has terminated abnormally");
835 goto out;
836 }
837
838 switch (WEXITSTATUS(status)) {
839 case SUSPEND_SUPPORTED:
840 goto out;
841 case SUSPEND_NOT_SUPPORTED:
842 error_setg(err,
843 "the requested suspend mode is not supported by the guest");
844 goto out;
845 default:
846 error_setg(err,
847 "the helper program '%s' returned an unexpected exit status"
848 " code (%d)", pmutils_path, WEXITSTATUS(status));
849 goto out;
850 }
851
852out:
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300853 g_free(pmutils_path);
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300854}
855
856static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
857 Error **err)
858{
Luiz Capitulino7b376082012-11-27 11:02:04 -0200859 Error *local_err = NULL;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300860 char *pmutils_path;
Luiz Capitulino7b376082012-11-27 11:02:04 -0200861 pid_t pid;
Luiz Capitulinodc8764f02012-05-11 16:19:46 -0300862 int status;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300863
864 pmutils_path = g_find_program_in_path(pmutils_bin);
865
866 pid = fork();
867 if (pid == 0) {
868 /* child */
869 int fd;
870
871 setsid();
872 reopen_fd_to_null(0);
873 reopen_fd_to_null(1);
874 reopen_fd_to_null(2);
875
876 if (pmutils_path) {
877 execle(pmutils_path, pmutils_bin, NULL, environ);
878 }
879
880 /*
881 * If we get here either pm-utils is not installed or execle() has
882 * failed. Let's try the manual method if the caller wants it.
883 */
884
885 if (!sysfile_str) {
886 _exit(EXIT_FAILURE);
887 }
888
889 fd = open(LINUX_SYS_STATE_FILE, O_WRONLY);
890 if (fd < 0) {
891 _exit(EXIT_FAILURE);
892 }
893
894 if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) {
895 _exit(EXIT_FAILURE);
896 }
897
898 _exit(EXIT_SUCCESS);
Luiz Capitulino7b376082012-11-27 11:02:04 -0200899 } else if (pid < 0) {
900 error_setg_errno(err, errno, "failed to create child process");
901 goto out;
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300902 }
903
Luiz Capitulino7b376082012-11-27 11:02:04 -0200904 ga_wait_child(pid, &status, &local_err);
905 if (error_is_set(&local_err)) {
906 error_propagate(err, local_err);
907 goto out;
908 }
909
910 if (!WIFEXITED(status)) {
911 error_setg(err, "child process has terminated abnormally");
912 goto out;
913 }
914
915 if (WEXITSTATUS(status)) {
916 error_setg(err, "child process has failed to suspend");
917 goto out;
918 }
919
920out:
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300921 g_free(pmutils_path);
Luiz Capitulino11d0f122012-02-28 11:03:03 -0300922}
923
924void qmp_guest_suspend_disk(Error **err)
925{
926 bios_supports_mode("pm-is-supported", "--hibernate", "disk", err);
927 if (error_is_set(err)) {
928 return;
929 }
930
931 guest_suspend("pm-hibernate", "disk", err);
932}
933
Luiz Capitulinofbf42212012-02-28 11:03:04 -0300934void qmp_guest_suspend_ram(Error **err)
935{
936 bios_supports_mode("pm-is-supported", "--suspend", "mem", err);
937 if (error_is_set(err)) {
938 return;
939 }
940
941 guest_suspend("pm-suspend", "mem", err);
942}
943
Luiz Capitulino95f4f402012-02-28 11:03:05 -0300944void qmp_guest_suspend_hybrid(Error **err)
945{
946 bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL, err);
947 if (error_is_set(err)) {
948 return;
949 }
950
951 guest_suspend("pm-suspend-hybrid", NULL, err);
952}
953
Michal Privoznik3424fc92012-02-29 17:02:23 +0100954static GuestNetworkInterfaceList *
955guest_find_interface(GuestNetworkInterfaceList *head,
956 const char *name)
957{
958 for (; head; head = head->next) {
959 if (strcmp(head->value->name, name) == 0) {
960 break;
961 }
962 }
963
964 return head;
965}
966
967/*
968 * Build information about guest interfaces
969 */
970GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
971{
972 GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
973 struct ifaddrs *ifap, *ifa;
Michal Privoznik3424fc92012-02-29 17:02:23 +0100974
975 if (getifaddrs(&ifap) < 0) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -0200976 error_setg_errno(errp, errno, "getifaddrs failed");
Michal Privoznik3424fc92012-02-29 17:02:23 +0100977 goto error;
978 }
979
980 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
981 GuestNetworkInterfaceList *info;
982 GuestIpAddressList **address_list = NULL, *address_item = NULL;
983 char addr4[INET_ADDRSTRLEN];
984 char addr6[INET6_ADDRSTRLEN];
985 int sock;
986 struct ifreq ifr;
987 unsigned char *mac_addr;
988 void *p;
989
990 g_debug("Processing %s interface", ifa->ifa_name);
991
992 info = guest_find_interface(head, ifa->ifa_name);
993
994 if (!info) {
995 info = g_malloc0(sizeof(*info));
996 info->value = g_malloc0(sizeof(*info->value));
997 info->value->name = g_strdup(ifa->ifa_name);
998
999 if (!cur_item) {
1000 head = cur_item = info;
1001 } else {
1002 cur_item->next = info;
1003 cur_item = info;
1004 }
1005 }
1006
1007 if (!info->value->has_hardware_address &&
1008 ifa->ifa_flags & SIOCGIFHWADDR) {
1009 /* we haven't obtained HW address yet */
1010 sock = socket(PF_INET, SOCK_STREAM, 0);
1011 if (sock == -1) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -02001012 error_setg_errno(errp, errno, "failed to create socket");
Michal Privoznik3424fc92012-02-29 17:02:23 +01001013 goto error;
1014 }
1015
1016 memset(&ifr, 0, sizeof(ifr));
Jim Meyering1ab516e2012-10-04 13:09:58 +02001017 pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->value->name);
Michal Privoznik3424fc92012-02-29 17:02:23 +01001018 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -02001019 error_setg_errno(errp, errno,
1020 "failed to get MAC address of %s",
1021 ifa->ifa_name);
Markus Armbruster10a21582013-01-16 18:15:09 +01001022 close(sock);
Michal Privoznik3424fc92012-02-29 17:02:23 +01001023 goto error;
1024 }
1025
Markus Armbruster10a21582013-01-16 18:15:09 +01001026 close(sock);
Michal Privoznik3424fc92012-02-29 17:02:23 +01001027 mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
1028
Stefan Weile4ada482013-01-16 18:37:23 +01001029 info->value->hardware_address =
1030 g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x",
1031 (int) mac_addr[0], (int) mac_addr[1],
1032 (int) mac_addr[2], (int) mac_addr[3],
1033 (int) mac_addr[4], (int) mac_addr[5]);
Michal Privoznik3424fc92012-02-29 17:02:23 +01001034
1035 info->value->has_hardware_address = true;
Michal Privoznik3424fc92012-02-29 17:02:23 +01001036 }
1037
1038 if (ifa->ifa_addr &&
1039 ifa->ifa_addr->sa_family == AF_INET) {
1040 /* interface with IPv4 address */
Michal Privoznik3424fc92012-02-29 17:02:23 +01001041 p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
1042 if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -02001043 error_setg_errno(errp, errno, "inet_ntop failed");
Michal Privoznik3424fc92012-02-29 17:02:23 +01001044 goto error;
1045 }
1046
Markus Armbruster10a21582013-01-16 18:15:09 +01001047 address_item = g_malloc0(sizeof(*address_item));
1048 address_item->value = g_malloc0(sizeof(*address_item->value));
Michal Privoznik3424fc92012-02-29 17:02:23 +01001049 address_item->value->ip_address = g_strdup(addr4);
1050 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4;
1051
1052 if (ifa->ifa_netmask) {
1053 /* Count the number of set bits in netmask.
1054 * This is safe as '1' and '0' cannot be shuffled in netmask. */
1055 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;
1056 address_item->value->prefix = ctpop32(((uint32_t *) p)[0]);
1057 }
1058 } else if (ifa->ifa_addr &&
1059 ifa->ifa_addr->sa_family == AF_INET6) {
1060 /* interface with IPv6 address */
Michal Privoznik3424fc92012-02-29 17:02:23 +01001061 p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
1062 if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) {
Luiz Capitulino878a0ae2012-11-27 11:02:02 -02001063 error_setg_errno(errp, errno, "inet_ntop failed");
Michal Privoznik3424fc92012-02-29 17:02:23 +01001064 goto error;
1065 }
1066
Markus Armbruster10a21582013-01-16 18:15:09 +01001067 address_item = g_malloc0(sizeof(*address_item));
1068 address_item->value = g_malloc0(sizeof(*address_item->value));
Michal Privoznik3424fc92012-02-29 17:02:23 +01001069 address_item->value->ip_address = g_strdup(addr6);
1070 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6;
1071
1072 if (ifa->ifa_netmask) {
1073 /* Count the number of set bits in netmask.
1074 * This is safe as '1' and '0' cannot be shuffled in netmask. */
1075 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
1076 address_item->value->prefix =
1077 ctpop32(((uint32_t *) p)[0]) +
1078 ctpop32(((uint32_t *) p)[1]) +
1079 ctpop32(((uint32_t *) p)[2]) +
1080 ctpop32(((uint32_t *) p)[3]);
1081 }
1082 }
1083
1084 if (!address_item) {
1085 continue;
1086 }
1087
1088 address_list = &info->value->ip_addresses;
1089
1090 while (*address_list && (*address_list)->next) {
1091 address_list = &(*address_list)->next;
1092 }
1093
1094 if (!*address_list) {
1095 *address_list = address_item;
1096 } else {
1097 (*address_list)->next = address_item;
1098 }
1099
1100 info->value->has_ip_addresses = true;
1101
1102
1103 }
1104
1105 freeifaddrs(ifap);
1106 return head;
1107
1108error:
1109 freeifaddrs(ifap);
1110 qapi_free_GuestNetworkInterfaceList(head);
1111 return NULL;
1112}
1113
Michael Rothe72c3f22012-03-25 13:59:41 -05001114#else /* defined(__linux__) */
1115
Michael Rothe72c3f22012-03-25 13:59:41 -05001116void qmp_guest_suspend_disk(Error **err)
1117{
1118 error_set(err, QERR_UNSUPPORTED);
1119}
1120
1121void qmp_guest_suspend_ram(Error **err)
1122{
1123 error_set(err, QERR_UNSUPPORTED);
1124}
1125
1126void qmp_guest_suspend_hybrid(Error **err)
1127{
1128 error_set(err, QERR_UNSUPPORTED);
1129}
1130
1131GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
1132{
1133 error_set(errp, QERR_UNSUPPORTED);
1134 return NULL;
1135}
1136
1137#endif
1138
Michael Rothd35d4cb2012-04-13 21:07:36 -05001139#if !defined(CONFIG_FSFREEZE)
1140
1141GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
1142{
1143 error_set(err, QERR_UNSUPPORTED);
1144
1145 return 0;
1146}
1147
1148int64_t qmp_guest_fsfreeze_freeze(Error **err)
1149{
1150 error_set(err, QERR_UNSUPPORTED);
1151
1152 return 0;
1153}
1154
1155int64_t qmp_guest_fsfreeze_thaw(Error **err)
1156{
1157 error_set(err, QERR_UNSUPPORTED);
1158
1159 return 0;
1160}
Paolo Bonzinieab5fd52012-06-13 07:41:28 +02001161#endif /* CONFIG_FSFREEZE */
Michael Rothd35d4cb2012-04-13 21:07:36 -05001162
Paolo Bonzinieab5fd52012-06-13 07:41:28 +02001163#if !defined(CONFIG_FSTRIM)
1164void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
1165{
1166 error_set(err, QERR_UNSUPPORTED);
Paolo Bonzinieab5fd52012-06-13 07:41:28 +02001167}
Michael Rothd35d4cb2012-04-13 21:07:36 -05001168#endif
1169
Michael Rothe3d4d252011-07-19 15:41:55 -05001170/* register init/cleanup routines for stateful command groups */
1171void ga_command_state_init(GAState *s, GACommandState *cs)
1172{
Anthony Liguori7006b9c2011-07-22 14:14:17 -05001173#if defined(CONFIG_FSFREEZE)
Michael Rothf22d85e2012-04-17 19:01:45 -05001174 ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup);
Anthony Liguori7006b9c2011-07-22 14:14:17 -05001175#endif
Michael Rothe3d4d252011-07-19 15:41:55 -05001176 ga_command_state_add(cs, guest_file_init, NULL);
1177}