Statistics
| Branch: | Revision:

root / qemu-ga.c @ fb5590f7

History | View | Annotate | Download (18.6 kB)

1 48ff7a62 Michael Roth
/*
2 48ff7a62 Michael Roth
 * QEMU Guest Agent
3 48ff7a62 Michael Roth
 *
4 48ff7a62 Michael Roth
 * Copyright IBM Corp. 2011
5 48ff7a62 Michael Roth
 *
6 48ff7a62 Michael Roth
 * Authors:
7 48ff7a62 Michael Roth
 *  Adam Litke        <aglitke@linux.vnet.ibm.com>
8 48ff7a62 Michael Roth
 *  Michael Roth      <mdroth@linux.vnet.ibm.com>
9 48ff7a62 Michael Roth
 *
10 48ff7a62 Michael Roth
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
11 48ff7a62 Michael Roth
 * See the COPYING file in the top-level directory.
12 48ff7a62 Michael Roth
 */
13 48ff7a62 Michael Roth
#include <stdlib.h>
14 48ff7a62 Michael Roth
#include <stdio.h>
15 48ff7a62 Michael Roth
#include <stdbool.h>
16 48ff7a62 Michael Roth
#include <glib.h>
17 48ff7a62 Michael Roth
#include <getopt.h>
18 48ff7a62 Michael Roth
#include <termios.h>
19 48ff7a62 Michael Roth
#include <syslog.h>
20 48ff7a62 Michael Roth
#include "qemu_socket.h"
21 48ff7a62 Michael Roth
#include "json-streamer.h"
22 48ff7a62 Michael Roth
#include "json-parser.h"
23 48ff7a62 Michael Roth
#include "qint.h"
24 48ff7a62 Michael Roth
#include "qjson.h"
25 48ff7a62 Michael Roth
#include "qga/guest-agent-core.h"
26 48ff7a62 Michael Roth
#include "module.h"
27 48ff7a62 Michael Roth
#include "signal.h"
28 48ff7a62 Michael Roth
#include "qerror.h"
29 48ff7a62 Michael Roth
#include "error_int.h"
30 abd6cf6d Michael Roth
#include "qapi/qmp-core.h"
31 48ff7a62 Michael Roth
32 48ff7a62 Michael Roth
#define QGA_VIRTIO_PATH_DEFAULT "/dev/virtio-ports/org.qemu.guest_agent.0"
33 48ff7a62 Michael Roth
#define QGA_PIDFILE_DEFAULT "/var/run/qemu-ga.pid"
34 48ff7a62 Michael Roth
#define QGA_BAUDRATE_DEFAULT B38400 /* for isa-serial channels */
35 48ff7a62 Michael Roth
#define QGA_TIMEOUT_DEFAULT 30*1000 /* ms */
36 48ff7a62 Michael Roth
37 48ff7a62 Michael Roth
struct GAState {
38 48ff7a62 Michael Roth
    JSONMessageParser parser;
39 48ff7a62 Michael Roth
    GMainLoop *main_loop;
40 48ff7a62 Michael Roth
    GIOChannel *conn_channel;
41 48ff7a62 Michael Roth
    GIOChannel *listen_channel;
42 48ff7a62 Michael Roth
    const char *path;
43 48ff7a62 Michael Roth
    const char *method;
44 48ff7a62 Michael Roth
    bool virtio; /* fastpath to check for virtio to deal with poll() quirks */
45 48ff7a62 Michael Roth
    GACommandState *command_state;
46 48ff7a62 Michael Roth
    GLogLevelFlags log_level;
47 48ff7a62 Michael Roth
    FILE *log_file;
48 48ff7a62 Michael Roth
    bool logging_enabled;
49 48ff7a62 Michael Roth
};
50 48ff7a62 Michael Roth
51 48ff7a62 Michael Roth
static struct GAState *ga_state;
52 48ff7a62 Michael Roth
53 48ff7a62 Michael Roth
static void quit_handler(int sig)
54 48ff7a62 Michael Roth
{
55 2542bfd5 Stefan Weil
    g_debug("received signal num %d, quitting", sig);
56 48ff7a62 Michael Roth
57 48ff7a62 Michael Roth
    if (g_main_loop_is_running(ga_state->main_loop)) {
58 48ff7a62 Michael Roth
        g_main_loop_quit(ga_state->main_loop);
59 48ff7a62 Michael Roth
    }
60 48ff7a62 Michael Roth
}
61 48ff7a62 Michael Roth
62 48ff7a62 Michael Roth
static void register_signal_handlers(void)
63 48ff7a62 Michael Roth
{
64 48ff7a62 Michael Roth
    struct sigaction sigact;
65 48ff7a62 Michael Roth
    int ret;
66 48ff7a62 Michael Roth
67 48ff7a62 Michael Roth
    memset(&sigact, 0, sizeof(struct sigaction));
68 48ff7a62 Michael Roth
    sigact.sa_handler = quit_handler;
69 48ff7a62 Michael Roth
70 48ff7a62 Michael Roth
    ret = sigaction(SIGINT, &sigact, NULL);
71 48ff7a62 Michael Roth
    if (ret == -1) {
72 48ff7a62 Michael Roth
        g_error("error configuring signal handler: %s", strerror(errno));
73 48ff7a62 Michael Roth
        exit(EXIT_FAILURE);
74 48ff7a62 Michael Roth
    }
75 48ff7a62 Michael Roth
    ret = sigaction(SIGTERM, &sigact, NULL);
76 48ff7a62 Michael Roth
    if (ret == -1) {
77 48ff7a62 Michael Roth
        g_error("error configuring signal handler: %s", strerror(errno));
78 48ff7a62 Michael Roth
    }
79 48ff7a62 Michael Roth
}
80 48ff7a62 Michael Roth
81 48ff7a62 Michael Roth
static void usage(const char *cmd)
82 48ff7a62 Michael Roth
{
83 48ff7a62 Michael Roth
    printf(
84 48ff7a62 Michael Roth
"Usage: %s -c <channel_opts>\n"
85 48ff7a62 Michael Roth
"QEMU Guest Agent %s\n"
86 48ff7a62 Michael Roth
"\n"
87 48ff7a62 Michael Roth
"  -m, --method      transport method: one of unix-listen, virtio-serial, or\n"
88 48ff7a62 Michael Roth
"                    isa-serial (virtio-serial is the default)\n"
89 48ff7a62 Michael Roth
"  -p, --path        device/socket path (%s is the default for virtio-serial)\n"
90 48ff7a62 Michael Roth
"  -l, --logfile     set logfile path, logs to stderr by default\n"
91 48ff7a62 Michael Roth
"  -f, --pidfile     specify pidfile (default is %s)\n"
92 48ff7a62 Michael Roth
"  -v, --verbose     log extra debugging information\n"
93 48ff7a62 Michael Roth
"  -V, --version     print version information and exit\n"
94 48ff7a62 Michael Roth
"  -d, --daemonize   become a daemon\n"
95 dabdf394 Stefan Weil
"  -b, --blacklist   comma-separated list of RPCs to disable (no spaces, \"?\""
96 abd6cf6d Michael Roth
"                    to list available RPCs)\n"
97 48ff7a62 Michael Roth
"  -h, --help        display this help and exit\n"
98 48ff7a62 Michael Roth
"\n"
99 48ff7a62 Michael Roth
"Report bugs to <mdroth@linux.vnet.ibm.com>\n"
100 48ff7a62 Michael Roth
    , cmd, QGA_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT);
101 48ff7a62 Michael Roth
}
102 48ff7a62 Michael Roth
103 48ff7a62 Michael Roth
static void conn_channel_close(GAState *s);
104 48ff7a62 Michael Roth
105 48ff7a62 Michael Roth
static const char *ga_log_level_str(GLogLevelFlags level)
106 48ff7a62 Michael Roth
{
107 48ff7a62 Michael Roth
    switch (level & G_LOG_LEVEL_MASK) {
108 48ff7a62 Michael Roth
        case G_LOG_LEVEL_ERROR:
109 48ff7a62 Michael Roth
            return "error";
110 48ff7a62 Michael Roth
        case G_LOG_LEVEL_CRITICAL:
111 48ff7a62 Michael Roth
            return "critical";
112 48ff7a62 Michael Roth
        case G_LOG_LEVEL_WARNING:
113 48ff7a62 Michael Roth
            return "warning";
114 48ff7a62 Michael Roth
        case G_LOG_LEVEL_MESSAGE:
115 48ff7a62 Michael Roth
            return "message";
116 48ff7a62 Michael Roth
        case G_LOG_LEVEL_INFO:
117 48ff7a62 Michael Roth
            return "info";
118 48ff7a62 Michael Roth
        case G_LOG_LEVEL_DEBUG:
119 48ff7a62 Michael Roth
            return "debug";
120 48ff7a62 Michael Roth
        default:
121 48ff7a62 Michael Roth
            return "user";
122 48ff7a62 Michael Roth
    }
123 48ff7a62 Michael Roth
}
124 48ff7a62 Michael Roth
125 48ff7a62 Michael Roth
bool ga_logging_enabled(GAState *s)
126 48ff7a62 Michael Roth
{
127 48ff7a62 Michael Roth
    return s->logging_enabled;
128 48ff7a62 Michael Roth
}
129 48ff7a62 Michael Roth
130 48ff7a62 Michael Roth
void ga_disable_logging(GAState *s)
131 48ff7a62 Michael Roth
{
132 48ff7a62 Michael Roth
    s->logging_enabled = false;
133 48ff7a62 Michael Roth
}
134 48ff7a62 Michael Roth
135 48ff7a62 Michael Roth
void ga_enable_logging(GAState *s)
136 48ff7a62 Michael Roth
{
137 48ff7a62 Michael Roth
    s->logging_enabled = true;
138 48ff7a62 Michael Roth
}
139 48ff7a62 Michael Roth
140 48ff7a62 Michael Roth
static void ga_log(const gchar *domain, GLogLevelFlags level,
141 48ff7a62 Michael Roth
                   const gchar *msg, gpointer opaque)
