]> Git Repo - qemu.git/blob - qemu-ga.c
qemu-ga: add initial win32 support
[qemu.git] / qemu-ga.c
1 /*
2  * QEMU Guest Agent
3  *
4  * Copyright IBM Corp. 2011
5  *
6  * Authors:
7  *  Adam Litke        <[email protected]>
8  *  Michael Roth      <[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 #include <stdlib.h>
14 #include <stdio.h>
15 #include <stdbool.h>
16 #include <glib.h>
17 #include <getopt.h>
18 #ifndef _WIN32
19 #include <syslog.h>
20 #endif
21 #include "json-streamer.h"
22 #include "json-parser.h"
23 #include "qint.h"
24 #include "qjson.h"
25 #include "qga/guest-agent-core.h"
26 #include "module.h"
27 #include "signal.h"
28 #include "qerror.h"
29 #include "error_int.h"
30 #include "qapi/qmp-core.h"
31 #include "qga/channel.h"
32
33 #ifndef _WIN32
34 #define QGA_VIRTIO_PATH_DEFAULT "/dev/virtio-ports/org.qemu.guest_agent.0"
35 #else
36 #define QGA_VIRTIO_PATH_DEFAULT "\\\\.\\Global\\org.qemu.guest_agent.0"
37 #endif
38 #define QGA_PIDFILE_DEFAULT "/var/run/qemu-ga.pid"
39
40 struct GAState {
41     JSONMessageParser parser;
42     GMainLoop *main_loop;
43     GAChannel *channel;
44     bool virtio; /* fastpath to check for virtio to deal with poll() quirks */
45     GACommandState *command_state;
46     GLogLevelFlags log_level;
47     FILE *log_file;
48     bool logging_enabled;
49 };
50
51 static struct GAState *ga_state;
52
53 #ifndef _WIN32
54 static void quit_handler(int sig)
55 {
56     g_debug("received signal num %d, quitting", sig);
57
58     if (g_main_loop_is_running(ga_state->main_loop)) {
59         g_main_loop_quit(ga_state->main_loop);
60     }
61 }
62
63 static gboolean register_signal_handlers(void)
64 {
65     struct sigaction sigact;
66     int ret;
67
68     memset(&sigact, 0, sizeof(struct sigaction));
69     sigact.sa_handler = quit_handler;
70
71     ret = sigaction(SIGINT, &sigact, NULL);
72     if (ret == -1) {
73         g_error("error configuring signal handler: %s", strerror(errno));
74         return false;
75     }
76     ret = sigaction(SIGTERM, &sigact, NULL);
77     if (ret == -1) {
78         g_error("error configuring signal handler: %s", strerror(errno));
79         return false;
80     }
81     return true;
82 }
83 #endif
84
85 static void usage(const char *cmd)
86 {
87     printf(
88 "Usage: %s -c <channel_opts>\n"
89 "QEMU Guest Agent %s\n"
90 "\n"
91 "  -m, --method      transport method: one of unix-listen, virtio-serial, or\n"
92 "                    isa-serial (virtio-serial is the default)\n"
93 "  -p, --path        device/socket path (%s is the default for virtio-serial)\n"
94 "  -l, --logfile     set logfile path, logs to stderr by default\n"
95 "  -f, --pidfile     specify pidfile (default is %s)\n"
96 "  -v, --verbose     log extra debugging information\n"
97 "  -V, --version     print version information and exit\n"
98 #ifndef _WIN32
99 "  -d, --daemonize   become a daemon\n"
100 #endif
101 "  -b, --blacklist   comma-separated list of RPCs to disable (no spaces, \"?\""
102 "                    to list available RPCs)\n"
103 "  -h, --help        display this help and exit\n"
104 "\n"
105 "Report bugs to <[email protected]>\n"
106     , cmd, QGA_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT);
107 }
108
109 static const char *ga_log_level_str(GLogLevelFlags level)
110 {
111     switch (level & G_LOG_LEVEL_MASK) {
112         case G_LOG_LEVEL_ERROR:
113             return "error";
114         case G_LOG_LEVEL_CRITICAL:
115             return "critical";
116         case G_LOG_LEVEL_WARNING:
117             return "warning";
118         case G_LOG_LEVEL_MESSAGE:
119             return "message";
120         case G_LOG_LEVEL_INFO:
121             return "info";
122         case G_LOG_LEVEL_DEBUG:
123             return "debug";
124         default:
125             return "user";
126     }
127 }
128
129 bool ga_logging_enabled(GAState *s)
130 {
131     return s->logging_enabled;
132 }
133
134 void ga_disable_logging(GAState *s)
135 {
136     s->logging_enabled = false;
137 }
138
139 void ga_enable_logging(GAState *s)
140 {
141     s->logging_enabled = true;
142 }
143
144 static void ga_log(const gchar *domain, GLogLevelFlags level,
145                    const gchar *msg, gpointer opaque)
146 {
147     GAState *s = opaque;
148     GTimeVal time;
149     const char *level_str = ga_log_level_str(level);
150
151     if (!ga_logging_enabled(s)) {
152         return;
153     }
154
155     level &= G_LOG_LEVEL_MASK;
156 #ifndef _WIN32
157     if (domain && strcmp(domain, "syslog") == 0) {
158         syslog(LOG_INFO, "%s: %s", level_str, msg);
159     } else if (level & s->log_level) {
160 #else
161     if (level & s->log_level) {
162 #endif
163         g_get_current_time(&time);
164         fprintf(s->log_file,
165                 "%lu.%lu: %s: %s\n", time.tv_sec, time.tv_usec, level_str, msg);
166         fflush(s->log_file);
167     }
168 }
169
170 #ifndef _WIN32
171 static void become_daemon(const char *pidfile)
172 {
173     pid_t pid, sid;
174     int pidfd;
175     char *pidstr = NULL;
176
177     pid = fork();
178     if (pid < 0) {
179         exit(EXIT_FAILURE);
180     }
181     if (pid > 0) {
182         exit(EXIT_SUCCESS);
183     }
184
185     pidfd = open(pidfile, O_CREAT|O_WRONLY|O_EXCL, S_IRUSR|S_IWUSR);
186     if (pidfd == -1) {
187         g_critical("Cannot create pid file, %s", strerror(errno));
188         exit(EXIT_FAILURE);
189     }
190
191     if (asprintf(&pidstr, "%d", getpid()) == -1) {
192         g_critical("Cannot allocate memory");
193         goto fail;
194     }
195     if (write(pidfd, pidstr, strlen(pidstr)) != strlen(pidstr)) {
196         free(pidstr);
197         g_critical("Failed to write pid file");
198         goto fail;
199     }
200
201     umask(0);
202     sid = setsid();
203     if (sid < 0) {
204         goto fail;
205     }
206     if ((chdir("/")) < 0) {
207         goto fail;
208     }
209
210     close(STDIN_FILENO);
211     close(STDOUT_FILENO);
212     close(STDERR_FILENO);
213     free(pidstr);
214     return;
215
216 fail:
217     unlink(pidfile);
218     g_critical("failed to daemonize");
219     exit(EXIT_FAILURE);
220 }
221 #endif
222
223 static int send_response(GAState *s, QObject *payload)
224 {
225     const char *buf;
226     QString *payload_qstr;
227     GIOStatus status;
228
229     g_assert(payload && s->channel);
230
231     payload_qstr = qobject_to_json(payload);
232     if (!payload_qstr) {
233         return -EINVAL;
234     }
235
236     qstring_append_chr(payload_qstr, '\n');
237     buf = qstring_get_str(payload_qstr);
238     status = ga_channel_write_all(s->channel, buf, strlen(buf));
239     QDECREF(payload_qstr);
240     if (status != G_IO_STATUS_NORMAL) {
241         return -EIO;
242     }
243
244     return 0;
245 }
246
247 static void process_command(GAState *s, QDict *req)
248 {
249     QObject *rsp = NULL;
250     int ret;
251
252     g_assert(req);
253     g_debug("processing command");
254     rsp = qmp_dispatch(QOBJECT(req));
255     if (rsp) {
256         ret = send_response(s, rsp);
257         if (ret) {
258             g_warning("error sending response: %s", strerror(ret));
259         }
260         qobject_decref(rsp);
261     } else {
262         g_warning("error getting response");
263     }
264 }
265
266 /* handle requests/control events coming in over the channel */
267 static void process_event(JSONMessageParser *parser, QList *tokens)
268 {
269     GAState *s = container_of(parser, GAState, parser);
270     QObject *obj;
271     QDict *qdict;
272     Error *err = NULL;
273     int ret;
274
275     g_assert(s && parser);
276
277     g_debug("process_event: called");
278     obj = json_parser_parse_err(tokens, NULL, &err);
279     if (err || !obj || qobject_type(obj) != QTYPE_QDICT) {
280         qobject_decref(obj);
281         qdict = qdict_new();
282         if (!err) {
283             g_warning("failed to parse event: unknown error");
284             error_set(&err, QERR_JSON_PARSING);
285         } else {
286             g_warning("failed to parse event: %s", error_get_pretty(err));
287         }
288         qdict_put_obj(qdict, "error", error_get_qobject(err));
289         error_free(err);
290     } else {
291         qdict = qobject_to_qdict(obj);
292     }
293
294     g_assert(qdict);
295
296     /* handle host->guest commands */
297     if (qdict_haskey(qdict, "execute")) {
298         process_command(s, qdict);
299     } else {
300         if (!qdict_haskey(qdict, "error")) {
301             QDECREF(qdict);
302             qdict = qdict_new();
303             g_warning("unrecognized payload format");
304             error_set(&err, QERR_UNSUPPORTED);
305             qdict_put_obj(qdict, "error", error_get_qobject(err));
306             error_free(err);
307         }
308         ret = send_response(s, QOBJECT(qdict));
309         if (ret) {
310             g_warning("error sending error response: %s", strerror(ret));
311         }
312     }
313
314     QDECREF(qdict);
315 }
316
317 /* false return signals GAChannel to close the current client connection */
318 static gboolean channel_event_cb(GIOCondition condition, gpointer data)
319 {
320     GAState *s = data;
321     gchar buf[QGA_READ_COUNT_DEFAULT+1];
322     gsize count;
323     GError *err = NULL;
324     GIOStatus status = ga_channel_read(s->channel, buf, QGA_READ_COUNT_DEFAULT, &count);
325     if (err != NULL) {
326         g_warning("error reading channel: %s", err->message);
327         g_error_free(err);
328         return false;
329     }
330     switch (status) {
331     case G_IO_STATUS_ERROR:
332         g_warning("error reading channel");
333         return false;
334     case G_IO_STATUS_NORMAL:
335         buf[count] = 0;
336         g_debug("read data, count: %d, data: %s", (int)count, buf);
337         json_message_parser_feed(&s->parser, (char *)buf, (int)count);
338         break;
339     case G_IO_STATUS_EOF:
340         g_debug("received EOF");
341         if (!s->virtio) {
342             return false;
343         }
344     case G_IO_STATUS_AGAIN:
345         /* virtio causes us to spin here when no process is attached to
346          * host-side chardev. sleep a bit to mitigate this
347          */
348         if (s->virtio) {
349             usleep(100*1000);
350         }
351         return true;
352     default:
353         g_warning("unknown channel read status, closing");
354         return false;
355     }
356     return true;
357 }
358
359 static gboolean channel_init(GAState *s, const gchar *method, const gchar *path)
360 {
361     GAChannelMethod channel_method;
362
363     if (method == NULL) {
364         method = "virtio-serial";
365     }
366
367     if (path == NULL) {
368         if (strcmp(method, "virtio-serial") != 0) {
369             g_critical("must specify a path for this channel");
370             return false;
371         }
372         /* try the default path for the virtio-serial port */
373         path = QGA_VIRTIO_PATH_DEFAULT;
374     }
375
376     if (strcmp(method, "virtio-serial") == 0) {
377         s->virtio = true; /* virtio requires special handling in some cases */
378         channel_method = GA_CHANNEL_VIRTIO_SERIAL;
379     } else if (strcmp(method, "isa-serial") == 0) {
380         channel_method = GA_CHANNEL_ISA_SERIAL;
381     } else if (strcmp(method, "unix-listen") == 0) {
382         channel_method = GA_CHANNEL_UNIX_LISTEN;
383     } else {
384         g_critical("unsupported channel method/type: %s", method);
385         return false;
386     }
387
388     s->channel = ga_channel_new(channel_method, path, channel_event_cb, s);
389     if (!s->channel) {
390         g_critical("failed to create guest agent channel");
391         return false;
392     }
393
394     return true;
395 }
396
397 int main(int argc, char **argv)
398 {
399     const char *sopt = "hVvdm:p:l:f:b:";
400     const char *method = NULL, *path = NULL, *pidfile = QGA_PIDFILE_DEFAULT;
401     const struct option lopt[] = {
402         { "help", 0, NULL, 'h' },
403         { "version", 0, NULL, 'V' },
404         { "logfile", 0, NULL, 'l' },
405         { "pidfile", 0, NULL, 'f' },
406         { "verbose", 0, NULL, 'v' },
407         { "method", 0, NULL, 'm' },
408         { "path", 0, NULL, 'p' },
409         { "daemonize", 0, NULL, 'd' },
410         { "blacklist", 0, NULL, 'b' },
411         { NULL, 0, NULL, 0 }
412     };
413     int opt_ind = 0, ch, daemonize = 0, i, j, len;
414     GLogLevelFlags log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL;
415     FILE *log_file = stderr;
416     GAState *s;
417
418     module_call_init(MODULE_INIT_QAPI);
419
420     while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
421         switch (ch) {
422         case 'm':
423             method = optarg;
424             break;
425         case 'p':
426             path = optarg;
427             break;
428         case 'l':
429             log_file = fopen(optarg, "a");
430             if (!log_file) {
431                 g_critical("unable to open specified log file: %s",
432                            strerror(errno));
433                 return EXIT_FAILURE;
434             }
435             break;
436         case 'f':
437             pidfile = optarg;
438             break;
439         case 'v':
440             /* enable all log levels */
441             log_level = G_LOG_LEVEL_MASK;
442             break;
443         case 'V':
444             printf("QEMU Guest Agent %s\n", QGA_VERSION);
445             return 0;
446         case 'd':
447             daemonize = 1;
448             break;
449         case 'b': {
450             char **list_head, **list;
451             if (*optarg == '?') {
452                 list_head = list = qmp_get_command_list();
453                 while (*list != NULL) {
454                     printf("%s\n", *list);
455                     g_free(*list);
456                     list++;
457                 }
458                 g_free(list_head);
459                 return 0;
460             }
461             for (j = 0, i = 0, len = strlen(optarg); i < len; i++) {
462                 if (optarg[i] == ',') {
463                     optarg[i] = 0;
464                     qmp_disable_command(&optarg[j]);
465                     g_debug("disabling command: %s", &optarg[j]);
466                     j = i + 1;
467                 }
468             }
469             if (j < i) {
470                 qmp_disable_command(&optarg[j]);
471                 g_debug("disabling command: %s", &optarg[j]);
472             }
473             break;
474         }
475         case 'h':
476             usage(argv[0]);
477             return 0;
478         case '?':
479             g_print("Unknown option, try '%s --help' for more information.\n",
480                     argv[0]);
481             return EXIT_FAILURE;
482         }
483     }
484
485 #ifndef _WIN32
486     if (daemonize) {
487         g_debug("starting daemon");
488         become_daemon(pidfile);
489     }
490 #endif
491
492     s = g_malloc0(sizeof(GAState));
493     s->log_file = log_file;
494     s->log_level = log_level;
495     g_log_set_default_handler(ga_log, s);
496     g_log_set_fatal_mask(NULL, G_LOG_LEVEL_ERROR);
497     s->logging_enabled = true;
498     s->command_state = ga_command_state_new();
499     ga_command_state_init(s, s->command_state);
500     ga_command_state_init_all(s->command_state);
501     json_message_parser_init(&s->parser, process_event);
502     ga_state = s;
503 #ifndef _WIN32
504     if (!register_signal_handlers()) {
505         g_critical("failed to register signal handlers");
506         goto out_bad;
507     }
508 #endif
509
510     s->main_loop = g_main_loop_new(NULL, false);
511     if (!channel_init(ga_state, method, path)) {
512         g_critical("failed to initialize guest agent channel");
513         goto out_bad;
514     }
515     g_main_loop_run(ga_state->main_loop);
516
517     ga_command_state_cleanup_all(ga_state->command_state);
518     ga_channel_free(ga_state->channel);
519
520     if (daemonize) {
521         unlink(pidfile);
522     }
523     return 0;
524
525 out_bad:
526     if (daemonize) {
527         unlink(pidfile);
528     }
529     return EXIT_FAILURE;
530 }
This page took 0.053696 seconds and 4 git commands to generate.