From 081c6330b12ebee717eda425e9a56253f6e18d64 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 10 Jul 2009 12:26:00 +0100 Subject: [PATCH] Decode incoming request header before invoking dispatch code 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 --- 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 d2338fb218..127f93b7f6 100644 --- a/qemud/dispatch.c +++ b/qemud/dispatch.c @@ -123,14 +123,51 @@ 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 9ab61482ba..db372f17d4 100644 --- a/qemud/dispatch.h +++ b/qemud/dispatch.h @@ -28,6 +28,9 @@ #include "qemud.h" +int +remoteDecodeClientMessageHeader (struct qemud_client_message *req); + int remoteDispatchClientRequest (struct qemud_server *server, struct qemud_client *client, diff --git a/qemud/qemud.c b/qemud/qemud.c index d300c5649e..c577d88271 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 c8273cb5c4..659742958d 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; };