142 48ff7a62 Michael Roth
{
143 48ff7a62 Michael Roth
    GAState *s = opaque;
144 48ff7a62 Michael Roth
    GTimeVal time;
145 48ff7a62 Michael Roth
    const char *level_str = ga_log_level_str(level);
146 48ff7a62 Michael Roth
147 48ff7a62 Michael Roth
    if (!ga_logging_enabled(s)) {
148 48ff7a62 Michael Roth
        return;
149 48ff7a62 Michael Roth
    }
150 48ff7a62 Michael Roth
151 48ff7a62 Michael Roth
    level &= G_LOG_LEVEL_MASK;
152 8f477478 Michael Roth
    if (domain && strcmp(domain, "syslog") == 0) {
153 48ff7a62 Michael Roth
        syslog(LOG_INFO, "%s: %s", level_str, msg);
154 48ff7a62 Michael Roth
    } else if (level & s->log_level) {
155 48ff7a62 Michael Roth
        g_get_current_time(&time);
156 48ff7a62 Michael Roth
        fprintf(s->log_file,
157 48ff7a62 Michael Roth
                "%lu.%lu: %s: %s\n", time.tv_sec, time.tv_usec, level_str, msg);
158 48ff7a62 Michael Roth
        fflush(s->log_file);
159 48ff7a62 Michael Roth
    }
160 48ff7a62 Michael Roth
}
161 48ff7a62 Michael Roth
162 48ff7a62 Michael Roth
static void become_daemon(const char *pidfile)
163 48ff7a62 Michael Roth
{
164 48ff7a62 Michael Roth
    pid_t pid, sid;
165 48ff7a62 Michael Roth
    int pidfd;
166 48ff7a62 Michael Roth
    char *pidstr = NULL;
167 48ff7a62 Michael Roth
168 48ff7a62 Michael Roth
    pid = fork();
169 48ff7a62 Michael Roth
    if (pid < 0) {
170 48ff7a62 Michael Roth
        exit(EXIT_FAILURE);
171 48ff7a62 Michael Roth
    }
172 48ff7a62 Michael Roth
    if (pid > 0) {
173 48ff7a62 Michael Roth
        exit(EXIT_SUCCESS);
174 48ff7a62 Michael Roth
    }
175 48ff7a62 Michael Roth
176 48ff7a62 Michael Roth
    pidfd = open(pidfile, O_CREAT|O_WRONLY|O_EXCL, S_IRUSR|S_IWUSR);
177 48ff7a62 Michael Roth
    if (pidfd == -1) {
178 48ff7a62 Michael Roth
        g_critical("Cannot create pid file, %s", strerror(errno));
179 48ff7a62 Michael Roth
        exit(EXIT_FAILURE);
180 48ff7a62 Michael Roth
    }
181 48ff7a62 Michael Roth
182 48ff7a62 Michael Roth
    if (asprintf(&pidstr, "%d", getpid()) == -1) {
183 48ff7a62 Michael Roth
        g_critical("Cannot allocate memory");
184 48ff7a62 Michael Roth
        goto fail;
185 48ff7a62 Michael Roth
    }
186 48ff7a62 Michael Roth
    if (write(pidfd, pidstr, strlen(pidstr)) != strlen(pidstr)) {
187 48ff7a62 Michael Roth
        free(pidstr);
188 48ff7a62 Michael Roth
        g_critical("Failed to write pid file");
189 48ff7a62 Michael Roth
        goto fail;
190 48ff7a62 Michael Roth
    }
191 48ff7a62 Michael Roth
192 48ff7a62 Michael Roth
    umask(0);
193 48ff7a62 Michael Roth
    sid = setsid();
194 48ff7a62 Michael Roth
    if (sid < 0) {
195 48ff7a62 Michael Roth
        goto fail;
196 48ff7a62 Michael Roth
    }
197 48ff7a62 Michael Roth
    if ((chdir("/")) < 0) {
198 48ff7a62 Michael Roth
        goto fail;
199 48ff7a62 Michael Roth
    }
200 48ff7a62 Michael Roth
201 48ff7a62 Michael Roth
    close(STDIN_FILENO);
202 48ff7a62 Michael Roth
    close(STDOUT_FILENO);
203 48ff7a62 Michael Roth
    close(STDERR_FILENO);
204 48ff7a62 Michael Roth
    free(pidstr);
205 48ff7a62 Michael Roth
    return;
206 48ff7a62 Michael Roth
207 48ff7a62 Michael Roth
fail:
208 48ff7a62 Michael Roth
    unlink(pidfile);
209 48ff7a62 Michael Roth
    g_critical("failed to daemonize");
210 48ff7a62 Michael Roth
    exit(EXIT_FAILURE);
211 48ff7a62 Michael Roth
}
212 48ff7a62 Michael Roth
213 48ff7a62 Michael Roth
static int conn_channel_send_buf(GIOChannel *channel, const char *buf,
214 48ff7a62 Michael Roth
                                 gsize count)
