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
This commit is contained in:
Daniel P. Berrange 2009-07-10 12:26:00 +01:00
parent a147ef3837
commit 081c6330b1
4 changed files with 72 additions and 32 deletions

View File

@ -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. */

View File

@ -28,6 +28,9 @@
#include "qemud.h"
int
remoteDecodeClientMessageHeader (struct qemud_client_message *req);
int
remoteDispatchClientRequest (struct qemud_server *server,
struct qemud_client *client,

View File

@ -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--;

View File

@ -85,6 +85,8 @@ struct qemud_client_message {
int async : 1;
remote_message_header hdr;
struct qemud_client_message *next;
};