Separate the decoding of incoming request header out from the dispatch code. This will allow later code to making dispatcher routing decisions based on the header field data. * qemud/dispatch.c, qemud/dispatch.h: Add remoteDecodeClientMessageHeader API for decoding the header of a client message. Update the remoteDispatchClientRequest method to assume a pre-decoded header. * qemud/qemud.h: Include a 'remote_message_header' field in 'struct qemud_client_message' for pre-decoded header data * qemud/qemud.c: Decode the incoming client message header before invoking remoteDispatchClientRequest Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- qemud/dispatch.c | 96 ++++++++++++++++++++++++++++++++++++----------------- qemud/dispatch.h | 3 ++ qemud/qemud.c | 3 +- qemud/qemud.h | 2 + 4 files changed, 72 insertions(+), 32 deletions(-) diff --git a/qemud/dispatch.c b/qemud/dispatch.c index d2338fb..127f93b 100644 --- a/qemud/dispatch.c +++ b/qemud/dispatch.c @@ -124,13 +124,50 @@ void remoteDispatchConnError (remote_error *rerr, /* + * @msg: the complete incoming message, whose header to decode + * + * Decodes the header part of the client message, but does not + * validate the decoded fields in the header. + * + * returns 0 if successfully decoded, -1 upon fatal error + */ +int +remoteDecodeClientMessageHeader (struct qemud_client_message *msg) +{ + XDR xdr; + int ret = -1; + + msg->bufferOffset = REMOTE_MESSAGE_HEADER_XDR_LEN; + + /* Parse the header. */ + xdrmem_create (&xdr, + msg->buffer + msg->bufferOffset, + msg->bufferLength - msg->bufferOffset, + XDR_DECODE); + + if (!xdr_remote_message_header (&xdr, &msg->hdr)) + goto cleanup; + + msg->bufferOffset += xdr_getpos(&xdr); + + ret = 0; + +cleanup: + xdr_destroy(&xdr); + return ret; +} + + +/* * @server: the unlocked server object * @client: the locked client object - * @msg: the complete incoming message packet + * @msg: the complete incoming message packet, with header already decoded * * This function gets called from qemud when it pulls a incoming * remote protocol messsage off the dispatch queue for processing. * + * The @msg parameter must have had its header decoded already by + * calling remoteDecodeClientMessageHeader * * Returns 0 if the message was dispatched, -1 upon fatal error */ @@ -140,7 +177,7 @@ remoteDispatchClientRequest (struct qemud_server *server, struct qemud_client_message *msg) { XDR xdr; - remote_message_header req, rep; + remote_message_header rep; remote_error rerr; dispatch_args args; dispatch_ret ret; @@ -153,36 +190,28 @@ remoteDispatchClientRequest (struct qemud_server *server, memset(&ret, 0, sizeof ret); memset(&rerr, 0, sizeof rerr); - /* Parse the header. */ - xdrmem_create (&xdr, - msg->buffer + REMOTE_MESSAGE_HEADER_XDR_LEN, - msg->bufferLength - REMOTE_MESSAGE_HEADER_XDR_LEN, - XDR_DECODE); - - if (!xdr_remote_message_header (&xdr, &req)) - goto fatal_error; /* Check version, etc. */ - if (req.prog != REMOTE_PROGRAM) { + if (msg->hdr.prog != REMOTE_PROGRAM) { remoteDispatchFormatError (&rerr, _("program mismatch (actual %x, expected %x)"), - req.prog, REMOTE_PROGRAM); + msg->hdr.prog, REMOTE_PROGRAM); goto rpc_error; } - if (req.vers != REMOTE_PROTOCOL_VERSION) { + if (msg->hdr.vers != REMOTE_PROTOCOL_VERSION) { remoteDispatchFormatError (&rerr, _("version mismatch (actual %x, expected %x)"), - req.vers, REMOTE_PROTOCOL_VERSION); + msg->hdr.vers, REMOTE_PROTOCOL_VERSION); goto rpc_error; } - if (req.direction != REMOTE_CALL) { + if (msg->hdr.direction != REMOTE_CALL) { remoteDispatchFormatError (&rerr, _("direction (%d) != REMOTE_CALL"), - (int) req.direction); + (int) msg->hdr.direction); goto rpc_error; } - if (req.status != REMOTE_OK) { + if (msg->hdr.status != REMOTE_OK) { remoteDispatchFormatError (&rerr, _("status (%d) != REMOTE_OK"), - (int) req.status); + (int) msg->hdr.status); goto rpc_error; } @@ -190,11 +219,11 @@ remoteDispatchClientRequest (struct qemud_server *server, * except for authentication ones */ if (client->auth) { - if (req.proc != REMOTE_PROC_AUTH_LIST && - req.proc != REMOTE_PROC_AUTH_SASL_INIT && - req.proc != REMOTE_PROC_AUTH_SASL_START && - req.proc != REMOTE_PROC_AUTH_SASL_STEP && - req.proc != REMOTE_PROC_AUTH_POLKIT + if (msg->hdr.proc != REMOTE_PROC_AUTH_LIST && + msg->hdr.proc != REMOTE_PROC_AUTH_SASL_INIT && + msg->hdr.proc != REMOTE_PROC_AUTH_SASL_START && + msg->hdr.proc != REMOTE_PROC_AUTH_SASL_STEP && + msg->hdr.proc != REMOTE_PROC_AUTH_POLKIT ) { /* Explicitly *NOT* calling remoteDispatchAuthError() because we want back-compatability with libvirt clients which don't @@ -204,19 +233,25 @@ remoteDispatchClientRequest (struct qemud_server *server, } } - data = remoteGetDispatchData(req.proc); + data = remoteGetDispatchData(msg->hdr.proc); if (!data) { remoteDispatchFormatError (&rerr, _("unknown procedure: %d"), - req.proc); + msg->hdr.proc); goto rpc_error; } - /* De-serialize args off the wire */ + /* De-serialize payload with args from the wire message */ + xdrmem_create (&xdr, + msg->buffer + msg->bufferOffset, + msg->bufferLength - msg->bufferOffset, + XDR_DECODE); if (!((data->args_filter)(&xdr, &args))) { + xdr_destroy (&xdr); remoteDispatchFormatError (&rerr, "%s", _("parse args failed")); goto rpc_error; } + xdr_destroy (&xdr); /* Call function. */ conn = client->conn; @@ -241,14 +276,13 @@ remoteDispatchClientRequest (struct qemud_server *server, xdr_free (data->args_filter, (char*)&args); rpc_error: - xdr_destroy (&xdr); /* Return header. */ - rep.prog = req.prog; - rep.vers = req.vers; - rep.proc = req.proc; + rep.prog = msg->hdr.prog; + rep.vers = msg->hdr.vers; + rep.proc = msg->hdr.proc; rep.direction = REMOTE_REPLY; - rep.serial = req.serial; + rep.serial = msg->hdr.serial; rep.status = rv < 0 ? REMOTE_ERROR : REMOTE_OK; /* Serialise the return header. */ diff --git a/qemud/dispatch.h b/qemud/dispatch.h index 9ab6148..db372f1 100644 --- a/qemud/dispatch.h +++ b/qemud/dispatch.h @@ -29,6 +29,9 @@ int +remoteDecodeClientMessageHeader (struct qemud_client_message *req); + +int remoteDispatchClientRequest (struct qemud_server *server, struct qemud_client *client, struct qemud_client_message *req); diff --git a/qemud/qemud.c b/qemud/qemud.c index d300c56..c577d88 100644 --- a/qemud/qemud.c +++ b/qemud/qemud.c @@ -1458,7 +1458,8 @@ static void *qemudWorker(void *data) /* This function drops the lock during dispatch, * and re-acquires it before returning */ - if (remoteDispatchClientRequest (server, client, reply) < 0) { + if (remoteDecodeClientMessageHeader(reply) < 0 || + remoteDispatchClientRequest (server, client, reply) < 0) { VIR_FREE(reply); qemudDispatchClientFailure(client); client->refs--; diff --git a/qemud/qemud.h b/qemud/qemud.h index c8273cb..6597429 100644 --- a/qemud/qemud.h +++ b/qemud/qemud.h @@ -85,6 +85,8 @@ struct qemud_client_message { int async : 1; + remote_message_header hdr; + struct qemud_client_message *next; }; -- 1.6.2.5 -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list