215 48ff7a62 Michael Roth
{
216 48ff7a62 Michael Roth
    GError *err = NULL;
217 48ff7a62 Michael Roth
    gsize written = 0;
218 48ff7a62 Michael Roth
    GIOStatus status;
219 48ff7a62 Michael Roth
220 48ff7a62 Michael Roth
    while (count) {
221 48ff7a62 Michael Roth
        status = g_io_channel_write_chars(channel, buf, count, &written, &err);
222 48ff7a62 Michael Roth
        g_debug("sending data, count: %d", (int)count);
223 48ff7a62 Michael Roth
        if (err != NULL) {
224 48ff7a62 Michael Roth
            g_warning("error sending newline: %s", err->message);
225 48ff7a62 Michael Roth
            return err->code;
226 48ff7a62 Michael Roth
        }
227 48ff7a62 Michael Roth
        if (status == G_IO_STATUS_ERROR || status == G_IO_STATUS_EOF) {
228 48ff7a62 Michael Roth
            return -EPIPE;
229 48ff7a62 Michael Roth
        }
230 48ff7a62 Michael Roth
231 48ff7a62 Michael Roth
        if (status == G_IO_STATUS_NORMAL) {
232 48ff7a62 Michael Roth
            count -= written;
233 48ff7a62 Michael Roth
        }
234 48ff7a62 Michael Roth
    }
235 48ff7a62 Michael Roth
236 48ff7a62 Michael Roth
    return 0;
237 48ff7a62 Michael Roth
}
238 48ff7a62 Michael Roth
239 48ff7a62 Michael Roth
static int conn_channel_send_payload(GIOChannel *channel, QObject *payload)
240 48ff7a62 Michael Roth
{
241 48ff7a62 Michael Roth
    int ret = 0;
242 48ff7a62 Michael Roth
    const char *buf;
243 48ff7a62 Michael Roth
    QString *payload_qstr;
244 48ff7a62 Michael Roth
    GError *err = NULL;
245 48ff7a62 Michael Roth
246 48ff7a62 Michael Roth
    g_assert(payload && channel);
247 48ff7a62 Michael Roth
248 48ff7a62 Michael Roth
    payload_qstr = qobject_to_json(payload);
249 48ff7a62 Michael Roth
    if (!payload_qstr) {
250 48ff7a62 Michael Roth
        return -EINVAL;
251 48ff7a62 Michael Roth
    }
252 48ff7a62 Michael Roth
253 48ff7a62 Michael Roth
    qstring_append_chr(payload_qstr, '\n');
254 48ff7a62 Michael Roth
    buf = qstring_get_str(payload_qstr);
255 48ff7a62 Michael Roth
    ret = conn_channel_send_buf(channel, buf, strlen(buf));
256 48ff7a62 Michael Roth
    if (ret) {
257 48ff7a62 Michael Roth
        goto out_free;
258 48ff7a62 Michael Roth
    }
259 48ff7a62 Michael Roth
260 48ff7a62 Michael Roth
    g_io_channel_flush(channel, &err);
261 48ff7a62 Michael Roth
    if (err != NULL) {
262 48ff7a62 Michael Roth
        g_warning("error flushing payload: %s", err->message);
263 48ff7a62 Michael Roth
        ret = err->code;
264 48ff7a62 Michael Roth
        goto out_free;
265 48ff7a62 Michael Roth
    }
266 48ff7a62 Michael Roth
267 48ff7a62 Michael Roth
out_free:
268 48ff7a62 Michael Roth
    QDECREF(payload_qstr);
269 48ff7a62 Michael Roth
    if (err) {
270 48ff7a62 Michael Roth
        g_error_free(err);
271 48ff7a62 Michael Roth
    }
272 48ff7a62 Michael Roth
    return ret;
273 48ff7a62 Michael Roth
}
274 48ff7a62 Michael Roth
275 48ff7a62 Michael Roth
static void process_command(GAState *s, QDict *req)
276 48ff7a62 Michael Roth
{
277 48ff7a62 Michael Roth
    QObject *rsp = NULL;
278 48ff7a62 Michael Roth
    int ret;
279 48ff7a62 Michael Roth
280 48ff7a62 Michael Roth
    g_assert(req);
281 48ff7a62 Michael Roth
    g_debug("processing command");
282 48ff7a62 Michael Roth
    rsp = qmp_dispatch(QOBJECT(req));
283 48ff7a62 Michael Roth
    if (rsp) {
284 48ff7a62 Michael Roth
        ret = conn_channel_send_payload(s->conn_channel, rsp);
285 48ff7a62 Michael Roth
        if (ret) {
286 48ff7a62 Michael Roth
            g_warning("error sending payload: %s", strerror(ret));
287 48ff7a62 Michael Roth
        }
288 48ff7a62 Michael Roth
        qobject_decref(rsp);
289 48ff7a62 Michael Roth
    } else {
290 48ff7a62 Michael Roth
        g_warning("error getting response");
291 48ff7a62 Michael Roth
    }
292 48ff7a62 Michael Roth
}
293 48ff7a62 Michael Roth
294 48ff7a62 Michael Roth
/* handle requests/control events coming in over the channel */
295 48ff7a62 Michael Roth
static void process_event(JSONMessageParser *parser, QList *tokens)
296 48ff7a62 Michael Roth
{
297 48ff7a62 Michael Roth
    GAState *s = container_of(parser, GAState, parser);
298 48ff7a62 Michael Roth
    QObject *obj;
299 48ff7a62 Michael Roth
    QDict *qdict;
300 48ff7a62 Michael Roth
    Error *err = NULL;
301 48ff7a62 Michael Roth
    int ret;
302 48ff7a62 Michael Roth
303 48ff7a62 Michael Roth
    g_assert(s && parser);
304 48ff7a62 Michael Roth
305 48ff7a62 Michael Roth
    g_debug("process_event: called");
306 48ff7a62 Michael Roth
    obj = json_parser_parse_err(tokens, NULL, &err);
307 48ff7a62 Michael Roth
    if (err || !obj || qobject_type(obj) != QTYPE_QDICT) {
308 48ff7a62 Michael Roth
        qobject_decref(obj);
309 48ff7a62 Michael Roth
        qdict = qdict_new();
310 48ff7a62 Michael Roth
        if (!err) {
311 48ff7a62 Michael Roth
            g_warning("failed to parse event: unknown error");
312 48ff7a62 Michael Roth
            error_set(&err, QERR_JSON_PARSING);
313 48ff7a62 Michael Roth
        } else {
314 48ff7a62 Michael Roth
            g_warning("failed to parse event: %s", error_get_pretty(err));
315 48ff7a62 Michael Roth
        }
316 48ff7a62 Michael Roth
        qdict_put_obj(qdict, "error", error_get_qobject(err));
317 48ff7a62 Michael Roth
        error_free(err);
318 48ff7a62 Michael Roth
    } else {
319 48ff7a62 Michael Roth
        qdict = qobject_to_qdict(obj);
320 48ff7a62 Michael Roth
    }
321 48ff7a62 Michael Roth
322 48ff7a62 Michael Roth
    g_assert(qdict);
323 48ff7a62 Michael Roth
324 48ff7a62 Michael Roth
    /* handle host->guest commands */
325 48ff7a62 Michael Roth
    if (qdict_haskey(qdict, "execute")) {
326 48ff7a62 Michael Roth
        process_command(s, qdict);
327 48ff7a62 Michael Roth
    } else {
328 48ff7a62 Michael Roth
        if (!qdict_haskey(qdict, "error")) {
329 48ff7a62 Michael Roth
            QDECREF(qdict);
330 48ff7a62 Michael Roth
            qdict = qdict_new();
331 48ff7a62 Michael Roth
            g_warning("unrecognized payload format");
332 48ff7a62 Michael Roth
            error_set(&err, QERR_UNSUPPORTED);
333 48ff7a62 Michael Roth
            qdict_put_obj(qdict, "error", error_get_qobject(err));
334 48ff7a62 Michael Roth
            error_free(err);
335 48ff7a62 Michael Roth
        }
336 48ff7a62 Michael Roth
        ret = conn_channel_send_payload(s->conn_channel, QOBJECT(qdict));
337 48ff7a62 Michael Roth
        if (ret) {
338 48ff7a62 Michael Roth
            g_warning("error sending payload: %s", strerror(ret));
339 48ff7a62 Michael Roth
        }
340 48ff7a62 Michael Roth
    }
341 48ff7a62 Michael Roth
342 48ff7a62 Michael Roth
    QDECREF(qdict);
343 48ff7a62 Michael Roth
}
344 48ff7a62 Michael Roth
345 48ff7a62 Michael Roth
static gboolean conn_channel_read(GIOChannel *channel, GIOCondition condition,
346 48ff7a62 Michael Roth
                                  gpointer data)
