[libvirt] [PATCH 2/9] Decode incoming request header before invoking dispatch code

Daniel P. Berrange berrange at redhat.com
Tue Jul 14 10:17:52 UTC 2009


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 at redhat.com>
---
 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 :|




More information about the libvir-list mailing list