@@ -403,10 +403,12 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
}
QLIST_FOREACH(mon, &mon_list, entry) {
- if (monitor_ctrl_mode(mon)) {
+ if (monitor_ctrl_mode(mon) &&
+ mon->mc->mode == QMODE_OPERATIONAL) {
monitor_json_emitter(mon, QOBJECT(qmp));
}
}
+
QDECREF(qmp);
}
@@ -4242,12 +4244,34 @@ static int monitor_check_qmp_args(const mon_cmd_t *cmd, QDict *args)
return err;
}
+static int qmp_invalid_mode(const Monitor *mon, unsigned int cmd_flags)
+{
+ switch (mon->mc->mode) {
+ case QMODE_OPERATIONAL:
+ if (cmd_flags & HANDLER_HANDSHAKE_ONLY) {
+ return 1;
+ }
+ break;
+ case QMODE_HANDSHAKE:
+ if (!((cmd_flags & HANDLER_HANDSHAKE) ||
+ (cmd_flags & HANDLER_HANDSHAKE_ONLY))) {
+ return 1;
+ }
+ break;
+ default:
+ abort();
+ }
+
+ return 0;
+}
+
static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
{
int err;
QObject *obj;
QDict *input, *args;
const mon_cmd_t *cmd;
+ unsigned int cmd_flags;
Monitor *mon = cur_mon;
const char *cmd_name, *info_item;
@@ -4289,6 +4313,15 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
goto err_input;
} else if (strstart(cmd_name, "query-", &info_item)) {
+ /* check if it exists and get its flags */
+ cmd = monitor_find_info_command(info_item);
+ if (!cmd) {
+ qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
+ goto err_input;
+ }
+ cmd_flags = cmd->flags;
+
+ /* setup 'info' to call it */
cmd = monitor_find_command("info");
qdict_put_obj(input, "arguments",
qobject_from_jsonf("{ 'item': %s }", info_item));
@@ -4298,6 +4331,12 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
goto err_input;
}
+ cmd_flags = cmd->flags;
+ }
+
+ if (qmp_invalid_mode(mon, cmd_flags)) {
+ qemu_error_new(QERR_COMMAND_NOT_FOUND, cmd_name);
+ goto err_input;
}
obj = qdict_get(input, "arguments");
It's done by starting QMP in handshake mode, where (apart from a few exceptions) only commands to query/enable/disable protocol capabilities are allowed. Asynchronous messages are also disabled in this mode. Clients can change to the operational mode (where capabilities' changes take effect and most commands are allowed) at any time. When the issued command is not allowed to be executed on the running mode, QMP will return the CommandNotFound error, as suggested by Markus. All these changes should have no effect in the user Monitor. Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com> --- monitor.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 40 insertions(+), 1 deletions(-)