347 48ff7a62 Michael Roth
{
348 48ff7a62 Michael Roth
    GAState *s = data;
349 48ff7a62 Michael Roth
    gchar buf[1024];
350 48ff7a62 Michael Roth
    gsize count;
351 48ff7a62 Michael Roth
    GError *err = NULL;
352 48ff7a62 Michael Roth
    memset(buf, 0, 1024);
353 48ff7a62 Michael Roth
    GIOStatus status = g_io_channel_read_chars(channel, buf, 1024,
354 48ff7a62 Michael Roth
                                               &count, &err);
355 48ff7a62 Michael Roth
    if (err != NULL) {
356 48ff7a62 Michael Roth
        g_warning("error reading channel: %s", err->message);
357 48ff7a62 Michael Roth
        conn_channel_close(s);
358 48ff7a62 Michael Roth
        g_error_free(err);
359 48ff7a62 Michael Roth
        return false;
360 48ff7a62 Michael Roth
    }
361 48ff7a62 Michael Roth
    switch (status) {
362 48ff7a62 Michael Roth
    case G_IO_STATUS_ERROR:
363 48ff7a62 Michael Roth
        g_warning("problem");
364 48ff7a62 Michael Roth
        return false;
365 48ff7a62 Michael Roth
    case G_IO_STATUS_NORMAL:
366 48ff7a62 Michael Roth
        g_debug("read data, count: %d, data: %s", (int)count, buf);
367 48ff7a62 Michael Roth
        json_message_parser_feed(&s->parser, (char *)buf, (int)count);
368 48ff7a62 Michael Roth
    case G_IO_STATUS_AGAIN:
369 48ff7a62 Michael Roth
        /* virtio causes us to spin here when no process is attached to
370 48ff7a62 Michael Roth
         * host-side chardev. sleep a bit to mitigate this
371 48ff7a62 Michael Roth
         */
372 48ff7a62 Michael Roth
        if (s->virtio) {
373 48ff7a62 Michael Roth
            usleep(100*1000);
374 48ff7a62 Michael Roth
        }
375 48ff7a62 Michael Roth
        return true;
376 48ff7a62 Michael Roth
    case G_IO_STATUS_EOF:
377 48ff7a62 Michael Roth
        g_debug("received EOF");
378 48ff7a62 Michael Roth
        conn_channel_close(s);
379 48ff7a62 Michael Roth
        if (s->virtio) {
380 48ff7a62 Michael Roth
            return true;
381 48ff7a62 Michael Roth
        }
382 48ff7a62 Michael Roth
        return false;
383 48ff7a62 Michael Roth
    default:
384 48ff7a62 Michael Roth
        g_warning("unknown channel read status, closing");
385 48ff7a62 Michael Roth
        conn_channel_close(s);
386 48ff7a62 Michael Roth
        return false;
387 48ff7a62 Michael Roth
    }
388 48ff7a62 Michael Roth
    return true;
389 48ff7a62 Michael Roth
}
390 48ff7a62 Michael Roth
391 48ff7a62 Michael Roth
static int conn_channel_add(GAState *s, int fd)
392 48ff7a62 Michael Roth
{
393 48ff7a62 Michael Roth
    GIOChannel *conn_channel;
394 48ff7a62 Michael Roth
    GError *err = NULL;
395 48ff7a62 Michael Roth
396 48ff7a62 Michael Roth
    g_assert(s && !s->conn_channel);
397 48ff7a62 Michael Roth
    conn_channel = g_io_channel_unix_new(fd);
398 48ff7a62 Michael Roth
    g_assert(conn_channel);
399 48ff7a62 Michael Roth
    g_io_channel_set_encoding(conn_channel, NULL, &err);
400 48ff7a62 Michael Roth
    if (err != NULL) {
401 48ff7a62 Michael Roth
        g_warning("error setting channel encoding to binary");
402 48ff7a62 Michael Roth
        g_error_free(err);
403 48ff7a62 Michael Roth
        return -1;
404 48ff7a62 Michael Roth
    }
405 48ff7a62 Michael Roth
    g_io_add_watch(conn_channel, G_IO_IN | G_IO_HUP,
406 48ff7a62 Michael Roth
                   conn_channel_read, s);
407 48ff7a62 Michael Roth
    s->conn_channel = conn_channel;
408 48ff7a62 Michael Roth
    return 0;
409 48ff7a62 Michael Roth
}
410 48ff7a62 Michael Roth
411 48ff7a62 Michael Roth
static gboolean listen_channel_accept(GIOChannel *channel,
412 48ff7a62 Michael Roth
                                      GIOCondition condition, gpointer data)
413 48ff7a62 Michael Roth
{
414 48ff7a62 Michael Roth
    GAState *s = data;
415 48ff7a62 Michael Roth
    g_assert(channel != NULL);
416 1fc7bd4a Anthony Liguori
    int ret, conn_fd;
417 48ff7a62 Michael Roth
    bool accepted = false;
418 1fc7bd4a Anthony Liguori
    struct sockaddr_un addr;
419 1fc7bd4a Anthony Liguori
    socklen_t addrlen = sizeof(addr);
420 48ff7a62 Michael Roth
421 1fc7bd4a Anthony Liguori
    conn_fd = qemu_accept(g_io_channel_unix_get_fd(s->listen_channel),
422 1fc7bd4a Anthony Liguori
                             (struct sockaddr *)&addr, &addrlen);
423 1fc7bd4a Anthony Liguori
    if (conn_fd == -1) {
424 1fc7bd4a Anthony Liguori
        g_warning("error converting fd to gsocket: %s", strerror(errno));
425 48ff7a62 Michael Roth
        goto out;
426 48ff7a62 Michael Roth
    }
427 1fc7bd4a Anthony Liguori
    fcntl(conn_fd, F_SETFL, O_NONBLOCK);
428 1fc7bd4a Anthony Liguori
    ret = conn_channel_add(s, conn_fd);
429 48ff7a62 Michael Roth
    if (ret) {
430 48ff7a62 Michael Roth
        g_warning("error setting up connection");
431 48ff7a62 Michael Roth
        goto out;
432 48ff7a62 Michael Roth
    }
433 48ff7a62 Michael Roth
    accepted = true;
434 48ff7a62 Michael Roth
435 48ff7a62 Michael Roth
out:
436 48ff7a62 Michael Roth
    /* only accept 1 connection at a time */
437 48ff7a62 Michael Roth
    return !accepted;
438 48ff7a62 Michael Roth
}
439 48ff7a62 Michael Roth
440 48ff7a62 Michael Roth
/* start polling for readable events on listen fd, new==true
441 48ff7a62 Michael Roth
 * indicates we should use the existing s->listen_channel
442 48ff7a62 Michael Roth
 */
443 48ff7a62 Michael Roth
static int listen_channel_add(GAState *s, int listen_fd, bool new)
444 48ff7a62 Michael Roth
{
445 48ff7a62 Michael Roth
    if (new) {
446 48ff7a62 Michael Roth
        s->listen_channel = g_io_channel_unix_new(listen_fd);
447 48ff7a62 Michael Roth
    }
448 48ff7a62 Michael Roth
    g_io_add_watch(s->listen_channel, G_IO_IN,
449 48ff7a62 Michael Roth
                   listen_channel_accept, s);
450 48ff7a62 Michael Roth
    return 0;
451 48ff7a62 Michael Roth
}
452 48ff7a62 Michael Roth
453 48ff7a62 Michael Roth
/* cleanup state for closed connection/session, start accepting new
454 48ff7a62 Michael Roth
 * connections if we're in listening mode
455 48ff7a62 Michael Roth
 */
456 48ff7a62 Michael Roth
static void conn_channel_close(GAState *s)
457 48ff7a62 Michael Roth
{
458 48ff7a62 Michael Roth
    if (strcmp(s->method, "unix-listen") == 0) {
459 48ff7a62 Michael Roth
        g_io_channel_shutdown(s->conn_channel, true, NULL);
460 48ff7a62 Michael Roth
        listen_channel_add(s, 0, false);
461 48ff7a62 Michael Roth
    } else if (strcmp(s->method, "virtio-serial") == 0) {
462 48ff7a62 Michael Roth
        /* we spin on EOF for virtio-serial, so back off a bit. also,
463 48ff7a62 Michael Roth
         * dont close the connection in this case, it'll resume normal
464 48ff7a62 Michael Roth
         * operation when another process connects to host chardev
465 48ff7a62 Michael Roth
         */
466 48ff7a62 Michael Roth
        usleep(100*1000);
467 48ff7a62 Michael Roth
        goto out_noclose;
468 48ff7a62 Michael Roth
    }
469 48ff7a62 Michael Roth
    g_io_channel_unref(s->conn_channel);
470 48ff7a62 Michael Roth
    s->conn_channel = NULL;
471 48ff7a62 Michael Roth
out_noclose:
472 48ff7a62 Michael Roth
    return;
473 48ff7a62 Michael Roth
}
474 48ff7a62 Michael Roth
475 48ff7a62 Michael Roth
static void init_guest_agent(GAState *s)
476 48ff7a62 Michael Roth
{
477 48ff7a62 Michael Roth
    struct termios tio;
478 48ff7a62 Michael Roth
    int ret, fd;
479 48ff7a62 Michael Roth
480 48ff7a62 Michael Roth
    if (s->method == NULL) {
481 48ff7a62 Michael Roth
        /* try virtio-serial as our default */
482 48ff7a62 Michael Roth
        s->method = "virtio-serial";
483 48ff7a62 Michael Roth
    }
484 48ff7a62 Michael Roth
485 48ff7a62 Michael Roth
    if (s->path == NULL) {
486 48ff7a62 Michael Roth
        if (strcmp(s->method, "virtio-serial") != 0) {
487 48ff7a62 Michael Roth
            g_critical("must specify a path for this channel");
488 48ff7a62 Michael Roth
            exit(EXIT_FAILURE);
489 48ff7a62 Michael Roth
        }
490 48ff7a62 Michael Roth
        /* try the default path for the virtio-serial port */
491 48ff7a62 Michael Roth
        s->path = QGA_VIRTIO_PATH_DEFAULT;
492 48ff7a62 Michael Roth
    }
493 48ff7a62 Michael Roth
494 48ff7a62 Michael Roth
    if (strcmp(s->method, "virtio-serial") == 0) {
495 48ff7a62 Michael Roth
        s->virtio = true;
496 48ff7a62 Michael Roth
        fd = qemu_open(s->path, O_RDWR | O_NONBLOCK | O_ASYNC);
497 48ff7a62 Michael Roth
        if (fd == -1) {
498 48ff7a62 Michael Roth
            g_critical("error opening channel: %s", strerror(errno));
499 48ff7a62 Michael Roth
            exit(EXIT_FAILURE);
500 48ff7a62 Michael Roth
        }
501 48ff7a62 Michael Roth
        ret = conn_channel_add(s, fd);
502 48ff7a62 Michael Roth
        if (ret) {
503 48ff7a62 Michael Roth
            g_critical("error adding channel to main loop");
504 48ff7a62 Michael Roth
            exit(EXIT_FAILURE);
505 48ff7a62 Michael Roth
        }
506 48ff7a62 Michael Roth
    } else if (strcmp(s->method, "isa-serial") == 0) {
507 48ff7a62 Michael Roth
        fd = qemu_open(s->path, O_RDWR | O_NOCTTY);
508 48ff7a62 Michael Roth
        if (fd == -1) {
509 48ff7a62 Michael Roth
            g_critical("error opening channel: %s", strerror(errno));
510 48ff7a62 Michael Roth
            exit(EXIT_FAILURE);
511 48ff7a62 Michael Roth
        }
512 48ff7a62 Michael Roth
        tcgetattr(fd, &tio);
513 48ff7a62 Michael Roth
        /* set up serial port for non-canonical, dumb byte streaming */
514 48ff7a62 Michael Roth
        tio.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP |
515 48ff7a62 Michael Roth
                         INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY |
516 48ff7a62 Michael Roth
                         IMAXBEL);
517 48ff7a62 Michael Roth
        tio.c_oflag = 0;
518 48ff7a62 Michael Roth
        tio.c_lflag = 0;
519 48ff7a62 Michael Roth
        tio.c_cflag |= QGA_BAUDRATE_DEFAULT;
520 48ff7a62 Michael Roth
        /* 1 available byte min or reads will block (we'll set non-blocking
521 48ff7a62 Michael Roth
         * elsewhere, else we have to deal with read()=0 instead)
522 48ff7a62 Michael Roth
         */
523 48ff7a62 Michael Roth
        tio.c_cc[VMIN] = 1;
524 48ff7a62 Michael Roth
        tio.c_cc[VTIME] = 0;
525 48ff7a62 Michael Roth
        /* flush everything waiting for read/xmit, it's garbage at this point */
526 48ff7a62 Michael Roth
        tcflush(fd, TCIFLUSH);
527 48ff7a62 Michael Roth
        tcsetattr(fd, TCSANOW, &tio);
528 48ff7a62 Michael Roth
        ret = conn_channel_add(s, fd);
529 48ff7a62 Michael Roth
        if (ret) {
530 48ff7a62 Michael Roth
            g_error("error adding channel to main loop");
531 48ff7a62 Michael Roth
        }
532 48ff7a62 Michael Roth
    } else if (strcmp(s->method, "unix-listen") == 0) {
533 48ff7a62 Michael Roth
        fd = unix_listen(s->path, NULL, strlen(s->path));
534 48ff7a62 Michael Roth
        if (fd == -1) {
535 48ff7a62 Michael Roth
            g_critical("error opening path: %s", strerror(errno));
536 48ff7a62 Michael Roth
            exit(EXIT_FAILURE);
537 48ff7a62 Michael Roth
        }
538 48ff7a62 Michael Roth
        ret = listen_channel_add(s, fd, true);
539 48ff7a62 Michael Roth
        if (ret) {
540 48ff7a62 Michael Roth
            g_critical("error binding/listening to specified socket");
541 48ff7a62 Michael Roth
            exit(EXIT_FAILURE);
542 48ff7a62 Michael Roth
        }
543 48ff7a62 Michael Roth
    } else {
544 48ff7a62 Michael Roth
        g_critical("unsupported channel method/type: %s", s->method);
545 48ff7a62 Michael Roth
        exit(EXIT_FAILURE);
546 48ff7a62 Michael Roth
    }
547 48ff7a62 Michael Roth
548 48ff7a62 Michael Roth
    json_message_parser_init(&s->parser, process_event);
549 48ff7a62 Michael Roth
    s->main_loop = g_main_loop_new(NULL, false);
550 48ff7a62 Michael Roth
}
551 48ff7a62 Michael Roth
552 48ff7a62 Michael Roth
int main(int argc, char **argv)
553 48ff7a62 Michael Roth
{
554 abd6cf6d Michael Roth
    const char *sopt = "hVvdm:p:l:f:b:";
555 48ff7a62 Michael Roth
    const char *method = NULL, *path = NULL, *pidfile = QGA_PIDFILE_DEFAULT;
556 48ff7a62 Michael Roth
    const struct option lopt[] = {
557 48ff7a62 Michael Roth
        { "help", 0, NULL, 'h' },
558 48ff7a62 Michael Roth
        { "version", 0, NULL, 'V' },
559 48ff7a62 Michael Roth
        { "logfile", 0, NULL, 'l' },
560 48ff7a62 Michael Roth
        { "pidfile", 0, NULL, 'f' },
561 48ff7a62 Michael Roth
        { "verbose", 0, NULL, 'v' },
562 48ff7a62 Michael Roth
        { "method", 0, NULL, 'm' },
563 48ff7a62 Michael Roth
        { "path", 0, NULL, 'p' },
564 48ff7a62 Michael Roth
        { "daemonize", 0, NULL, 'd' },
565 abd6cf6d Michael Roth
        { "blacklist", 0, NULL, 'b' },
566 48ff7a62 Michael Roth
        { NULL, 0, NULL, 0 }
567 48ff7a62 Michael Roth
    };
568 abd6cf6d Michael Roth
    int opt_ind = 0, ch, daemonize = 0, i, j, len;
569 48ff7a62 Michael Roth
    GLogLevelFlags log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL;
570 48ff7a62 Michael Roth
    FILE *log_file = stderr;
571 48ff7a62 Michael Roth
    GAState *s;
572 48ff7a62 Michael Roth
573 abd6cf6d Michael Roth
    module_call_init(MODULE_INIT_QAPI);
574 abd6cf6d Michael Roth
575 48ff7a62 Michael Roth
    while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
576 48ff7a62 Michael Roth
        switch (ch) {
577 48ff7a62 Michael Roth
        case 'm':
578 48ff7a62 Michael Roth
            method = optarg;
579 48ff7a62 Michael Roth
            break;
580 48ff7a62 Michael Roth
        case 'p':
581 48ff7a62 Michael Roth
            path = optarg;
582 48ff7a62 Michael Roth
            break;
583 48ff7a62 Michael Roth
        case 'l':
584 48ff7a62 Michael Roth
            log_file = fopen(optarg, "a");
585 48ff7a62 Michael Roth
            if (!log_file) {
586 48ff7a62 Michael Roth
                g_critical("unable to open specified log file: %s",
587 48ff7a62 Michael Roth
                           strerror(errno));
588 48ff7a62 Michael Roth
                return EXIT_FAILURE;
589 48ff7a62 Michael Roth
            }
590 48ff7a62 Michael Roth
            break;
591 48ff7a62 Michael Roth
        case 'f':
592 48ff7a62 Michael Roth
            pidfile = optarg;
593 48ff7a62 Michael Roth
            break;
594 48ff7a62 Michael Roth
        case 'v':
595 48ff7a62 Michael Roth
            /* enable all log levels */
596 48ff7a62 Michael Roth
            log_level = G_LOG_LEVEL_MASK;
597 48ff7a62 Michael Roth
            break;
598 48ff7a62 Michael Roth
        case 'V':
599 48ff7a62 Michael Roth
            printf("QEMU Guest Agent %s\n", QGA_VERSION);
600 48ff7a62 Michael Roth
            return 0;
601 48ff7a62 Michael Roth
        case 'd':
602 48ff7a62 Michael Roth
            daemonize = 1;
603 48ff7a62 Michael Roth
            break;
604 abd6cf6d Michael Roth
        case 'b': {
605 abd6cf6d Michael Roth
            char **list_head, **list;
606 abd6cf6d Michael Roth
            if (*optarg == '?') {
607 abd6cf6d Michael Roth
                list_head = list = qmp_get_command_list();
608 abd6cf6d Michael Roth
                while (*list != NULL) {
609 abd6cf6d Michael Roth
                    printf("%s\n", *list);
610 abd6cf6d Michael Roth
                    g_free(*list);
611 abd6cf6d Michael Roth
                    list++;
612 abd6cf6d Michael Roth
                }
613 abd6cf6d Michael Roth
                g_free(list_head);
614 abd6cf6d Michael Roth
                return 0;
615 abd6cf6d Michael Roth
            }
616 abd6cf6d Michael Roth
            for (j = 0, i = 0, len = strlen(optarg); i < len; i++) {
617 abd6cf6d Michael Roth
                if (optarg[i] == ',') {
618 abd6cf6d Michael Roth
                    optarg[i] = 0;
619 abd6cf6d Michael Roth
                    qmp_disable_command(&optarg[j]);
620 abd6cf6d Michael Roth
                    g_debug("disabling command: %s", &optarg[j]);
621 abd6cf6d Michael Roth
                    j = i + 1;
622 abd6cf6d Michael Roth
                }
623 abd6cf6d Michael Roth
            }
624 abd6cf6d Michael Roth
            if (j < i) {
625 abd6cf6d Michael Roth
                qmp_disable_command(&optarg[j]);
626 abd6cf6d Michael Roth
                g_debug("disabling command: %s", &optarg[j]);
627 abd6cf6d Michael Roth
            }
628 abd6cf6d Michael Roth
            break;
629 abd6cf6d Michael Roth
        }
630 48ff7a62 Michael Roth
        case 'h':
631 48ff7a62 Michael Roth
            usage(argv[0]);
632 48ff7a62 Michael Roth
            return 0;
633 48ff7a62 Michael Roth
        case '?':
634 48ff7a62 Michael Roth
            g_print("Unknown option, try '%s --help' for more information.\n",
635 48ff7a62 Michael Roth
                    argv[0]);
636 48ff7a62 Michael Roth
            return EXIT_FAILURE;
637 48ff7a62 Michael Roth
        }
638 48ff7a62 Michael Roth
    }
639 48ff7a62 Michael Roth
640 48ff7a62 Michael Roth
    if (daemonize) {
641 48ff7a62 Michael Roth
        g_debug("starting daemon");
642 48ff7a62 Michael Roth
        become_daemon(pidfile);
643 48ff7a62 Michael Roth
    }
644 48ff7a62 Michael Roth
645 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(GAState));
646 48ff7a62 Michael Roth
    s->conn_channel = NULL;
647 48ff7a62 Michael Roth
    s->path = path;
648 48ff7a62 Michael Roth
    s->method = method;
649 48ff7a62 Michael Roth
    s->log_file = log_file;
650 48ff7a62 Michael Roth
    s->log_level = log_level;
651 48ff7a62 Michael Roth
    g_log_set_default_handler(ga_log, s);
652 48ff7a62 Michael Roth
    g_log_set_fatal_mask(NULL, G_LOG_LEVEL_ERROR);
653 48ff7a62 Michael Roth
    s->logging_enabled = true;
654 e3d4d252 Michael Roth
    s->command_state = ga_command_state_new();
655 e3d4d252 Michael Roth
    ga_command_state_init(s, s->command_state);
656 e3d4d252 Michael Roth
    ga_command_state_init_all(s->command_state);
657 48ff7a62 Michael Roth
    ga_state = s;
658 48ff7a62 Michael Roth
659 48ff7a62 Michael Roth
    init_guest_agent(ga_state);
660 48ff7a62 Michael Roth
    register_signal_handlers();
661 48ff7a62 Michael Roth
662 48ff7a62 Michael Roth
    g_main_loop_run(ga_state->main_loop);
663 48ff7a62 Michael Roth
664 e3d4d252 Michael Roth
    ga_command_state_cleanup_all(ga_state->command_state);
665 48ff7a62 Michael Roth
    unlink(pidfile);
666 48ff7a62 Michael Roth
667 48ff7a62 Michael Roth
    return 0;
668 48ff7a62 Michael Roth
}