Remote patch, 2007-04-26

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Been on holiday last week, and then got massively sidetracked with query strings in libxml2, so there's not been much progress. Nevertheless, here is the current remote patch. It still needs GnuTLS support to be copied over from the old version, so currently it only listens on Unix sockets.

Rich.

--
Emerging Technologies, Red Hat  http://et.redhat.com/~rjones/
64 Baker Street, London, W1U 7DF     Mobile: +44 7866 314 421

Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod
Street, Windsor, Berkshire, SL4 1TE, United Kingdom.
Registered in England and Wales under Company Registration No. 3798903
Directors: Michael Cunningham (USA), Charlie Peters (USA) and David
Owens (Ireland)
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/configure.in libvirt-remote/configure.in
--- libvirt-cvs/configure.in	2007-04-17 19:49:16.000000000 +0100
+++ libvirt-remote/configure.in	2007-04-26 10:31:05.000000000 +0100
@@ -67,13 +67,15 @@
             [HTML_DIR="$HTML_DIR/\$(PACKAGE)-\$(VERSION)/html"])
 AC_SUBST(HTML_DIR)
 
-dnl Allow to build without Xen, QEMU/KVM or test driver
+dnl Allow to build without Xen, QEMU/KVM, test or remote driver
 AC_ARG_WITH(xen,
 [  --with-xen              add XEN support (on)])
 AC_ARG_WITH(qemu,
 [  --with-qemu             add QEMU/KVM support (on)])
 AC_ARG_WITH(test,
 [  --with-test             add test driver support (on)])
+AC_ARG_WITH(remote,
+[  --with-remote           add remote driver support (on)])
 
 dnl
 dnl specific tests to setup DV devel environments with debug etc ...
@@ -108,6 +110,18 @@
 AC_SUBST(QEMUD_PID_FILE)
 AC_MSG_RESULT($QEMUD_PID_FILE)
 
+AC_MSG_CHECKING([where to write libvirtd PID file])
+AC_ARG_WITH(remote-pid-file, AC_HELP_STRING([--with-remote-pid-file=[pidfile|none]], [PID file for libvirtd]))
+if test "x$with_remote_pid_file" == "x" ; then
+   REMOTE_PID_FILE="$localstatedir/run/libvirtd.pid"
+elif test "x$with_remote_pid_file" == "xnone" ; then
+   REMOTE_PID_FILE=""
+else
+   REMOTE_PID_FILE="$with_remote_pid_file"
+fi
+AC_SUBST(REMOTE_PID_FILE)
+AC_MSG_RESULT($REMOTE_PID_FILE)
+
 dnl
 dnl init script flavor
 dnl
@@ -183,6 +197,12 @@
     LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_TEST"
 fi
 
+if test "$with_remote" = "no" ; then
+    echo "Disabling remote driver support"
+else
+    LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_REMOTE"
+fi
+
 if test "$with_depends" != "no"
 then
 
@@ -264,6 +284,22 @@
 AC_SUBST(LIBXML_CONFIG)
 AC_SUBST(LIBXML_MIN_VERSION)
 
+dnl xmlURI structure has query_raw?
+old_cflags="$CFLAGS"
+CFLAGS="$CFLAGS $LIBXML_CFLAGS"
+AC_CHECK_MEMBER(struct _xmlURI.query_raw,
+		[AC_DEFINE(HAVE_XMLURI_QUERY_RAW, [], [Have query_raw field in libxml2 xmlURI structure])],,
+		[#include <libxml/uri.h>])
+CFLAGS="$old_cflags"
+
+dnl GnuTLS library
+AC_CHECK_HEADER([gnutls/gnutls.h],
+       [],
+       AC_MSG_ERROR([You must install the GnuTLS development package in order to compile libvirt]))
+AC_CHECK_LIB(gnutls, gnutls_handshake,
+       [],
+       [AC_MSG_ERROR([You must install the GnuTLS library in order to compile and run libvirt])])
+
 dnl virsh libraries
 AC_CHECK_LIB(curses, initscr, 
 	[VIRSH_LIBS="$VIRSH_LIBS -lcurses"],
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/.cvsignore libvirt-remote/.cvsignore
--- libvirt-cvs/.cvsignore	2007-03-16 11:04:43.000000000 +0000
+++ libvirt-remote/.cvsignore	2007-04-17 18:01:28.000000000 +0100
@@ -28,3 +28,8 @@
 coverage
 results.log
 libvirt-*.tar.gz
+INSTALL
+compile
+depcomp
+install-sh
+missing
\ No newline at end of file
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/docs/libvir.html libvirt-remote/docs/libvir.html
--- libvirt-cvs/docs/libvir.html	2007-04-26 11:23:37.000000000 +0100
+++ libvirt-remote/docs/libvir.html	2007-04-19 11:59:21.000000000 +0100
@@ -1456,7 +1456,7 @@
 </p>
 
 <p>
-<code>driver</code>[<code>+transport</code>]<code>://</code>[<code>username@</code>]<code>hostname</code>[<code>:port</code>]<code>/</code>[<code>path</code>][<code>?extraparameters</code>]
+<code>driver</code>[<code>+transport</code>]<code>://</code>[<code>username@</code>][<code>hostname</code>][<code>:port</code>]<code>/</code>[<code>path</code>][<code>?extraparameters</code>]
 </p>
 
 <p>
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/docs/remote.html libvirt-remote/docs/remote.html
--- libvirt-cvs/docs/remote.html	2007-04-19 09:44:07.000000000 +0100
+++ libvirt-remote/docs/remote.html	2007-04-23 12:35:37.000000000 +0100
@@ -81,7 +81,7 @@
 </p><h3><a name="Remote_URI_reference" id="Remote_URI_reference">Remote URIs</a></h3><p>
 Remote URIs have the general form ("[...]" meaning an optional part):
 </p><p>
-<code>driver</code>[<code>+transport</code>]<code>://</code>[<code>username@</code>]<code>hostname</code>[<code>:port</code>]<code>/</code>[<code>path</code>][<code>?extraparameters</code>]
+<code>driver</code>[<code>+transport</code>]<code>://</code>[<code>username@</code>][<code>hostname</code>][<code>:port</code>]<code>/</code>[<code>path</code>][<code>?extraparameters</code>]
 </p><p>
 Either the transport or the hostname must be given in order
 to distinguish this from a local URI.
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/include/libvirt/virterror.h libvirt-remote/include/libvirt/virterror.h
--- libvirt-cvs/include/libvirt/virterror.h	2007-04-26 11:23:39.000000000 +0100
+++ libvirt-remote/include/libvirt/virterror.h	2007-04-18 11:18:02.000000000 +0100
@@ -50,6 +50,7 @@
     VIR_FROM_QEMU,      /* Error at the QEMU daemon */
     VIR_FROM_NET,       /* Error when operating on a network */
     VIR_FROM_TEST,	/* Error from test driver */
+    VIR_FROM_REMOTE,	/* Error from remote driver */
 } virErrorDomain;
 
 
@@ -121,6 +122,8 @@
     VIR_ERR_INVALID_NETWORK, /* invalid network object */
     VIR_ERR_NETWORK_EXIST, /* the network already exist */
     VIR_ERR_SYSTEM_ERROR, /* general system call failure */
+    VIR_ERR_RPC, /* some sort of RPC error */
+    VIR_ERR_GNUTLS_ERROR, /* error from a GNUTLS call */
 } virErrorNumber;
 
 /**
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/conf.c libvirt-remote/qemud/conf.c
--- libvirt-cvs/qemud/conf.c	2007-04-17 19:49:31.000000000 +0100
+++ libvirt-remote/qemud/conf.c	2007-04-17 14:42:29.000000000 +0100
@@ -42,7 +42,6 @@
 
 #include <libvirt/virterror.h>
 
-#include "protocol.h"
 #include "internal.h"
 #include "conf.h"
 #include "driver.h"
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/dispatch.c libvirt-remote/qemud/dispatch.c
--- libvirt-cvs/qemud/dispatch.c	2007-03-16 11:04:46.000000000 +0000
+++ libvirt-remote/qemud/dispatch.c	2007-04-17 11:20:21.000000000 +0100
@@ -40,65 +40,56 @@
 
 static int qemudDispatchFailure(struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
-                                struct qemud_packet *out) {
-    out->header.type = QEMUD_PKT_FAILURE;
-    out->header.dataSize = sizeof(out->data.failureReply);
-    out->data.failureReply.code = server->errorCode;
-    strcpy(out->data.failureReply.message, server->errorMessage);
+                                struct qemud_packet_server_data *out) {
+    out->type = QEMUD_SERVER_PKT_FAILURE;
+    out->qemud_packet_server_data_u.failureReply.code = server->errorCode;
+    strcpy(out->qemud_packet_server_data_u.failureReply.message, server->errorMessage);
     return 0;
 }
 
 
 static int qemudDispatchGetVersion(struct qemud_server *server, struct qemud_client *client,
-                                   struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != 0)
-        return -1;
-
+                                   struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
     int version = qemudGetVersion(server);
     if (version < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_GET_VERSION;
-        out->header.dataSize = sizeof(out->data.getVersionReply);
-        out->data.getVersionReply.version = version;
+        out->type = QEMUD_SERVER_PKT_GET_VERSION;
+        out->qemud_packet_server_data_u.getVersionReply.versionNum = version;
     }
     return 0;
 }
 
 static int qemudDispatchGetNodeInfo(struct qemud_server *server, struct qemud_client *client,
-                                    struct qemud_packet *in, struct qemud_packet *out) {
+                                    struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
     struct utsname info;
 
-    if (in->header.dataSize != 0)
-        return -1;
-
     if (uname(&info) < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
         return 0;
     }
 
-    if (qemudGetCPUInfo(&out->data.getNodeInfoReply.cpus,
-                        &out->data.getNodeInfoReply.mhz,
-                        &out->data.getNodeInfoReply.nodes,
-                        &out->data.getNodeInfoReply.sockets,
-                        &out->data.getNodeInfoReply.cores,
-                        &out->data.getNodeInfoReply.threads) < 0) {
+    if (qemudGetCPUInfo(&out->qemud_packet_server_data_u.getNodeInfoReply.cpus,
+                        &out->qemud_packet_server_data_u.getNodeInfoReply.mhz,
+                        &out->qemud_packet_server_data_u.getNodeInfoReply.nodes,
+                        &out->qemud_packet_server_data_u.getNodeInfoReply.sockets,
+                        &out->qemud_packet_server_data_u.getNodeInfoReply.cores,
+                        &out->qemud_packet_server_data_u.getNodeInfoReply.threads) < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
         return 0;
     }
-    if (qemudGetMemInfo(&out->data.getNodeInfoReply.memory) < 0) {
+    if (qemudGetMemInfo(&out->qemud_packet_server_data_u.getNodeInfoReply.memory) < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
         return 0;
     }
 
-    out->header.type = QEMUD_PKT_GET_NODEINFO;
-    out->header.dataSize = sizeof(out->data.getNodeInfoReply);
-    strncpy(out->data.getNodeInfoReply.model, info.machine, sizeof(out->data.getNodeInfoReply.model));
-    out->data.getNodeInfoReply.model[sizeof(out->data.getNodeInfoReply.model)-1] = '\0';
+    out->type = QEMUD_SERVER_PKT_GET_NODEINFO;
+    strncpy(out->qemud_packet_server_data_u.getNodeInfoReply.model, info.machine, sizeof(out->qemud_packet_server_data_u.getNodeInfoReply.model));
+    out->qemud_packet_server_data_u.getNodeInfoReply.model[sizeof(out->qemud_packet_server_data_u.getNodeInfoReply.model)-1] = '\0';
 
     return 0;
 }
@@ -106,8 +97,8 @@
 static int
 qemudDispatchGetCapabilities (struct qemud_server *server,
                               struct qemud_client *client,
-                              struct qemud_packet *in,
-                              struct qemud_packet *out)
+                              struct qemud_packet_client_data *in ATTRIBUTE_UNUSED,
+                              struct qemud_packet_server_data *out)
 {
     struct utsname utsname;
     int i, j, r;
@@ -116,8 +107,6 @@
     bufferPtr xml;
     int len;
 
-    if (in->header.dataSize != 0) return -1;
-
     /* Really, this never fails - look at the man-page. */
     uname (&utsname);
 
@@ -268,18 +257,15 @@
         qemudDispatchFailure (server, client, out);
         return 0;
     }
-    out->header.type = QEMUD_PKT_GET_CAPABILITIES;
-    out->header.dataSize = sizeof(out->data.getCapabilitiesReply);
-    strcpy (out->data.getCapabilitiesReply.xml, xml->content);
+    out->type = QEMUD_SERVER_PKT_GET_CAPABILITIES;
+    strcpy (out->qemud_packet_server_data_u.getCapabilitiesReply.xml, xml->content);
     bufferFree (xml);
     return 0;
 }
 
 static int qemudDispatchListDomains(struct qemud_server *server, struct qemud_client *client,
-                                    struct qemud_packet *in, struct qemud_packet *out) {
+                                    struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
     int i, ndomains, domains[QEMUD_MAX_NUM_DOMAINS];
-    if (in->header.dataSize != 0)
-        return -1;
 
     ndomains = qemudListDomains(server,
                                 domains,
@@ -288,172 +274,136 @@
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_LIST_DOMAINS;
-        out->header.dataSize = sizeof(out->data.listDomainsReply);
+        out->type = QEMUD_SERVER_PKT_LIST_DOMAINS;
         for (i = 0 ; i < ndomains ; i++) {
-            out->data.listDomainsReply.domains[i] = domains[i];
+            out->qemud_packet_server_data_u.listDomainsReply.domains[i] = domains[i];
         }
-        out->data.listDomainsReply.numDomains = ndomains;
+        out->qemud_packet_server_data_u.listDomainsReply.numDomains = ndomains;
     }
     return 0;
 }
 
 static int qemudDispatchNumDomains(struct qemud_server *server, struct qemud_client *client,
-                                   struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != 0)
-        return -1;
-
+                                   struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
     int ndomains = qemudNumDomains(server);
     if (ndomains < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NUM_DOMAINS;
-        out->header.dataSize = sizeof(out->data.numDomainsReply);
-        out->data.numDomainsReply.numDomains = ndomains;
+        out->type = QEMUD_SERVER_PKT_NUM_DOMAINS;
+        out->qemud_packet_server_data_u.numDomainsReply.numDomains = ndomains;
     }
     return 0;
 }
 
 static int qemudDispatchDomainCreate(struct qemud_server *server, struct qemud_client *client,
-                                     struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainCreateRequest))
-        return -1;
-
-    in->data.domainCreateRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
+                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    in->qemud_packet_client_data_u.domainCreateRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
 
-    struct qemud_vm *vm = qemudDomainCreate(server, in->data.domainCreateRequest.xml);
+    struct qemud_vm *vm = qemudDomainCreate(server, in->qemud_packet_client_data_u.domainCreateRequest.xml);
     if (!vm) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_CREATE;
-        out->header.dataSize = sizeof(out->data.domainCreateReply);
-        out->data.domainCreateReply.id = vm->id;
-        memcpy(out->data.domainCreateReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
-        strncpy(out->data.domainCreateReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.domainCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_DOMAIN_CREATE;
+        out->qemud_packet_server_data_u.domainCreateReply.id = vm->id;
+        memcpy(out->qemud_packet_server_data_u.domainCreateReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
+        strncpy(out->qemud_packet_server_data_u.domainCreateReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.domainCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchDomainLookupByID(struct qemud_server *server, struct qemud_client *client,
-                                         struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainLookupByIDRequest))
-        return -1;
-
-    struct qemud_vm *vm = qemudFindVMByID(server, in->data.domainLookupByIDRequest.id);
+                                         struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    struct qemud_vm *vm = qemudFindVMByID(server, in->qemud_packet_client_data_u.domainLookupByIDRequest.id);
     if (!vm) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_LOOKUP_BY_ID;
-        out->header.dataSize = sizeof(out->data.domainLookupByIDReply);
-        memcpy(out->data.domainLookupByIDReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
-        strncpy(out->data.domainLookupByIDReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.domainLookupByIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_ID;
+        memcpy(out->qemud_packet_server_data_u.domainLookupByIDReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
+        strncpy(out->qemud_packet_server_data_u.domainLookupByIDReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.domainLookupByIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchDomainLookupByUUID(struct qemud_server *server, struct qemud_client *client,
-                                           struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainLookupByUUIDRequest))
-        return -1;
-
-    struct qemud_vm *vm = qemudFindVMByUUID(server, in->data.domainLookupByUUIDRequest.uuid);
+                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    struct qemud_vm *vm = qemudFindVMByUUID(server, in->qemud_packet_client_data_u.domainLookupByUUIDRequest.uuid);
     if (!vm) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_LOOKUP_BY_UUID;
-        out->header.dataSize = sizeof(out->data.domainLookupByUUIDReply);
-        out->data.domainLookupByUUIDReply.id = vm->id;
-        strncpy(out->data.domainLookupByUUIDReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.domainLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_UUID;
+        out->qemud_packet_server_data_u.domainLookupByUUIDReply.id = vm->id;
+        strncpy(out->qemud_packet_server_data_u.domainLookupByUUIDReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.domainLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchDomainLookupByName(struct qemud_server *server, struct qemud_client *client,
-                                           struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainLookupByNameRequest))
-        return -1;
-
+                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     /* Paranoia NULL termination */
-    in->data.domainLookupByNameRequest.name[QEMUD_MAX_NAME_LEN-1] = '\0';
-    struct qemud_vm *vm = qemudFindVMByName(server, in->data.domainLookupByNameRequest.name);
+    in->qemud_packet_client_data_u.domainLookupByNameRequest.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+    struct qemud_vm *vm = qemudFindVMByName(server, in->qemud_packet_client_data_u.domainLookupByNameRequest.name);
     if (!vm) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_LOOKUP_BY_NAME;
-        out->header.dataSize = sizeof(out->data.domainLookupByNameReply);
-        out->data.domainLookupByNameReply.id = vm->id;
-        memcpy(out->data.domainLookupByNameReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
+        out->type = QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_NAME;
+        out->qemud_packet_server_data_u.domainLookupByNameReply.id = vm->id;
+        memcpy(out->qemud_packet_server_data_u.domainLookupByNameReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
     }
     return 0;
 }
 
 static int qemudDispatchDomainSuspend(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainSuspendRequest))
-        return -1;
-
-    int ret = qemudDomainSuspend(server, in->data.domainSuspendRequest.id);
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    int ret = qemudDomainSuspend(server, in->qemud_packet_client_data_u.domainSuspendRequest.id);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_SUSPEND;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_SUSPEND;
     }
     return 0;
 }
 
 static int qemudDispatchDomainResume(struct qemud_server *server, struct qemud_client *client,
-                                     struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainResumeRequest))
-        return -1;
-
-    int ret = qemudDomainResume(server, in->data.domainResumeRequest.id);
+                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    int ret = qemudDomainResume(server, in->qemud_packet_client_data_u.domainResumeRequest.id);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_RESUME;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_RESUME;
     }
     return 0;
 }
 
 static int qemudDispatchDomainDestroy(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainDestroyRequest))
-        return -1;
-
-    if (qemudDomainDestroy(server, in->data.domainDestroyRequest.id) < 0) {
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    if (qemudDomainDestroy(server, in->qemud_packet_client_data_u.domainDestroyRequest.id) < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_DESTROY;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_DESTROY;
     }
     return 0;
 }
 
 static int qemudDispatchDomainGetInfo(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int runstate;
     unsigned long long cpuTime;
     unsigned long memory;
     unsigned long maxmem;
     unsigned int nrVirtCpu;
 
-    if (in->header.dataSize != sizeof(in->data.domainGetInfoRequest))
-        return -1;
-
-    int ret = qemudDomainGetInfo(server, in->data.domainGetInfoRequest.uuid,
+    int ret = qemudDomainGetInfo(server, in->qemud_packet_client_data_u.domainGetInfoRequest.uuid,
                                  &runstate,
                                  &cpuTime,
                                  &maxmem,
@@ -463,91 +413,77 @@
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_GET_INFO;
-        out->header.dataSize = sizeof(out->data.domainGetInfoReply);
-        out->data.domainGetInfoReply.runstate = runstate;
-        out->data.domainGetInfoReply.cpuTime = cpuTime;
-        out->data.domainGetInfoReply.maxmem = maxmem;
-        out->data.domainGetInfoReply.memory = memory;
-        out->data.domainGetInfoReply.nrVirtCpu = nrVirtCpu;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_GET_INFO;
+        out->qemud_packet_server_data_u.domainGetInfoReply.runstate = runstate;
+        out->qemud_packet_server_data_u.domainGetInfoReply.cpuTime = cpuTime;
+        out->qemud_packet_server_data_u.domainGetInfoReply.maxmem = maxmem;
+        out->qemud_packet_server_data_u.domainGetInfoReply.memory = memory;
+        out->qemud_packet_server_data_u.domainGetInfoReply.nrVirtCpu = nrVirtCpu;
     }
     return 0;
 }
 
 static int qemudDispatchDomainSave(struct qemud_server *server, struct qemud_client *client,
-                                   struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainSaveRequest))
-        return -1;
-
+                                   struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     /* Paranoia NULL termination */
-    in->data.domainSaveRequest.file[PATH_MAX-1] ='\0';
+    in->qemud_packet_client_data_u.domainSaveRequest.file[PATH_MAX-1] ='\0';
 
     int ret = qemudDomainSave(server,
-                              in->data.domainSaveRequest.id,
-                              in->data.domainSaveRequest.file);
+                              in->qemud_packet_client_data_u.domainSaveRequest.id,
+                              in->qemud_packet_client_data_u.domainSaveRequest.file);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_SAVE;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_SAVE;
     }
     return 0;
 }
 
 static int qemudDispatchDomainRestore(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int id;
-    if (in->header.dataSize != sizeof(in->data.domainRestoreRequest))
-        return -1;
 
     /* Paranoia null termination */
-    in->data.domainRestoreRequest.file[PATH_MAX-1] ='\0';
+    in->qemud_packet_client_data_u.domainRestoreRequest.file[PATH_MAX-1] ='\0';
 
-    id = qemudDomainRestore(server, in->data.domainRestoreRequest.file);
+    id = qemudDomainRestore(server, in->qemud_packet_client_data_u.domainRestoreRequest.file);
     if (id < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_RESTORE;
-        out->header.dataSize = sizeof(out->data.domainRestoreReply);
-        out->data.domainRestoreReply.id = id;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_RESTORE;
+        out->qemud_packet_server_data_u.domainRestoreReply.id = id;
     }
     return 0;
 }
 
 static int qemudDispatchDumpXML(struct qemud_server *server, struct qemud_client *client,
-                                struct qemud_packet *in, struct qemud_packet *out) {
+                                struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int ret;
-    if (in->header.dataSize != sizeof(in->data.domainDumpXMLRequest))
-        return -1;
-
     ret = qemudDomainDumpXML(server,
-                             in->data.domainDumpXMLRequest.uuid,
-                             out->data.domainDumpXMLReply.xml,
+                             in->qemud_packet_client_data_u.domainDumpXMLRequest.uuid,
+                             out->qemud_packet_server_data_u.domainDumpXMLReply.xml,
                              QEMUD_MAX_XML_LEN);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DUMP_XML;
-        out->header.dataSize = sizeof(out->data.domainDumpXMLReply);
+        out->type = QEMUD_SERVER_PKT_DUMP_XML;
     }
     return 0;
 }
 
 static int qemudDispatchListDefinedDomains(struct qemud_server *server, struct qemud_client *client,
-                                           struct qemud_packet *in, struct qemud_packet *out) {
+                                           struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
     char **names;
     int i, ndomains;
-    if (in->header.dataSize != 0)
-        return -1;
 
     if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_DOMAINS)))
         return -1;
 
     for (i = 0 ; i < QEMUD_MAX_NUM_DOMAINS ; i++) {
-        names[i] = out->data.listDefinedDomainsReply.domains[i];
+        names[i] = &out->qemud_packet_server_data_u.listDefinedDomainsReply.domains[i*QEMUD_MAX_NAME_LEN];
     }
 
     ndomains = qemudListDefinedDomains(server,
@@ -558,114 +494,95 @@
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_LIST_DEFINED_DOMAINS;
-        out->header.dataSize = sizeof(out->data.listDefinedDomainsReply);
-        out->data.listDefinedDomainsReply.numDomains = ndomains;
+        out->type = QEMUD_SERVER_PKT_LIST_DEFINED_DOMAINS;
+        out->qemud_packet_server_data_u.listDefinedDomainsReply.numDomains = ndomains;
+    }
+    printf("%d %d\n", out->type, out->qemud_packet_server_data_u.listDefinedDomainsReply.numDomains);
+    for (i = 0 ; i < ndomains;i++) {
+        printf("[%s]\n", &out->qemud_packet_server_data_u.listDefinedDomainsReply.domains[i*QEMUD_MAX_NAME_LEN]);
     }
     return 0;
 }
 
 static int qemudDispatchNumDefinedDomains(struct qemud_server *server, struct qemud_client *client,
-                                          struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != 0)
-        return -1;
-
+                                          struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
     int ndomains = qemudNumDefinedDomains(server);
     if (ndomains < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NUM_DEFINED_DOMAINS;
-        out->header.dataSize = sizeof(out->data.numDefinedDomainsReply);
-        out->data.numDefinedDomainsReply.numDomains = ndomains;
+        out->type = QEMUD_SERVER_PKT_NUM_DEFINED_DOMAINS;
+        out->qemud_packet_server_data_u.numDefinedDomainsReply.numDomains = ndomains;
     }
     return 0;
 }
 
 static int qemudDispatchDomainStart(struct qemud_server *server, struct qemud_client *client,
-                                    struct qemud_packet *in, struct qemud_packet *out) {
+                                    struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     struct qemud_vm *vm;
 
-    if (in->header.dataSize != sizeof(in->data.domainStartRequest))
-        return -1;
-
-    if (!(vm = qemudDomainStart(server, in->data.domainStartRequest.uuid))) {
+    if (!(vm = qemudDomainStart(server, in->qemud_packet_client_data_u.domainStartRequest.uuid))) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_START;
-        out->header.dataSize = sizeof(out->data.domainStartReply);
-        out->data.domainStartReply.id = vm->id;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_START;
+        out->qemud_packet_server_data_u.domainStartReply.id = vm->id;
     }
     return 0;
 }
 
 static int qemudDispatchDomainDefine(struct qemud_server *server, struct qemud_client *client,
-                                     struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainDefineRequest))
-        return -1;
-
-    in->data.domainDefineRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
+                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    in->qemud_packet_client_data_u.domainDefineRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
 
-    struct qemud_vm *vm = qemudDomainDefine(server, in->data.domainDefineRequest.xml);
+    struct qemud_vm *vm = qemudDomainDefine(server, in->qemud_packet_client_data_u.domainDefineRequest.xml);
     if (!vm) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_DEFINE;
-        out->header.dataSize = sizeof(out->data.domainDefineReply);
-        memcpy(out->data.domainDefineReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
-        strncpy(out->data.domainDefineReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.domainDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_DOMAIN_DEFINE;
+        memcpy(out->qemud_packet_server_data_u.domainDefineReply.uuid, vm->def->uuid, QEMUD_UUID_RAW_LEN);
+        strncpy(out->qemud_packet_server_data_u.domainDefineReply.name, vm->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.domainDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchDomainUndefine(struct qemud_server *server, struct qemud_client *client,
-                                       struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.domainUndefineRequest))
-        return -1;
-
-    int ret = qemudDomainUndefine(server, in->data.domainUndefineRequest.uuid);
+                                       struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    int ret = qemudDomainUndefine(server, in->qemud_packet_client_data_u.domainUndefineRequest.uuid);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_UNDEFINE;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_UNDEFINE;
     }
     return 0;
 }
 
 static int qemudDispatchNumNetworks(struct qemud_server *server, struct qemud_client *client,
-                                    struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != 0)
-        return -1;
-
+                                    struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
     int nnetworks = qemudNumNetworks(server);
     if (nnetworks < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NUM_NETWORKS;
-        out->header.dataSize = sizeof(out->data.numNetworksReply);
-        out->data.numNetworksReply.numNetworks = nnetworks;
+        out->type = QEMUD_SERVER_PKT_NUM_NETWORKS;
+        out->qemud_packet_server_data_u.numNetworksReply.numNetworks = nnetworks;
     }
     return 0;
 }
 
 static int qemudDispatchListNetworks(struct qemud_server *server, struct qemud_client *client,
-                                     struct qemud_packet *in, struct qemud_packet *out) {
+                                     struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
     char **names;
     int i;
-    if (in->header.dataSize != 0)
-        return -1;
 
     if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_NETWORKS)))
         return -1;
 
     for (i = 0 ; i < QEMUD_MAX_NUM_NETWORKS ; i++) {
-        names[i] = out->data.listNetworksReply.networks[i];
+        names[i] = &out->qemud_packet_server_data_u.listNetworksReply.networks[i*QEMUD_MAX_NAME_LEN];
     }
 
     int nnetworks = qemudListNetworks(server,
@@ -676,42 +593,35 @@
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_LIST_NETWORKS;
-        out->header.dataSize = sizeof(out->data.listNetworksReply);
-        out->data.listNetworksReply.numNetworks = nnetworks;
+        out->type = QEMUD_SERVER_PKT_LIST_NETWORKS;
+        out->qemud_packet_server_data_u.listNetworksReply.numNetworks = nnetworks;
     }
     return 0;
 }
 
 static int qemudDispatchNumDefinedNetworks(struct qemud_server *server, struct qemud_client *client,
-                                           struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != 0)
-        return -1;
-
+                                           struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
     int nnetworks = qemudNumDefinedNetworks(server);
     if (nnetworks < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NUM_DEFINED_NETWORKS;
-        out->header.dataSize = sizeof(out->data.numDefinedNetworksReply);
-        out->data.numDefinedNetworksReply.numNetworks = nnetworks;
+        out->type = QEMUD_SERVER_PKT_NUM_DEFINED_NETWORKS;
+        out->qemud_packet_server_data_u.numDefinedNetworksReply.numNetworks = nnetworks;
     }
     return 0;
 }
 
 static int qemudDispatchListDefinedNetworks(struct qemud_server *server, struct qemud_client *client,
-                                            struct qemud_packet *in, struct qemud_packet *out) {
+                                            struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
     char **names;
     int i;
-    if (in->header.dataSize != 0)
-        return -1;
 
     if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_NETWORKS)))
         return -1;
 
     for (i = 0 ; i < QEMUD_MAX_NUM_NETWORKS ; i++) {
-        names[i] = out->data.listDefinedNetworksReply.networks[i];
+        names[i] = &out->qemud_packet_server_data_u.listDefinedNetworksReply.networks[i*QEMUD_MAX_NAME_LEN];
     }
 
     int nnetworks = qemudListDefinedNetworks(server,
@@ -722,276 +632,222 @@
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_LIST_DEFINED_NETWORKS;
-        out->header.dataSize = sizeof(out->data.listDefinedNetworksReply);
-        out->data.listDefinedNetworksReply.numNetworks = nnetworks;
+        out->type = QEMUD_SERVER_PKT_LIST_DEFINED_NETWORKS;
+        out->qemud_packet_server_data_u.listDefinedNetworksReply.numNetworks = nnetworks;
     }
     return 0;
 }
 
 static int qemudDispatchNetworkLookupByName(struct qemud_server *server, struct qemud_client *client,
-                                            struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkLookupByNameRequest))
-        return -1;
-
+                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     /* Paranoia NULL termination */
-    in->data.networkLookupByNameRequest.name[QEMUD_MAX_NAME_LEN-1] = '\0';
-    struct qemud_network *network = qemudFindNetworkByName(server, in->data.networkLookupByNameRequest.name);
+    in->qemud_packet_client_data_u.networkLookupByNameRequest.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+    struct qemud_network *network = qemudFindNetworkByName(server, in->qemud_packet_client_data_u.networkLookupByNameRequest.name);
     if (!network) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_LOOKUP_BY_NAME;
-        out->header.dataSize = sizeof(out->data.networkLookupByNameReply);
-        memcpy(out->data.networkLookupByNameReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
+        out->type = QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_NAME;
+        memcpy(out->qemud_packet_server_data_u.networkLookupByNameReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
     }
     return 0;
 }
 
 static int qemudDispatchNetworkLookupByUUID(struct qemud_server *server, struct qemud_client *client,
-                                            struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkLookupByUUIDRequest))
-        return -1;
-
-    struct qemud_network *network = qemudFindNetworkByUUID(server, in->data.networkLookupByUUIDRequest.uuid);
+                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    struct qemud_network *network = qemudFindNetworkByUUID(server, in->qemud_packet_client_data_u.networkLookupByUUIDRequest.uuid);
     if (!network) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_LOOKUP_BY_UUID;
-        out->header.dataSize = sizeof(out->data.networkLookupByUUIDReply);
-        strncpy(out->data.networkLookupByUUIDReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.networkLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_UUID;
+        strncpy(out->qemud_packet_server_data_u.networkLookupByUUIDReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.networkLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchNetworkCreate(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkCreateRequest))
-        return -1;
-
-    in->data.networkCreateRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    in->qemud_packet_client_data_u.networkCreateRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
 
-    struct qemud_network *network = qemudNetworkCreate(server, in->data.networkCreateRequest.xml);
+    struct qemud_network *network = qemudNetworkCreate(server, in->qemud_packet_client_data_u.networkCreateRequest.xml);
     if (!network) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_CREATE;
-        out->header.dataSize = sizeof(out->data.networkCreateReply);
-        memcpy(out->data.networkCreateReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
-        strncpy(out->data.networkCreateReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.networkCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_NETWORK_CREATE;
+        memcpy(out->qemud_packet_server_data_u.networkCreateReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
+        strncpy(out->qemud_packet_server_data_u.networkCreateReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.networkCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchNetworkDefine(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkDefineRequest))
-        return -1;
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    in->qemud_packet_client_data_u.networkDefineRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
 
-    in->data.networkDefineRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
-
-    struct qemud_network *network = qemudNetworkDefine(server, in->data.networkDefineRequest.xml);
+    struct qemud_network *network = qemudNetworkDefine(server, in->qemud_packet_client_data_u.networkDefineRequest.xml);
     if (!network) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_DEFINE;
-        out->header.dataSize = sizeof(out->data.networkDefineReply);
-        memcpy(out->data.networkDefineReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
-        strncpy(out->data.networkDefineReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
-        out->data.networkDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+        out->type = QEMUD_SERVER_PKT_NETWORK_DEFINE;
+        memcpy(out->qemud_packet_server_data_u.networkDefineReply.uuid, network->def->uuid, QEMUD_UUID_RAW_LEN);
+        strncpy(out->qemud_packet_server_data_u.networkDefineReply.name, network->def->name, QEMUD_MAX_NAME_LEN-1);
+        out->qemud_packet_server_data_u.networkDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
     }
     return 0;
 }
 
 static int qemudDispatchNetworkUndefine(struct qemud_server *server, struct qemud_client *client,
-                                        struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkUndefineRequest))
-        return -1;
-
-    int ret = qemudNetworkUndefine(server, in->data.networkUndefineRequest.uuid);
+                                        struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    int ret = qemudNetworkUndefine(server, in->qemud_packet_client_data_u.networkUndefineRequest.uuid);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_UNDEFINE;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_NETWORK_UNDEFINE;
     }
     return 0;
 }
 
 static int qemudDispatchNetworkStart(struct qemud_server *server, struct qemud_client *client,
-                                     struct qemud_packet *in, struct qemud_packet *out) {
+                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     struct qemud_network *network;
 
-    if (in->header.dataSize != sizeof(in->data.networkStartRequest))
-        return -1;
-
-    if (!(network = qemudNetworkStart(server, in->data.networkStartRequest.uuid))) {
+    if (!(network = qemudNetworkStart(server, in->qemud_packet_client_data_u.networkStartRequest.uuid))) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_START;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_NETWORK_START;
     }
     return 0;
 }
 
 static int qemudDispatchNetworkDestroy(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkDestroyRequest))
-        return -1;
-
-    if (qemudNetworkDestroy(server, in->data.networkDestroyRequest.uuid) < 0) {
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
+    if (qemudNetworkDestroy(server, in->qemud_packet_client_data_u.networkDestroyRequest.uuid) < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_DESTROY;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_NETWORK_DESTROY;
     }
     return 0;
 }
 
 static int qemudDispatchNetworkDumpXML(struct qemud_server *server, struct qemud_client *client,
-                                      struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkDumpXMLRequest))
-        return -1;
-
+                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int ret = qemudNetworkDumpXML(server,
-                                  in->data.networkDumpXMLRequest.uuid,
-                                  out->data.networkDumpXMLReply.xml, QEMUD_MAX_XML_LEN);
+                                  in->qemud_packet_client_data_u.networkDumpXMLRequest.uuid,
+                                  out->qemud_packet_server_data_u.networkDumpXMLReply.xml, QEMUD_MAX_XML_LEN);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_DUMP_XML;
-        out->header.dataSize = sizeof(out->data.networkDumpXMLReply);
+        out->type = QEMUD_SERVER_PKT_NETWORK_DUMP_XML;
     }
     return 0;
 }
 
 static int qemudDispatchNetworkGetBridgeName(struct qemud_server *server, struct qemud_client *client,
-                                             struct qemud_packet *in, struct qemud_packet *out) {
-    if (in->header.dataSize != sizeof(in->data.networkGetBridgeNameRequest))
-        return -1;
-
+                                             struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
     int ret = qemudNetworkGetBridgeName(server,
-                                        in->data.networkDumpXMLRequest.uuid,
-                                        out->data.networkGetBridgeNameReply.ifname, QEMUD_MAX_IFNAME_LEN);
+                                        in->qemud_packet_client_data_u.networkDumpXMLRequest.uuid,
+                                        out->qemud_packet_server_data_u.networkGetBridgeNameReply.ifname, QEMUD_MAX_IFNAME_LEN);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_GET_BRIDGE_NAME;
-        out->header.dataSize = sizeof(out->data.networkGetBridgeNameReply);
+        out->type = QEMUD_SERVER_PKT_NETWORK_GET_BRIDGE_NAME;
     }
     return 0;
 }
 
 static int qemudDispatchDomainGetAutostart(struct qemud_server *server, struct qemud_client *client,
-                                           struct qemud_packet *in, struct qemud_packet *out)
+                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
 {
     int ret;
     int autostart;
 
-    if (in->header.dataSize != sizeof(in->data.domainGetAutostartRequest))
-        return -1;
-
     autostart = 0;
 
     ret = qemudDomainGetAutostart(server,
-                                  in->data.domainGetAutostartRequest.uuid,
+                                  in->qemud_packet_client_data_u.domainGetAutostartRequest.uuid,
                                   &autostart);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_GET_AUTOSTART;
-        out->header.dataSize = sizeof(out->data.networkGetAutostartReply);
-        out->data.networkGetAutostartReply.autostart = (autostart != 0);
+        out->type = QEMUD_SERVER_PKT_DOMAIN_GET_AUTOSTART;
+        out->qemud_packet_server_data_u.networkGetAutostartReply.autostart = (autostart != 0);
     }
     return 0;
 }
 
 static int qemudDispatchDomainSetAutostart(struct qemud_server *server, struct qemud_client *client,
-                                           struct qemud_packet *in, struct qemud_packet *out)
+                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
 {
     int ret;
 
-    if (in->header.dataSize != sizeof(in->data.domainSetAutostartRequest))
-        return -1;
-
     ret = qemudDomainSetAutostart(server,
-                                  in->data.domainGetAutostartRequest.uuid,
-                                  in->data.domainSetAutostartRequest.autostart);
+                                  in->qemud_packet_client_data_u.domainGetAutostartRequest.uuid,
+                                  in->qemud_packet_client_data_u.domainSetAutostartRequest.autostart);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_DOMAIN_SET_AUTOSTART;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_DOMAIN_SET_AUTOSTART;
     }
     return 0;
 }
 
 static int qemudDispatchNetworkGetAutostart(struct qemud_server *server, struct qemud_client *client,
-                                            struct qemud_packet *in, struct qemud_packet *out)
+                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
 {
     int ret;
     int autostart;
 
-    if (in->header.dataSize != sizeof(in->data.networkGetAutostartRequest))
-        return -1;
-
     autostart = 0;
 
     ret = qemudNetworkGetAutostart(server,
-                                   in->data.networkGetAutostartRequest.uuid,
+                                   in->qemud_packet_client_data_u.networkGetAutostartRequest.uuid,
                                    &autostart);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_GET_AUTOSTART;
-        out->header.dataSize = sizeof(out->data.networkGetAutostartReply);
-        out->data.networkGetAutostartReply.autostart = (autostart != 0);
+        out->type = QEMUD_SERVER_PKT_NETWORK_GET_AUTOSTART;
+        out->qemud_packet_server_data_u.networkGetAutostartReply.autostart = (autostart != 0);
     }
     return 0;
 }
 
 static int qemudDispatchNetworkSetAutostart(struct qemud_server *server, struct qemud_client *client,
-                                            struct qemud_packet *in, struct qemud_packet *out)
+                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
 {
     int ret;
 
-    if (in->header.dataSize != sizeof(in->data.networkSetAutostartRequest))
-        return -1;
-
     ret = qemudNetworkSetAutostart(server,
-                                   in->data.networkGetAutostartRequest.uuid,
-                                   in->data.networkSetAutostartRequest.autostart);
+                                   in->qemud_packet_client_data_u.networkGetAutostartRequest.uuid,
+                                   in->qemud_packet_client_data_u.networkSetAutostartRequest.autostart);
     if (ret < 0) {
         if (qemudDispatchFailure(server, client, out) < 0)
             return -1;
     } else {
-        out->header.type = QEMUD_PKT_NETWORK_SET_AUTOSTART;
-        out->header.dataSize = 0;
+        out->type = QEMUD_SERVER_PKT_NETWORK_SET_AUTOSTART;
     }
     return 0;
 }
 
 typedef int (*clientFunc)(struct qemud_server *server, struct qemud_client *client,
-                          struct qemud_packet *in, struct qemud_packet *out);
+                          struct qemud_packet_client_data *in, struct qemud_packet_server_data *out);
 
 
 /* One per message type recorded in qemud_packet_type enum */
 
-clientFunc funcsTransmitRW[QEMUD_PKT_MAX] = {
-    NULL, /* FAILURE code */
+clientFunc funcsTransmitRW[QEMUD_CLIENT_PKT_MAX] = {
     qemudDispatchGetVersion,
     qemudDispatchGetNodeInfo,
     qemudDispatchListDomains,
@@ -1032,8 +888,7 @@
     qemudDispatchGetCapabilities,
 };
 
-clientFunc funcsTransmitRO[QEMUD_PKT_MAX] = {
-    NULL, /* FAILURE code */
+clientFunc funcsTransmitRO[QEMUD_CLIENT_PKT_MAX] = {
     qemudDispatchGetVersion,
     qemudDispatchGetNodeInfo,
     qemudDispatchListDomains,
@@ -1084,22 +939,18 @@
  * incoming type, or is QEMUD_PKT_FAILURE
  */
 int qemudDispatch(struct qemud_server *server, struct qemud_client *client,
-                  struct qemud_packet *in, struct qemud_packet *out) {
+                  qemud_packet_client_data *in, qemud_packet_server_data *out) {
     clientFunc *funcs;
-    unsigned int type = in->header.type;
-    qemudDebug("> Dispatching request %d readonly ? %d", type, client->readonly);
+    unsigned int type = in->type;
+    qemudDebug("> Dispatching request type %d, readonly ? %d",
+               in->type, client->readonly);
 
     server->errorCode = 0;
     server->errorMessage[0] = '\0';
 
-    memset(out, 0, sizeof(struct qemud_packet));
+    memset(out, 0, sizeof(*out));
 
-    if (type >= QEMUD_PKT_MAX) {
-        qemudDebug("Illegal request type");
-        return -1;
-    }
-
-    if (type == QEMUD_PKT_FAILURE) {
+    if (type >= QEMUD_CLIENT_PKT_MAX) {
         qemudDebug("Illegal request type");
         return -1;
     }
@@ -1116,18 +967,15 @@
     } else {
         if ((funcs[type])(server, client, in, out) < 0) {
             qemudDebug("Dispatch failed");
-            return -1;
+            return 0;
         }
     }
 
-    qemudDebug("< Returning reply %d (%d bytes)",
-           out->header.type,
-           out->header.dataSize);
+    qemudDebug("< Returning reply %d", out->type);
 
     return 0;
 }
 
-
 /*
  * Local variables:
  *  indent-tabs-mode: nil
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/dispatch.h libvirt-remote/qemud/dispatch.h
--- libvirt-cvs/qemud/dispatch.h	2007-02-14 01:40:09.000000000 +0000
+++ libvirt-remote/qemud/dispatch.h	2007-04-17 11:20:22.000000000 +0100
@@ -29,7 +29,7 @@
 
 
 int qemudDispatch(struct qemud_server *server, struct qemud_client *client,
-                  struct qemud_packet *in, struct qemud_packet *out);
+                  struct qemud_packet_client_data *in, struct qemud_packet_server_data *out);
 
 #endif
 
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/internal.h libvirt-remote/qemud/internal.h
--- libvirt-cvs/qemud/internal.h	2007-04-12 15:18:13.000000000 +0100
+++ libvirt-remote/qemud/internal.h	2007-04-23 15:33:33.000000000 +0100
@@ -29,6 +29,7 @@
 #include <netinet/in.h>
 
 #include "protocol.h"
+#include "remote_protocol.h"
 #include "bridge.h"
 #include "iptables.h"
 
@@ -58,15 +59,6 @@
 #endif
 } qemudLogPriority;
 
-typedef enum {
-    QEMUD_DIR_CONFIG = 0,
-    QEMUD_DIR_AUTOSTART,
-    QEMUD_DIR_NETWORK_CONFIG,
-    QEMUD_DIR_NETWORK_AUTOSTART,
-
-    QEMUD_N_CONFIG_DIRS
-} qemudConfigDirType;
-
 /* Different types of QEMU acceleration possible */
 enum qemud_vm_virt_type {
     QEMUD_VIRT_QEMU,
@@ -273,18 +265,39 @@
     struct qemud_network *next;
 };
 
+
+enum {
+    QEMUD_MODE_RX_HEADER,
+    QEMUD_MODE_RX_PAYLOAD,
+    QEMUD_MODE_TX_PACKET,
+};
+
 /* Stores the per-client connection state */
 struct qemud_client {
+    int magic;
+
     int fd;
     int readonly;
-    struct qemud_packet incoming;
-    unsigned int incomingReceived;
-    struct qemud_packet outgoing;
-    unsigned int outgoingSent;
-    int tx;
+    int mode;
+
+    unsigned int incomingSerial;
+    unsigned int outgoingSerial;
+
+    char buffer [REMOTE_MESSAGE_MAX];
+    unsigned int bufferLength;
+    unsigned int bufferOffset;
+
+    /* This is only valid if a remote open call has been made on this
+     * connection, otherwise it will be NULL.  Also if remote close is
+     * called, it will be set back to NULL if that succeeds.
+     */
+    virConnectPtr conn;
+
     struct qemud_client *next;
 };
 
+#define QEMUD_CLIENT_MAGIC 0x7788aaee
+
 
 struct qemud_socket {
     int fd;
@@ -311,7 +324,6 @@
     struct qemud_network *networks;
     brControl *brctl;
     iptablesContext *iptables;
-    char configDirs[QEMUD_N_CONFIG_DIRS][PATH_MAX];
     char *configDir;
     char *autostartDir;
     char *networkConfigDir;
@@ -342,6 +354,9 @@
 #define qemudDebug(fmt, ...) do {} while(0)
 #endif
 
+void remoteDispatchClientRequest (struct qemud_server *server,
+                                  struct qemud_client *client);
+
 static inline int
 qemudIsActiveVM(struct qemud_vm *vm)
 {
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/Makefile.am libvirt-remote/qemud/Makefile.am
--- libvirt-cvs/qemud/Makefile.am	2007-04-04 15:39:43.000000000 +0100
+++ libvirt-remote/qemud/Makefile.am	2007-04-23 12:31:52.000000000 +0100
@@ -5,23 +5,28 @@
 
 sbin_PROGRAMS = libvirt_qemud
 
-libvirt_qemud_SOURCES = qemud.c internal.h protocol.h \
+libvirt_qemud_SOURCES = \
+		qemud.c internal.h \
                 driver.c driver.h \
                 dispatch.c dispatch.h \
                 conf.c conf.h \
                 bridge.c bridge.h \
                 iptables.c iptables.h \
                 uuid.c uuid.h \
-		buf.c buf.h
+		buf.c buf.h \
+		protocol.h protocol.c \
+		remote_protocol.h remote_protocol.c \
+		remote.c
 #-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_POSIX_C_SOURCE=199506L
-libvirt_qemud_CFLAGS = \
+libvirt_qemud_CFLAGS = -g \
         -I$(top_srcdir)/include -I$(top_builddir)/include $(LIBXML_CFLAGS) \
         $(WARN_CFLAGS) -DLOCAL_STATE_DIR="\"$(localstatedir)\"" \
         -DSYSCONF_DIR="\"$(sysconfdir)\"" \
-	-DQEMUD_PID_FILE="\"$(QEMUD_PID_FILE)\""
+	-DQEMUD_PID_FILE="\"$(QEMUD_PID_FILE)\"" \
+	-DREMOTE_PID_FILE="\"$(REMOTE_PID_FILE)\""
 libvirt_qemud_LDFLAGS = $(LIBXML_LIBS) $(SYSFS_LIBS)
-libvirt_qemud_DEPENDENCIES =
-libvirt_qemud_LDADD =
+libvirt_qemud_DEPENDENCIES = ../src/libvirt.la
+libvirt_qemud_LDADD = ../src/libvirt.la
 
 install-data-local:
 	mkdir -p $(DESTDIR)$(sysconfdir)/libvirt/qemu/networks/autostart
@@ -39,7 +44,25 @@
 	rmdir $(DESTDIR)$(localstatedir)/run/libvirt || :
 	rmdir $(DESTDIR)$(localstatedir)/lib/libvirt || :
 
-EXTRA_DIST = libvirtd.in default-network.xml
+# Distribute the generated files so that rpcgen isn't required on the
+# target machine (although almost any Unix machine will have it).
+EXTRA_DIST = libvirtd.in default-network.xml \
+	protocol.x remote_protocol.x \
+	protocol.c protocol.h \
+	remote_protocol.c remote_protocol.h
+
+.x.c:
+	rm -f $@
+	rpcgen -c -o $@ $<
+	mv $@ $@.bak
+	perl -w rpcgen_fix.pl < $@.bak > $@
+
+.x.h:
+	rm -f $@
+	rpcgen -h -o $@ $<
+
+protocol.c: protocol.h
+remote_protocol.c: remote_protocol.h
 
 if LIBVIRT_INIT_SCRIPTS_RED_HAT
 initdir = $(sysconfdir)/rc.d/init.d
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/protocol.c libvirt-remote/qemud/protocol.c
--- libvirt-cvs/qemud/protocol.c	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-remote/qemud/protocol.c	2007-04-17 17:40:30.000000000 +0100
@@ -0,0 +1,969 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "protocol.h"
+
+bool_t
+xdr_qemud_domain_runstate (XDR *xdrs, qemud_domain_runstate *objp)
+{
+
+	 if (!xdr_enum (xdrs, (enum_t *) objp))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_client_data_type (XDR *xdrs, qemud_packet_client_data_type *objp)
+{
+
+	 if (!xdr_enum (xdrs, (enum_t *) objp))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_server_data_type (XDR *xdrs, qemud_packet_server_data_type *objp)
+{
+
+	 if (!xdr_enum (xdrs, (enum_t *) objp))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_failure_reply (XDR *xdrs, qemud_packet_failure_reply *objp)
+{
+
+	 if (!xdr_uint32_t (xdrs, &objp->code))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->message, QEMUD_MAX_ERROR_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_get_version_reply (XDR *xdrs, qemud_packet_get_version_reply *objp)
+{
+
+	 if (!xdr_uint32_t (xdrs, &objp->versionNum))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_get_node_info_reply (XDR *xdrs, qemud_packet_get_node_info_reply *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->model, 32,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->memory))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->cpus))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->mhz))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->nodes))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->sockets))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->cores))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->threads))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_get_capabilities_reply (XDR *xdrs, qemud_packet_get_capabilities_reply *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->xml, QEMUD_MAX_XML_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_list_domains_reply (XDR *xdrs, qemud_packet_list_domains_reply *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->numDomains))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->domains, QEMUD_MAX_NUM_DOMAINS,
+		sizeof (int32_t), (xdrproc_t) xdr_int32_t))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_num_domains_reply (XDR *xdrs, qemud_packet_num_domains_reply *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->numDomains))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_create_request (XDR *xdrs, qemud_packet_domain_create_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->xml, QEMUD_MAX_XML_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_create_reply (XDR *xdrs, qemud_packet_domain_create_reply *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->id))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->name, QEMUD_MAX_NAME_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_lookup_by_id_request (XDR *xdrs, qemud_packet_domain_lookup_by_id_request *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->id))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_lookup_by_id_reply (XDR *xdrs, qemud_packet_domain_lookup_by_id_reply *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->name, QEMUD_MAX_NAME_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_lookup_by_name_request (XDR *xdrs, qemud_packet_domain_lookup_by_name_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->name, QEMUD_MAX_NAME_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_lookup_by_name_reply (XDR *xdrs, qemud_packet_domain_lookup_by_name_reply *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->id))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_lookup_by_uuid_request (XDR *xdrs, qemud_packet_domain_lookup_by_uuid_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_lookup_by_uuid_reply (XDR *xdrs, qemud_packet_domain_lookup_by_uuid_reply *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->id))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->name, QEMUD_MAX_NAME_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_suspend_request (XDR *xdrs, qemud_packet_domain_suspend_request *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->id))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_resume_request (XDR *xdrs, qemud_packet_domain_resume_request *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->id))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_destroy_request (XDR *xdrs, qemud_packet_domain_destroy_request *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->id))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_get_info_request (XDR *xdrs, qemud_packet_domain_get_info_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_get_info_reply (XDR *xdrs, qemud_packet_domain_get_info_reply *objp)
+{
+
+	 if (!xdr_uint64_t (xdrs, &objp->cpuTime))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->runstate))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->memory))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->maxmem))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->nrVirtCpu))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_save_request (XDR *xdrs, qemud_packet_domain_save_request *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->id))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->file, PATH_MAX,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_restore_request (XDR *xdrs, qemud_packet_domain_restore_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->file, PATH_MAX,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_restore_reply (XDR *xdrs, qemud_packet_domain_restore_reply *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->id))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_dump_xml_request (XDR *xdrs, qemud_packet_domain_dump_xml_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_dump_xml_reply (XDR *xdrs, qemud_packet_domain_dump_xml_reply *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->xml, QEMUD_MAX_XML_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_list_defined_domains_reply (XDR *xdrs, qemud_packet_list_defined_domains_reply *objp)
+{
+
+	 if (!xdr_uint32_t (xdrs, &objp->numDomains))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->domains, QEMUD_MAX_DOMAINS_NAME_BUF,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_num_defined_domains_reply (XDR *xdrs, qemud_packet_num_defined_domains_reply *objp)
+{
+
+	 if (!xdr_uint32_t (xdrs, &objp->numDomains))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_start_request (XDR *xdrs, qemud_packet_domain_start_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_start_reply (XDR *xdrs, qemud_packet_domain_start_reply *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->id))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_define_request (XDR *xdrs, qemud_packet_domain_define_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->xml, QEMUD_MAX_XML_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_define_reply (XDR *xdrs, qemud_packet_domain_define_reply *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->name, QEMUD_MAX_NAME_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_undefine_request (XDR *xdrs, qemud_packet_domain_undefine_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_num_networks_reply (XDR *xdrs, qemud_packet_num_networks_reply *objp)
+{
+
+	 if (!xdr_uint32_t (xdrs, &objp->numNetworks))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_list_networks_reply (XDR *xdrs, qemud_packet_list_networks_reply *objp)
+{
+
+	 if (!xdr_uint32_t (xdrs, &objp->numNetworks))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->networks, QEMUD_MAX_NETWORKS_NAME_BUF,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_num_defined_networks_reply (XDR *xdrs, qemud_packet_num_defined_networks_reply *objp)
+{
+
+	 if (!xdr_uint32_t (xdrs, &objp->numNetworks))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_list_defined_networks_reply (XDR *xdrs, qemud_packet_list_defined_networks_reply *objp)
+{
+
+	 if (!xdr_uint32_t (xdrs, &objp->numNetworks))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->networks, QEMUD_MAX_NETWORKS_NAME_BUF,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_lookup_by_name_request (XDR *xdrs, qemud_packet_network_lookup_by_name_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->name, QEMUD_MAX_NAME_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_lookup_by_name_reply (XDR *xdrs, qemud_packet_network_lookup_by_name_reply *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->id))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_lookup_by_uuid_request (XDR *xdrs, qemud_packet_network_lookup_by_uuid_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_lookup_by_uuid_reply (XDR *xdrs, qemud_packet_network_lookup_by_uuid_reply *objp)
+{
+
+	 if (!xdr_int32_t (xdrs, &objp->id))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->name, QEMUD_MAX_NAME_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_create_request (XDR *xdrs, qemud_packet_network_create_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->xml, QEMUD_MAX_XML_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_create_reply (XDR *xdrs, qemud_packet_network_create_reply *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->name, QEMUD_MAX_NAME_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_define_request (XDR *xdrs, qemud_packet_network_define_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->xml, QEMUD_MAX_XML_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_define_reply (XDR *xdrs, qemud_packet_network_define_reply *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	 if (!xdr_vector (xdrs, (char *)objp->name, QEMUD_MAX_NAME_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_undefine_request (XDR *xdrs, qemud_packet_network_undefine_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_start_request (XDR *xdrs, qemud_packet_network_start_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_destroy_request (XDR *xdrs, qemud_packet_network_destroy_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_dump_xml_request (XDR *xdrs, qemud_packet_network_dump_xml_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_dump_xml_reply (XDR *xdrs, qemud_packet_network_dump_xml_reply *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->xml, QEMUD_MAX_XML_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_get_bridge_name_request (XDR *xdrs, qemud_packet_network_get_bridge_name_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_get_bridge_name_reply (XDR *xdrs, qemud_packet_network_get_bridge_name_reply *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->ifname, QEMUD_MAX_IFNAME_LEN,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_get_autostart_request (XDR *xdrs, qemud_packet_domain_get_autostart_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_get_autostart_reply (XDR *xdrs, qemud_packet_domain_get_autostart_reply *objp)
+{
+
+	 if (!xdr_uint32_t (xdrs, &objp->autostart))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_domain_set_autostart_request (XDR *xdrs, qemud_packet_domain_set_autostart_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->autostart))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_get_autostart_request (XDR *xdrs, qemud_packet_network_get_autostart_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_get_autostart_reply (XDR *xdrs, qemud_packet_network_get_autostart_reply *objp)
+{
+
+	 if (!xdr_uint32_t (xdrs, &objp->autostart))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_network_set_autostart_request (XDR *xdrs, qemud_packet_network_set_autostart_request *objp)
+{
+
+	 if (!xdr_vector (xdrs, (char *)objp->uuid, QEMUD_UUID_RAW_LEN,
+		sizeof (u_char), (xdrproc_t) xdr_u_char))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->autostart))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_client_data (XDR *xdrs, qemud_packet_client_data *objp)
+{
+
+	 if (!xdr_qemud_packet_client_data_type (xdrs, &objp->type))
+		 return FALSE;
+	switch (objp->type) {
+	case QEMUD_CLIENT_PKT_GET_VERSION:
+		break;
+	case QEMUD_CLIENT_PKT_GET_NODEINFO:
+		break;
+	case QEMUD_CLIENT_PKT_LIST_DOMAINS:
+		break;
+	case QEMUD_CLIENT_PKT_NUM_DOMAINS:
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_CREATE:
+		 if (!xdr_qemud_packet_domain_create_request (xdrs, &objp->qemud_packet_client_data_u.domainCreateRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_ID:
+		 if (!xdr_qemud_packet_domain_lookup_by_id_request (xdrs, &objp->qemud_packet_client_data_u.domainLookupByIDRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_UUID:
+		 if (!xdr_qemud_packet_domain_lookup_by_uuid_request (xdrs, &objp->qemud_packet_client_data_u.domainLookupByUUIDRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_NAME:
+		 if (!xdr_qemud_packet_domain_lookup_by_name_request (xdrs, &objp->qemud_packet_client_data_u.domainLookupByNameRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_SUSPEND:
+		 if (!xdr_qemud_packet_domain_suspend_request (xdrs, &objp->qemud_packet_client_data_u.domainSuspendRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_RESUME:
+		 if (!xdr_qemud_packet_domain_resume_request (xdrs, &objp->qemud_packet_client_data_u.domainResumeRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_DESTROY:
+		 if (!xdr_qemud_packet_domain_destroy_request (xdrs, &objp->qemud_packet_client_data_u.domainDestroyRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_GET_INFO:
+		 if (!xdr_qemud_packet_domain_get_info_request (xdrs, &objp->qemud_packet_client_data_u.domainGetInfoRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_SAVE:
+		 if (!xdr_qemud_packet_domain_save_request (xdrs, &objp->qemud_packet_client_data_u.domainSaveRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_RESTORE:
+		 if (!xdr_qemud_packet_domain_restore_request (xdrs, &objp->qemud_packet_client_data_u.domainRestoreRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DUMP_XML:
+		 if (!xdr_qemud_packet_domain_dump_xml_request (xdrs, &objp->qemud_packet_client_data_u.domainDumpXMLRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_LIST_DEFINED_DOMAINS:
+		break;
+	case QEMUD_CLIENT_PKT_NUM_DEFINED_DOMAINS:
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_START:
+		 if (!xdr_qemud_packet_domain_start_request (xdrs, &objp->qemud_packet_client_data_u.domainStartRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_DEFINE:
+		 if (!xdr_qemud_packet_domain_define_request (xdrs, &objp->qemud_packet_client_data_u.domainDefineRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_UNDEFINE:
+		 if (!xdr_qemud_packet_domain_undefine_request (xdrs, &objp->qemud_packet_client_data_u.domainUndefineRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_NUM_NETWORKS:
+		break;
+	case QEMUD_CLIENT_PKT_LIST_NETWORKS:
+		break;
+	case QEMUD_CLIENT_PKT_NUM_DEFINED_NETWORKS:
+		break;
+	case QEMUD_CLIENT_PKT_LIST_DEFINED_NETWORKS:
+		break;
+	case QEMUD_CLIENT_PKT_NETWORK_LOOKUP_BY_UUID:
+		 if (!xdr_qemud_packet_network_lookup_by_uuid_request (xdrs, &objp->qemud_packet_client_data_u.networkLookupByUUIDRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_NETWORK_LOOKUP_BY_NAME:
+		 if (!xdr_qemud_packet_network_lookup_by_name_request (xdrs, &objp->qemud_packet_client_data_u.networkLookupByNameRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_NETWORK_CREATE:
+		 if (!xdr_qemud_packet_network_create_request (xdrs, &objp->qemud_packet_client_data_u.networkCreateRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_NETWORK_DEFINE:
+		 if (!xdr_qemud_packet_network_define_request (xdrs, &objp->qemud_packet_client_data_u.networkDefineRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_NETWORK_UNDEFINE:
+		 if (!xdr_qemud_packet_network_undefine_request (xdrs, &objp->qemud_packet_client_data_u.networkUndefineRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_NETWORK_START:
+		 if (!xdr_qemud_packet_network_start_request (xdrs, &objp->qemud_packet_client_data_u.networkStartRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_NETWORK_DESTROY:
+		 if (!xdr_qemud_packet_network_destroy_request (xdrs, &objp->qemud_packet_client_data_u.networkDestroyRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_NETWORK_DUMP_XML:
+		 if (!xdr_qemud_packet_network_dump_xml_request (xdrs, &objp->qemud_packet_client_data_u.networkDumpXMLRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_NETWORK_GET_BRIDGE_NAME:
+		 if (!xdr_qemud_packet_network_get_bridge_name_request (xdrs, &objp->qemud_packet_client_data_u.networkGetBridgeNameRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_GET_AUTOSTART:
+		 if (!xdr_qemud_packet_domain_get_autostart_request (xdrs, &objp->qemud_packet_client_data_u.domainGetAutostartRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_DOMAIN_SET_AUTOSTART:
+		 if (!xdr_qemud_packet_domain_set_autostart_request (xdrs, &objp->qemud_packet_client_data_u.domainSetAutostartRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_NETWORK_GET_AUTOSTART:
+		 if (!xdr_qemud_packet_network_get_autostart_request (xdrs, &objp->qemud_packet_client_data_u.networkGetAutostartRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_NETWORK_SET_AUTOSTART:
+		 if (!xdr_qemud_packet_network_set_autostart_request (xdrs, &objp->qemud_packet_client_data_u.networkSetAutostartRequest))
+			 return FALSE;
+		break;
+	case QEMUD_CLIENT_PKT_GET_CAPABILITIES:
+		break;
+	default:
+		return FALSE;
+	}
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_server_data (XDR *xdrs, qemud_packet_server_data *objp)
+{
+
+	 if (!xdr_qemud_packet_server_data_type (xdrs, &objp->type))
+		 return FALSE;
+	switch (objp->type) {
+	case QEMUD_SERVER_PKT_FAILURE:
+		 if (!xdr_qemud_packet_failure_reply (xdrs, &objp->qemud_packet_server_data_u.failureReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_GET_VERSION:
+		 if (!xdr_qemud_packet_get_version_reply (xdrs, &objp->qemud_packet_server_data_u.getVersionReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_GET_NODEINFO:
+		 if (!xdr_qemud_packet_get_node_info_reply (xdrs, &objp->qemud_packet_server_data_u.getNodeInfoReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_LIST_DOMAINS:
+		 if (!xdr_qemud_packet_list_domains_reply (xdrs, &objp->qemud_packet_server_data_u.listDomainsReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_NUM_DOMAINS:
+		 if (!xdr_qemud_packet_num_domains_reply (xdrs, &objp->qemud_packet_server_data_u.numDomainsReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_CREATE:
+		 if (!xdr_qemud_packet_domain_create_reply (xdrs, &objp->qemud_packet_server_data_u.domainCreateReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_ID:
+		 if (!xdr_qemud_packet_domain_lookup_by_id_reply (xdrs, &objp->qemud_packet_server_data_u.domainLookupByIDReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_UUID:
+		 if (!xdr_qemud_packet_domain_lookup_by_uuid_reply (xdrs, &objp->qemud_packet_server_data_u.domainLookupByUUIDReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_NAME:
+		 if (!xdr_qemud_packet_domain_lookup_by_name_reply (xdrs, &objp->qemud_packet_server_data_u.domainLookupByNameReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_SUSPEND:
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_RESUME:
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_DESTROY:
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_GET_INFO:
+		 if (!xdr_qemud_packet_domain_get_info_reply (xdrs, &objp->qemud_packet_server_data_u.domainGetInfoReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_SAVE:
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_RESTORE:
+		 if (!xdr_qemud_packet_domain_restore_reply (xdrs, &objp->qemud_packet_server_data_u.domainRestoreReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_DUMP_XML:
+		 if (!xdr_qemud_packet_domain_dump_xml_reply (xdrs, &objp->qemud_packet_server_data_u.domainDumpXMLReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_LIST_DEFINED_DOMAINS:
+		 if (!xdr_qemud_packet_list_defined_domains_reply (xdrs, &objp->qemud_packet_server_data_u.listDefinedDomainsReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_NUM_DEFINED_DOMAINS:
+		 if (!xdr_qemud_packet_num_defined_domains_reply (xdrs, &objp->qemud_packet_server_data_u.numDefinedDomainsReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_START:
+		 if (!xdr_qemud_packet_domain_start_reply (xdrs, &objp->qemud_packet_server_data_u.domainStartReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_DEFINE:
+		 if (!xdr_qemud_packet_domain_define_reply (xdrs, &objp->qemud_packet_server_data_u.domainDefineReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_UNDEFINE:
+		break;
+	case QEMUD_SERVER_PKT_NUM_NETWORKS:
+		 if (!xdr_qemud_packet_num_networks_reply (xdrs, &objp->qemud_packet_server_data_u.numNetworksReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_LIST_NETWORKS:
+		 if (!xdr_qemud_packet_list_networks_reply (xdrs, &objp->qemud_packet_server_data_u.listNetworksReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_NUM_DEFINED_NETWORKS:
+		 if (!xdr_qemud_packet_num_defined_networks_reply (xdrs, &objp->qemud_packet_server_data_u.numDefinedNetworksReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_LIST_DEFINED_NETWORKS:
+		 if (!xdr_qemud_packet_list_defined_networks_reply (xdrs, &objp->qemud_packet_server_data_u.listDefinedNetworksReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_UUID:
+		 if (!xdr_qemud_packet_network_lookup_by_uuid_reply (xdrs, &objp->qemud_packet_server_data_u.networkLookupByUUIDReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_NAME:
+		 if (!xdr_qemud_packet_network_lookup_by_name_reply (xdrs, &objp->qemud_packet_server_data_u.networkLookupByNameReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_NETWORK_CREATE:
+		 if (!xdr_qemud_packet_network_create_reply (xdrs, &objp->qemud_packet_server_data_u.networkCreateReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_NETWORK_DEFINE:
+		 if (!xdr_qemud_packet_network_define_reply (xdrs, &objp->qemud_packet_server_data_u.networkDefineReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_NETWORK_UNDEFINE:
+		break;
+	case QEMUD_SERVER_PKT_NETWORK_START:
+		break;
+	case QEMUD_SERVER_PKT_NETWORK_DESTROY:
+		break;
+	case QEMUD_SERVER_PKT_NETWORK_DUMP_XML:
+		 if (!xdr_qemud_packet_network_dump_xml_reply (xdrs, &objp->qemud_packet_server_data_u.networkDumpXMLReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_NETWORK_GET_BRIDGE_NAME:
+		 if (!xdr_qemud_packet_network_get_bridge_name_reply (xdrs, &objp->qemud_packet_server_data_u.networkGetBridgeNameReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_GET_AUTOSTART:
+		 if (!xdr_qemud_packet_domain_get_autostart_reply (xdrs, &objp->qemud_packet_server_data_u.domainGetAutostartReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_DOMAIN_SET_AUTOSTART:
+		break;
+	case QEMUD_SERVER_PKT_NETWORK_GET_AUTOSTART:
+		 if (!xdr_qemud_packet_network_get_autostart_reply (xdrs, &objp->qemud_packet_server_data_u.networkGetAutostartReply))
+			 return FALSE;
+		break;
+	case QEMUD_SERVER_PKT_NETWORK_SET_AUTOSTART:
+		break;
+	case QEMUD_SERVER_PKT_GET_CAPABILITIES:
+		 if (!xdr_qemud_packet_get_capabilities_reply (xdrs, &objp->qemud_packet_server_data_u.getCapabilitiesReply))
+			 return FALSE;
+		break;
+	default:
+		return FALSE;
+	}
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_client (XDR *xdrs, qemud_packet_client *objp)
+{
+
+	 if (!xdr_uint32_t (xdrs, &objp->serial))
+		 return FALSE;
+	 if (!xdr_qemud_packet_client_data (xdrs, &objp->data))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_server (XDR *xdrs, qemud_packet_server *objp)
+{
+
+	 if (!xdr_uint32_t (xdrs, &objp->serial))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->inReplyTo))
+		 return FALSE;
+	 if (!xdr_qemud_packet_server_data (xdrs, &objp->data))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_qemud_packet_header (XDR *xdrs, qemud_packet_header *objp)
+{
+
+	 if (!xdr_uint32_t (xdrs, &objp->length))
+		 return FALSE;
+	 if (!xdr_uint32_t (xdrs, &objp->prog))
+		 return FALSE;
+	return TRUE;
+}
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/protocol.h libvirt-remote/qemud/protocol.h
--- libvirt-cvs/qemud/protocol.h	2007-03-22 13:44:57.000000000 +0000
+++ libvirt-remote/qemud/protocol.h	2007-04-17 17:38:48.000000000 +0100
@@ -1,329 +1,660 @@
 /*
- * protocol.h: wire protocol message format & data structures
- *
- * Copyright (C) 2006, 2007 Red Hat, Inc.
- * Copyright (C) 2006 Daniel P. Berrange
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
- *
- * Author: Daniel P. Berrange <berrange@xxxxxxxxxx>
+ * Please do not edit this file.
+ * It was generated using rpcgen.
  */
 
+#ifndef _PROTOCOL_H_RPCGEN
+#define _PROTOCOL_H_RPCGEN
 
-#ifndef QEMUD_PROTOCOL_H__
-#define QEMUD_PROTOCOL_H__
+#include <rpc/rpc.h>
 
-#include <stdint.h>
-#include <net/if.h> /* for IF_NAMESIZE */
 
-/* List of different packet types which can be sent */
-enum qemud_packet_type {
-    QEMUD_PKT_FAILURE = 0,
-    QEMUD_PKT_GET_VERSION,
-    QEMUD_PKT_GET_NODEINFO,
-    QEMUD_PKT_LIST_DOMAINS,
-    QEMUD_PKT_NUM_DOMAINS,
-    QEMUD_PKT_DOMAIN_CREATE,
-    QEMUD_PKT_DOMAIN_LOOKUP_BY_ID,
-    QEMUD_PKT_DOMAIN_LOOKUP_BY_UUID,
-    QEMUD_PKT_DOMAIN_LOOKUP_BY_NAME,
-    QEMUD_PKT_DOMAIN_SUSPEND,
-    QEMUD_PKT_DOMAIN_RESUME,
-    QEMUD_PKT_DOMAIN_DESTROY,
-    QEMUD_PKT_DOMAIN_GET_INFO,
-    QEMUD_PKT_DOMAIN_SAVE,
-    QEMUD_PKT_DOMAIN_RESTORE,
-    QEMUD_PKT_DUMP_XML,
-    QEMUD_PKT_LIST_DEFINED_DOMAINS,
-    QEMUD_PKT_NUM_DEFINED_DOMAINS,
-    QEMUD_PKT_DOMAIN_START,
-    QEMUD_PKT_DOMAIN_DEFINE,
-    QEMUD_PKT_DOMAIN_UNDEFINE,
-    QEMUD_PKT_NUM_NETWORKS,
-    QEMUD_PKT_LIST_NETWORKS,
-    QEMUD_PKT_NUM_DEFINED_NETWORKS,
-    QEMUD_PKT_LIST_DEFINED_NETWORKS,
-    QEMUD_PKT_NETWORK_LOOKUP_BY_UUID,
-    QEMUD_PKT_NETWORK_LOOKUP_BY_NAME,
-    QEMUD_PKT_NETWORK_CREATE,
-    QEMUD_PKT_NETWORK_DEFINE,
-    QEMUD_PKT_NETWORK_UNDEFINE,
-    QEMUD_PKT_NETWORK_START,
-    QEMUD_PKT_NETWORK_DESTROY,
-    QEMUD_PKT_NETWORK_DUMP_XML,
-    QEMUD_PKT_NETWORK_GET_BRIDGE_NAME,
-    QEMUD_PKT_DOMAIN_GET_AUTOSTART,
-    QEMUD_PKT_DOMAIN_SET_AUTOSTART,
-    QEMUD_PKT_NETWORK_GET_AUTOSTART,
-    QEMUD_PKT_NETWORK_SET_AUTOSTART,
-    QEMUD_PKT_GET_CAPABILITIES,
-
-    QEMUD_PKT_MAX,
-};
-
-
-#define QEMUD_PROTOCOL_VERSION_MAJOR 1
-#define QEMUD_PROTOCOL_VERSION_MINOR 0
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 #define QEMUD_UUID_RAW_LEN 16
 #define QEMUD_MAX_NAME_LEN 50
 #define QEMUD_MAX_XML_LEN 4096
-#define QEMUD_MAX_IFNAME_LEN IF_NAMESIZE
+#define QEMUD_MAX_IFNAME_LEN 50
 #define QEMUD_MAX_NUM_DOMAINS 100
 #define QEMUD_MAX_NUM_NETWORKS 100
+#define QEMUD_MAX_DOMAINS_NAME_BUF 5000
+#define QEMUD_MAX_NETWORKS_NAME_BUF 5000
 #define QEMUD_MAX_ERROR_LEN 1024
 
-/* Possible guest VM states */
 enum qemud_domain_runstate {
-    QEMUD_STATE_RUNNING = 1,
-    QEMUD_STATE_PAUSED,
-    QEMUD_STATE_STOPPED,
+	QEMUD_STATE_RUNNING = 1,
+	QEMUD_STATE_PAUSED = 1 + 1,
+	QEMUD_STATE_STOPPED = 1 + 2,
+};
+typedef enum qemud_domain_runstate qemud_domain_runstate;
+
+enum qemud_packet_client_data_type {
+	QEMUD_CLIENT_PKT_GET_VERSION = 0,
+	QEMUD_CLIENT_PKT_GET_NODEINFO = 1,
+	QEMUD_CLIENT_PKT_LIST_DOMAINS = 2,
+	QEMUD_CLIENT_PKT_NUM_DOMAINS = 3,
+	QEMUD_CLIENT_PKT_DOMAIN_CREATE = 4,
+	QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_ID = 5,
+	QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_UUID = 6,
+	QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_NAME = 7,
+	QEMUD_CLIENT_PKT_DOMAIN_SUSPEND = 8,
+	QEMUD_CLIENT_PKT_DOMAIN_RESUME = 9,
+	QEMUD_CLIENT_PKT_DOMAIN_DESTROY = 10,
+	QEMUD_CLIENT_PKT_DOMAIN_GET_INFO = 11,
+	QEMUD_CLIENT_PKT_DOMAIN_SAVE = 12,
+	QEMUD_CLIENT_PKT_DOMAIN_RESTORE = 13,
+	QEMUD_CLIENT_PKT_DUMP_XML = 14,
+	QEMUD_CLIENT_PKT_LIST_DEFINED_DOMAINS = 15,
+	QEMUD_CLIENT_PKT_NUM_DEFINED_DOMAINS = 16,
+	QEMUD_CLIENT_PKT_DOMAIN_START = 17,
+	QEMUD_CLIENT_PKT_DOMAIN_DEFINE = 18,
+	QEMUD_CLIENT_PKT_DOMAIN_UNDEFINE = 19,
+	QEMUD_CLIENT_PKT_NUM_NETWORKS = 20,
+	QEMUD_CLIENT_PKT_LIST_NETWORKS = 21,
+	QEMUD_CLIENT_PKT_NUM_DEFINED_NETWORKS = 22,
+	QEMUD_CLIENT_PKT_LIST_DEFINED_NETWORKS = 23,
+	QEMUD_CLIENT_PKT_NETWORK_LOOKUP_BY_UUID = 24,
+	QEMUD_CLIENT_PKT_NETWORK_LOOKUP_BY_NAME = 25,
+	QEMUD_CLIENT_PKT_NETWORK_CREATE = 26,
+	QEMUD_CLIENT_PKT_NETWORK_DEFINE = 27,
+	QEMUD_CLIENT_PKT_NETWORK_UNDEFINE = 28,
+	QEMUD_CLIENT_PKT_NETWORK_START = 29,
+	QEMUD_CLIENT_PKT_NETWORK_DESTROY = 30,
+	QEMUD_CLIENT_PKT_NETWORK_DUMP_XML = 31,
+	QEMUD_CLIENT_PKT_NETWORK_GET_BRIDGE_NAME = 32,
+	QEMUD_CLIENT_PKT_DOMAIN_GET_AUTOSTART = 33,
+	QEMUD_CLIENT_PKT_DOMAIN_SET_AUTOSTART = 34,
+	QEMUD_CLIENT_PKT_NETWORK_GET_AUTOSTART = 35,
+	QEMUD_CLIENT_PKT_NETWORK_SET_AUTOSTART = 36,
+	QEMUD_CLIENT_PKT_GET_CAPABILITIES = 37,
+	QEMUD_CLIENT_PKT_MAX = 38,
+};
+typedef enum qemud_packet_client_data_type qemud_packet_client_data_type;
+
+enum qemud_packet_server_data_type {
+	QEMUD_SERVER_PKT_FAILURE = 0,
+	QEMUD_SERVER_PKT_GET_VERSION = 0 + 1,
+	QEMUD_SERVER_PKT_GET_NODEINFO = 0 + 2,
+	QEMUD_SERVER_PKT_LIST_DOMAINS = 0 + 3,
+	QEMUD_SERVER_PKT_NUM_DOMAINS = 0 + 4,
+	QEMUD_SERVER_PKT_DOMAIN_CREATE = 0 + 5,
+	QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_ID = 0 + 6,
+	QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_UUID = 0 + 7,
+	QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_NAME = 0 + 8,
+	QEMUD_SERVER_PKT_DOMAIN_SUSPEND = 0 + 9,
+	QEMUD_SERVER_PKT_DOMAIN_RESUME = 0 + 10,
+	QEMUD_SERVER_PKT_DOMAIN_DESTROY = 0 + 11,
+	QEMUD_SERVER_PKT_DOMAIN_GET_INFO = 0 + 12,
+	QEMUD_SERVER_PKT_DOMAIN_SAVE = 0 + 13,
+	QEMUD_SERVER_PKT_DOMAIN_RESTORE = 0 + 14,
+	QEMUD_SERVER_PKT_DUMP_XML = 0 + 15,
+	QEMUD_SERVER_PKT_LIST_DEFINED_DOMAINS = 0 + 16,
+	QEMUD_SERVER_PKT_NUM_DEFINED_DOMAINS = 0 + 17,
+	QEMUD_SERVER_PKT_DOMAIN_START = 0 + 18,
+	QEMUD_SERVER_PKT_DOMAIN_DEFINE = 0 + 19,
+	QEMUD_SERVER_PKT_DOMAIN_UNDEFINE = 0 + 20,
+	QEMUD_SERVER_PKT_NUM_NETWORKS = 0 + 21,
+	QEMUD_SERVER_PKT_LIST_NETWORKS = 0 + 22,
+	QEMUD_SERVER_PKT_NUM_DEFINED_NETWORKS = 0 + 23,
+	QEMUD_SERVER_PKT_LIST_DEFINED_NETWORKS = 0 + 24,
+	QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_UUID = 0 + 25,
+	QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_NAME = 0 + 26,
+	QEMUD_SERVER_PKT_NETWORK_CREATE = 0 + 27,
+	QEMUD_SERVER_PKT_NETWORK_DEFINE = 0 + 28,
+	QEMUD_SERVER_PKT_NETWORK_UNDEFINE = 0 + 29,
+	QEMUD_SERVER_PKT_NETWORK_START = 0 + 30,
+	QEMUD_SERVER_PKT_NETWORK_DESTROY = 0 + 31,
+	QEMUD_SERVER_PKT_NETWORK_DUMP_XML = 0 + 32,
+	QEMUD_SERVER_PKT_NETWORK_GET_BRIDGE_NAME = 0 + 33,
+	QEMUD_SERVER_PKT_DOMAIN_GET_AUTOSTART = 0 + 34,
+	QEMUD_SERVER_PKT_DOMAIN_SET_AUTOSTART = 0 + 35,
+	QEMUD_SERVER_PKT_NETWORK_GET_AUTOSTART = 0 + 36,
+	QEMUD_SERVER_PKT_NETWORK_SET_AUTOSTART = 0 + 37,
+	QEMUD_SERVER_PKT_GET_CAPABILITIES = 0 + 38,
+	QEMUD_SERVER_PKT_MAX = 0 + 39,
+};
+typedef enum qemud_packet_server_data_type qemud_packet_server_data_type;
+
+struct qemud_packet_failure_reply {
+	uint32_t code;
+	char message[QEMUD_MAX_ERROR_LEN];
+};
+typedef struct qemud_packet_failure_reply qemud_packet_failure_reply;
+
+struct qemud_packet_get_version_reply {
+	uint32_t versionNum;
+};
+typedef struct qemud_packet_get_version_reply qemud_packet_get_version_reply;
+
+struct qemud_packet_get_node_info_reply {
+	char model[32];
+	uint32_t memory;
+	uint32_t cpus;
+	uint32_t mhz;
+	uint32_t nodes;
+	uint32_t sockets;
+	uint32_t cores;
+	uint32_t threads;
+};
+typedef struct qemud_packet_get_node_info_reply qemud_packet_get_node_info_reply;
+
+struct qemud_packet_get_capabilities_reply {
+	char xml[QEMUD_MAX_XML_LEN];
+};
+typedef struct qemud_packet_get_capabilities_reply qemud_packet_get_capabilities_reply;
+
+struct qemud_packet_list_domains_reply {
+	int32_t numDomains;
+	int32_t domains[QEMUD_MAX_NUM_DOMAINS];
+};
+typedef struct qemud_packet_list_domains_reply qemud_packet_list_domains_reply;
+
+struct qemud_packet_num_domains_reply {
+	int32_t numDomains;
+};
+typedef struct qemud_packet_num_domains_reply qemud_packet_num_domains_reply;
+
+struct qemud_packet_domain_create_request {
+	char xml[QEMUD_MAX_XML_LEN];
+};
+typedef struct qemud_packet_domain_create_request qemud_packet_domain_create_request;
+
+struct qemud_packet_domain_create_reply {
+	int32_t id;
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+	char name[QEMUD_MAX_NAME_LEN];
+};
+typedef struct qemud_packet_domain_create_reply qemud_packet_domain_create_reply;
+
+struct qemud_packet_domain_lookup_by_id_request {
+	int32_t id;
+};
+typedef struct qemud_packet_domain_lookup_by_id_request qemud_packet_domain_lookup_by_id_request;
+
+struct qemud_packet_domain_lookup_by_id_reply {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+	char name[QEMUD_MAX_NAME_LEN];
+};
+typedef struct qemud_packet_domain_lookup_by_id_reply qemud_packet_domain_lookup_by_id_reply;
+
+struct qemud_packet_domain_lookup_by_name_request {
+	char name[QEMUD_MAX_NAME_LEN];
+};
+typedef struct qemud_packet_domain_lookup_by_name_request qemud_packet_domain_lookup_by_name_request;
+
+struct qemud_packet_domain_lookup_by_name_reply {
+	int32_t id;
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_domain_lookup_by_name_reply qemud_packet_domain_lookup_by_name_reply;
+
+struct qemud_packet_domain_lookup_by_uuid_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_domain_lookup_by_uuid_request qemud_packet_domain_lookup_by_uuid_request;
+
+struct qemud_packet_domain_lookup_by_uuid_reply {
+	int32_t id;
+	char name[QEMUD_MAX_NAME_LEN];
+};
+typedef struct qemud_packet_domain_lookup_by_uuid_reply qemud_packet_domain_lookup_by_uuid_reply;
+
+struct qemud_packet_domain_suspend_request {
+	int32_t id;
+};
+typedef struct qemud_packet_domain_suspend_request qemud_packet_domain_suspend_request;
+
+struct qemud_packet_domain_resume_request {
+	int32_t id;
+};
+typedef struct qemud_packet_domain_resume_request qemud_packet_domain_resume_request;
+
+struct qemud_packet_domain_destroy_request {
+	int32_t id;
+};
+typedef struct qemud_packet_domain_destroy_request qemud_packet_domain_destroy_request;
+
+struct qemud_packet_domain_get_info_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_domain_get_info_request qemud_packet_domain_get_info_request;
+
+struct qemud_packet_domain_get_info_reply {
+	uint64_t cpuTime;
+	uint32_t runstate;
+	uint32_t memory;
+	uint32_t maxmem;
+	uint32_t nrVirtCpu;
+};
+typedef struct qemud_packet_domain_get_info_reply qemud_packet_domain_get_info_reply;
+
+struct qemud_packet_domain_save_request {
+	int32_t id;
+	char file[PATH_MAX];
+};
+typedef struct qemud_packet_domain_save_request qemud_packet_domain_save_request;
+
+struct qemud_packet_domain_restore_request {
+	char file[PATH_MAX];
+};
+typedef struct qemud_packet_domain_restore_request qemud_packet_domain_restore_request;
+
+struct qemud_packet_domain_restore_reply {
+	int32_t id;
+};
+typedef struct qemud_packet_domain_restore_reply qemud_packet_domain_restore_reply;
+
+struct qemud_packet_domain_dump_xml_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_domain_dump_xml_request qemud_packet_domain_dump_xml_request;
+
+struct qemud_packet_domain_dump_xml_reply {
+	char xml[QEMUD_MAX_XML_LEN];
+};
+typedef struct qemud_packet_domain_dump_xml_reply qemud_packet_domain_dump_xml_reply;
+
+struct qemud_packet_list_defined_domains_reply {
+	uint32_t numDomains;
+	char domains[QEMUD_MAX_DOMAINS_NAME_BUF];
+};
+typedef struct qemud_packet_list_defined_domains_reply qemud_packet_list_defined_domains_reply;
+
+struct qemud_packet_num_defined_domains_reply {
+	uint32_t numDomains;
+};
+typedef struct qemud_packet_num_defined_domains_reply qemud_packet_num_defined_domains_reply;
+
+struct qemud_packet_domain_start_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_domain_start_request qemud_packet_domain_start_request;
+
+struct qemud_packet_domain_start_reply {
+	int32_t id;
+};
+typedef struct qemud_packet_domain_start_reply qemud_packet_domain_start_reply;
+
+struct qemud_packet_domain_define_request {
+	char xml[QEMUD_MAX_XML_LEN];
 };
+typedef struct qemud_packet_domain_define_request qemud_packet_domain_define_request;
+
+struct qemud_packet_domain_define_reply {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+	char name[QEMUD_MAX_NAME_LEN];
+};
+typedef struct qemud_packet_domain_define_reply qemud_packet_domain_define_reply;
+
+struct qemud_packet_domain_undefine_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_domain_undefine_request qemud_packet_domain_undefine_request;
+
+struct qemud_packet_num_networks_reply {
+	uint32_t numNetworks;
+};
+typedef struct qemud_packet_num_networks_reply qemud_packet_num_networks_reply;
+
+struct qemud_packet_list_networks_reply {
+	uint32_t numNetworks;
+	char networks[QEMUD_MAX_NETWORKS_NAME_BUF];
+};
+typedef struct qemud_packet_list_networks_reply qemud_packet_list_networks_reply;
+
+struct qemud_packet_num_defined_networks_reply {
+	uint32_t numNetworks;
+};
+typedef struct qemud_packet_num_defined_networks_reply qemud_packet_num_defined_networks_reply;
+
+struct qemud_packet_list_defined_networks_reply {
+	uint32_t numNetworks;
+	char networks[QEMUD_MAX_NETWORKS_NAME_BUF];
+};
+typedef struct qemud_packet_list_defined_networks_reply qemud_packet_list_defined_networks_reply;
+
+struct qemud_packet_network_lookup_by_name_request {
+	char name[QEMUD_MAX_NAME_LEN];
+};
+typedef struct qemud_packet_network_lookup_by_name_request qemud_packet_network_lookup_by_name_request;
+
+struct qemud_packet_network_lookup_by_name_reply {
+	int32_t id;
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_network_lookup_by_name_reply qemud_packet_network_lookup_by_name_reply;
+
+struct qemud_packet_network_lookup_by_uuid_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_network_lookup_by_uuid_request qemud_packet_network_lookup_by_uuid_request;
+
+struct qemud_packet_network_lookup_by_uuid_reply {
+	int32_t id;
+	char name[QEMUD_MAX_NAME_LEN];
+};
+typedef struct qemud_packet_network_lookup_by_uuid_reply qemud_packet_network_lookup_by_uuid_reply;
+
+struct qemud_packet_network_create_request {
+	char xml[QEMUD_MAX_XML_LEN];
+};
+typedef struct qemud_packet_network_create_request qemud_packet_network_create_request;
+
+struct qemud_packet_network_create_reply {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+	char name[QEMUD_MAX_NAME_LEN];
+};
+typedef struct qemud_packet_network_create_reply qemud_packet_network_create_reply;
+
+struct qemud_packet_network_define_request {
+	char xml[QEMUD_MAX_XML_LEN];
+};
+typedef struct qemud_packet_network_define_request qemud_packet_network_define_request;
+
+struct qemud_packet_network_define_reply {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+	char name[QEMUD_MAX_NAME_LEN];
+};
+typedef struct qemud_packet_network_define_reply qemud_packet_network_define_reply;
+
+struct qemud_packet_network_undefine_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_network_undefine_request qemud_packet_network_undefine_request;
+
+struct qemud_packet_network_start_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_network_start_request qemud_packet_network_start_request;
+
+struct qemud_packet_network_destroy_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_network_destroy_request qemud_packet_network_destroy_request;
+
+struct qemud_packet_network_dump_xml_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_network_dump_xml_request qemud_packet_network_dump_xml_request;
+
+struct qemud_packet_network_dump_xml_reply {
+	char xml[QEMUD_MAX_XML_LEN];
+};
+typedef struct qemud_packet_network_dump_xml_reply qemud_packet_network_dump_xml_reply;
+
+struct qemud_packet_network_get_bridge_name_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_network_get_bridge_name_request qemud_packet_network_get_bridge_name_request;
+
+struct qemud_packet_network_get_bridge_name_reply {
+	char ifname[QEMUD_MAX_IFNAME_LEN];
+};
+typedef struct qemud_packet_network_get_bridge_name_reply qemud_packet_network_get_bridge_name_reply;
+
+struct qemud_packet_domain_get_autostart_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_domain_get_autostart_request qemud_packet_domain_get_autostart_request;
+
+struct qemud_packet_domain_get_autostart_reply {
+	uint32_t autostart;
+};
+typedef struct qemud_packet_domain_get_autostart_reply qemud_packet_domain_get_autostart_reply;
+
+struct qemud_packet_domain_set_autostart_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+	uint32_t autostart;
+};
+typedef struct qemud_packet_domain_set_autostart_request qemud_packet_domain_set_autostart_request;
+
+struct qemud_packet_network_get_autostart_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+};
+typedef struct qemud_packet_network_get_autostart_request qemud_packet_network_get_autostart_request;
+
+struct qemud_packet_network_get_autostart_reply {
+	uint32_t autostart;
+};
+typedef struct qemud_packet_network_get_autostart_reply qemud_packet_network_get_autostart_reply;
+
+struct qemud_packet_network_set_autostart_request {
+	u_char uuid[QEMUD_UUID_RAW_LEN];
+	uint32_t autostart;
+};
+typedef struct qemud_packet_network_set_autostart_request qemud_packet_network_set_autostart_request;
+
+struct qemud_packet_client_data {
+	qemud_packet_client_data_type type;
+	union {
+		qemud_packet_domain_create_request domainCreateRequest;
+		qemud_packet_domain_lookup_by_id_request domainLookupByIDRequest;
+		qemud_packet_domain_lookup_by_uuid_request domainLookupByUUIDRequest;
+		qemud_packet_domain_lookup_by_name_request domainLookupByNameRequest;
+		qemud_packet_domain_suspend_request domainSuspendRequest;
+		qemud_packet_domain_resume_request domainResumeRequest;
+		qemud_packet_domain_destroy_request domainDestroyRequest;
+		qemud_packet_domain_get_info_request domainGetInfoRequest;
+		qemud_packet_domain_save_request domainSaveRequest;
+		qemud_packet_domain_restore_request domainRestoreRequest;
+		qemud_packet_domain_dump_xml_request domainDumpXMLRequest;
+		qemud_packet_domain_start_request domainStartRequest;
+		qemud_packet_domain_define_request domainDefineRequest;
+		qemud_packet_domain_undefine_request domainUndefineRequest;
+		qemud_packet_network_lookup_by_uuid_request networkLookupByUUIDRequest;
+		qemud_packet_network_lookup_by_name_request networkLookupByNameRequest;
+		qemud_packet_network_create_request networkCreateRequest;
+		qemud_packet_network_define_request networkDefineRequest;
+		qemud_packet_network_undefine_request networkUndefineRequest;
+		qemud_packet_network_start_request networkStartRequest;
+		qemud_packet_network_destroy_request networkDestroyRequest;
+		qemud_packet_network_dump_xml_request networkDumpXMLRequest;
+		qemud_packet_network_get_bridge_name_request networkGetBridgeNameRequest;
+		qemud_packet_domain_get_autostart_request domainGetAutostartRequest;
+		qemud_packet_domain_set_autostart_request domainSetAutostartRequest;
+		qemud_packet_network_get_autostart_request networkGetAutostartRequest;
+		qemud_packet_network_set_autostart_request networkSetAutostartRequest;
+	} qemud_packet_client_data_u;
+};
+typedef struct qemud_packet_client_data qemud_packet_client_data;
+
+struct qemud_packet_server_data {
+	qemud_packet_server_data_type type;
+	union {
+		qemud_packet_failure_reply failureReply;
+		qemud_packet_get_version_reply getVersionReply;
+		qemud_packet_get_node_info_reply getNodeInfoReply;
+		qemud_packet_list_domains_reply listDomainsReply;
+		qemud_packet_num_domains_reply numDomainsReply;
+		qemud_packet_domain_create_reply domainCreateReply;
+		qemud_packet_domain_lookup_by_id_reply domainLookupByIDReply;
+		qemud_packet_domain_lookup_by_uuid_reply domainLookupByUUIDReply;
+		qemud_packet_domain_lookup_by_name_reply domainLookupByNameReply;
+		qemud_packet_domain_get_info_reply domainGetInfoReply;
+		qemud_packet_domain_restore_reply domainRestoreReply;
+		qemud_packet_domain_dump_xml_reply domainDumpXMLReply;
+		qemud_packet_list_defined_domains_reply listDefinedDomainsReply;
+		qemud_packet_num_defined_domains_reply numDefinedDomainsReply;
+		qemud_packet_domain_start_reply domainStartReply;
+		qemud_packet_domain_define_reply domainDefineReply;
+		qemud_packet_num_networks_reply numNetworksReply;
+		qemud_packet_list_networks_reply listNetworksReply;
+		qemud_packet_num_defined_networks_reply numDefinedNetworksReply;
+		qemud_packet_list_defined_networks_reply listDefinedNetworksReply;
+		qemud_packet_network_lookup_by_uuid_reply networkLookupByUUIDReply;
+		qemud_packet_network_lookup_by_name_reply networkLookupByNameReply;
+		qemud_packet_network_create_reply networkCreateReply;
+		qemud_packet_network_define_reply networkDefineReply;
+		qemud_packet_network_dump_xml_reply networkDumpXMLReply;
+		qemud_packet_network_get_bridge_name_reply networkGetBridgeNameReply;
+		qemud_packet_domain_get_autostart_reply domainGetAutostartReply;
+		qemud_packet_network_get_autostart_reply networkGetAutostartReply;
+		qemud_packet_get_capabilities_reply getCapabilitiesReply;
+	} qemud_packet_server_data_u;
+};
+typedef struct qemud_packet_server_data qemud_packet_server_data;
+
+struct qemud_packet_client {
+	uint32_t serial;
+	struct qemud_packet_client_data data;
+};
+typedef struct qemud_packet_client qemud_packet_client;
+
+struct qemud_packet_server {
+	uint32_t serial;
+	uint32_t inReplyTo;
+	struct qemud_packet_server_data data;
+};
+typedef struct qemud_packet_server qemud_packet_server;
+#define QEMUD_PROGRAM 0x20001A64
+#define QEMUD_PKT_HEADER_XDR_LEN 8
 
-/* Each packets has at least a fixed size header.
- *
- * All data required to be network byte order
- * to 32-bit boundaries */
 struct qemud_packet_header {
-    uint32_t type;
-    /* Stores the size of the data struct matching
-       the type arg.
-       Must be <= sizeof(union qemudPacketData) */
-    uint32_t dataSize;
-};
-
-/* Most packets also have some message specific data
- * All data required to be network byte order, padded
- * to 32-bit boundaries */
-union qemud_packet_data {
-    struct {
-        int32_t code;
-        char message[QEMUD_MAX_ERROR_LEN];
-    } failureReply;
-    struct {
-        int32_t version;
-    } getVersionReply;
-    struct {
-        char model[32];
-        uint32_t memory;
-        uint32_t cpus;
-        uint32_t mhz;
-        uint32_t nodes;
-        uint32_t sockets;
-        uint32_t cores;
-        uint32_t threads;
-    } getNodeInfoReply;
-    struct {
-        char xml[QEMUD_MAX_XML_LEN];
-    } getCapabilitiesReply;
-    struct {
-        int32_t numDomains;
-        int32_t domains[QEMUD_MAX_NUM_DOMAINS];
-    } listDomainsReply;
-    struct {
-        int32_t numDomains;
-    } numDomainsReply;
-    struct {
-        char xml[QEMUD_MAX_XML_LEN];
-    } domainCreateRequest;
-    struct {
-        int32_t id;
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-        char name[QEMUD_MAX_NAME_LEN];
-    } domainCreateReply;
-    struct {
-        int32_t id;
-    } domainLookupByIDRequest;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-        char name[QEMUD_MAX_NAME_LEN];
-    } domainLookupByIDReply;
-    struct {
-        char name[QEMUD_MAX_NAME_LEN];
-    } domainLookupByNameRequest;
-    struct {
-        int32_t id;
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } domainLookupByNameReply;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } domainLookupByUUIDRequest;
-    struct {
-        int32_t id;
-        char name[QEMUD_MAX_NAME_LEN];
-    } domainLookupByUUIDReply;
-    struct {
-        int32_t id;
-    } domainSuspendRequest;
-    struct {
-        int32_t id;
-    } domainResumeRequest;
-    struct {
-    } domainResumeReply;
-    struct {
-        int32_t id;
-    } domainDestroyRequest;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } domainGetInfoRequest;
-    struct {
-        uint64_t cpuTime;
-        int32_t runstate;
-        uint32_t memory;
-        uint32_t maxmem;
-        uint32_t nrVirtCpu;
-    } domainGetInfoReply;
-    struct {
-        int32_t id;
-        char file[PATH_MAX];
-    } domainSaveRequest;
-    struct {
-        char file[PATH_MAX];
-    } domainRestoreRequest;
-    struct {
-        int32_t id;
-    } domainRestoreReply;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } domainDumpXMLRequest;
-    struct {
-        char xml[QEMUD_MAX_XML_LEN];
-    } domainDumpXMLReply;
-    struct {
-        int32_t numDomains;
-        char domains[QEMUD_MAX_NUM_DOMAINS][QEMUD_MAX_NAME_LEN];
-    } listDefinedDomainsReply;
-    struct {
-        int32_t numDomains;
-    } numDefinedDomainsReply;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } domainStartRequest;
-    struct {
-        int32_t id;
-    } domainStartReply;
-    struct {
-        char xml[QEMUD_MAX_XML_LEN];
-    } domainDefineRequest;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-        char name[QEMUD_MAX_NAME_LEN];
-    } domainDefineReply;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } domainUndefineRequest;
-    struct {
-        int32_t numNetworks;
-    } numNetworksReply;
-    struct {
-        int32_t numNetworks;
-        char networks[QEMUD_MAX_NUM_NETWORKS][QEMUD_MAX_NAME_LEN];
-    } listNetworksReply;
-    struct {
-        int32_t numNetworks;
-    } numDefinedNetworksReply;
-    struct {
-        int32_t numNetworks;
-        char networks[QEMUD_MAX_NUM_NETWORKS][QEMUD_MAX_NAME_LEN];
-    } listDefinedNetworksReply;
-    struct {
-        char name[QEMUD_MAX_NAME_LEN];
-    } networkLookupByNameRequest;
-    struct {
-        int32_t id;
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } networkLookupByNameReply;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } networkLookupByUUIDRequest;
-    struct {
-        int32_t id;
-        char name[QEMUD_MAX_NAME_LEN];
-    } networkLookupByUUIDReply;
-    struct {
-        char xml[QEMUD_MAX_XML_LEN];
-    } networkCreateRequest;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-        char name[QEMUD_MAX_NAME_LEN];
-    } networkCreateReply;
-    struct {
-        char xml[QEMUD_MAX_XML_LEN];
-    } networkDefineRequest;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-        char name[QEMUD_MAX_NAME_LEN];
-    } networkDefineReply;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } networkUndefineRequest;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } networkStartRequest;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } networkDestroyRequest;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } networkDumpXMLRequest;
-    struct {
-        char xml[QEMUD_MAX_XML_LEN];
-    } networkDumpXMLReply;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } networkGetBridgeNameRequest;
-    struct {
-        char ifname[QEMUD_MAX_IFNAME_LEN];
-    } networkGetBridgeNameReply;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } domainGetAutostartRequest;
-    struct {
-        int autostart;
-    } domainGetAutostartReply;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-        unsigned int autostart : 1;
-    } domainSetAutostartRequest;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-    } networkGetAutostartRequest;
-    struct {
-        unsigned int autostart : 1;
-    } networkGetAutostartReply;
-    struct {
-        unsigned char uuid[QEMUD_UUID_RAW_LEN];
-        unsigned int autostart : 1;
-    } networkSetAutostartRequest;
-};
-
-/* Each packet has header & data */
-struct qemud_packet {
-    struct qemud_packet_header header;
-    union qemud_packet_data data;
+	uint32_t length;
+	uint32_t prog;
 };
+typedef struct qemud_packet_header qemud_packet_header;
 
+/* the xdr functions */
 
-#endif
+#if defined(__STDC__) || defined(__cplusplus)
+extern  bool_t xdr_qemud_domain_runstate (XDR *, qemud_domain_runstate*);
+extern  bool_t xdr_qemud_packet_client_data_type (XDR *, qemud_packet_client_data_type*);
+extern  bool_t xdr_qemud_packet_server_data_type (XDR *, qemud_packet_server_data_type*);
+extern  bool_t xdr_qemud_packet_failure_reply (XDR *, qemud_packet_failure_reply*);
+extern  bool_t xdr_qemud_packet_get_version_reply (XDR *, qemud_packet_get_version_reply*);
+extern  bool_t xdr_qemud_packet_get_node_info_reply (XDR *, qemud_packet_get_node_info_reply*);
+extern  bool_t xdr_qemud_packet_get_capabilities_reply (XDR *, qemud_packet_get_capabilities_reply*);
+extern  bool_t xdr_qemud_packet_list_domains_reply (XDR *, qemud_packet_list_domains_reply*);
+extern  bool_t xdr_qemud_packet_num_domains_reply (XDR *, qemud_packet_num_domains_reply*);
+extern  bool_t xdr_qemud_packet_domain_create_request (XDR *, qemud_packet_domain_create_request*);
+extern  bool_t xdr_qemud_packet_domain_create_reply (XDR *, qemud_packet_domain_create_reply*);
+extern  bool_t xdr_qemud_packet_domain_lookup_by_id_request (XDR *, qemud_packet_domain_lookup_by_id_request*);
+extern  bool_t xdr_qemud_packet_domain_lookup_by_id_reply (XDR *, qemud_packet_domain_lookup_by_id_reply*);
+extern  bool_t xdr_qemud_packet_domain_lookup_by_name_request (XDR *, qemud_packet_domain_lookup_by_name_request*);
+extern  bool_t xdr_qemud_packet_domain_lookup_by_name_reply (XDR *, qemud_packet_domain_lookup_by_name_reply*);
+extern  bool_t xdr_qemud_packet_domain_lookup_by_uuid_request (XDR *, qemud_packet_domain_lookup_by_uuid_request*);
+extern  bool_t xdr_qemud_packet_domain_lookup_by_uuid_reply (XDR *, qemud_packet_domain_lookup_by_uuid_reply*);
+extern  bool_t xdr_qemud_packet_domain_suspend_request (XDR *, qemud_packet_domain_suspend_request*);
+extern  bool_t xdr_qemud_packet_domain_resume_request (XDR *, qemud_packet_domain_resume_request*);
+extern  bool_t xdr_qemud_packet_domain_destroy_request (XDR *, qemud_packet_domain_destroy_request*);
+extern  bool_t xdr_qemud_packet_domain_get_info_request (XDR *, qemud_packet_domain_get_info_request*);
+extern  bool_t xdr_qemud_packet_domain_get_info_reply (XDR *, qemud_packet_domain_get_info_reply*);
+extern  bool_t xdr_qemud_packet_domain_save_request (XDR *, qemud_packet_domain_save_request*);
+extern  bool_t xdr_qemud_packet_domain_restore_request (XDR *, qemud_packet_domain_restore_request*);
+extern  bool_t xdr_qemud_packet_domain_restore_reply (XDR *, qemud_packet_domain_restore_reply*);
+extern  bool_t xdr_qemud_packet_domain_dump_xml_request (XDR *, qemud_packet_domain_dump_xml_request*);
+extern  bool_t xdr_qemud_packet_domain_dump_xml_reply (XDR *, qemud_packet_domain_dump_xml_reply*);
+extern  bool_t xdr_qemud_packet_list_defined_domains_reply (XDR *, qemud_packet_list_defined_domains_reply*);
+extern  bool_t xdr_qemud_packet_num_defined_domains_reply (XDR *, qemud_packet_num_defined_domains_reply*);
+extern  bool_t xdr_qemud_packet_domain_start_request (XDR *, qemud_packet_domain_start_request*);
+extern  bool_t xdr_qemud_packet_domain_start_reply (XDR *, qemud_packet_domain_start_reply*);
+extern  bool_t xdr_qemud_packet_domain_define_request (XDR *, qemud_packet_domain_define_request*);
+extern  bool_t xdr_qemud_packet_domain_define_reply (XDR *, qemud_packet_domain_define_reply*);
+extern  bool_t xdr_qemud_packet_domain_undefine_request (XDR *, qemud_packet_domain_undefine_request*);
+extern  bool_t xdr_qemud_packet_num_networks_reply (XDR *, qemud_packet_num_networks_reply*);
+extern  bool_t xdr_qemud_packet_list_networks_reply (XDR *, qemud_packet_list_networks_reply*);
+extern  bool_t xdr_qemud_packet_num_defined_networks_reply (XDR *, qemud_packet_num_defined_networks_reply*);
+extern  bool_t xdr_qemud_packet_list_defined_networks_reply (XDR *, qemud_packet_list_defined_networks_reply*);
+extern  bool_t xdr_qemud_packet_network_lookup_by_name_request (XDR *, qemud_packet_network_lookup_by_name_request*);
+extern  bool_t xdr_qemud_packet_network_lookup_by_name_reply (XDR *, qemud_packet_network_lookup_by_name_reply*);
+extern  bool_t xdr_qemud_packet_network_lookup_by_uuid_request (XDR *, qemud_packet_network_lookup_by_uuid_request*);
+extern  bool_t xdr_qemud_packet_network_lookup_by_uuid_reply (XDR *, qemud_packet_network_lookup_by_uuid_reply*);
+extern  bool_t xdr_qemud_packet_network_create_request (XDR *, qemud_packet_network_create_request*);
+extern  bool_t xdr_qemud_packet_network_create_reply (XDR *, qemud_packet_network_create_reply*);
+extern  bool_t xdr_qemud_packet_network_define_request (XDR *, qemud_packet_network_define_request*);
+extern  bool_t xdr_qemud_packet_network_define_reply (XDR *, qemud_packet_network_define_reply*);
+extern  bool_t xdr_qemud_packet_network_undefine_request (XDR *, qemud_packet_network_undefine_request*);
+extern  bool_t xdr_qemud_packet_network_start_request (XDR *, qemud_packet_network_start_request*);
+extern  bool_t xdr_qemud_packet_network_destroy_request (XDR *, qemud_packet_network_destroy_request*);
+extern  bool_t xdr_qemud_packet_network_dump_xml_request (XDR *, qemud_packet_network_dump_xml_request*);
+extern  bool_t xdr_qemud_packet_network_dump_xml_reply (XDR *, qemud_packet_network_dump_xml_reply*);
+extern  bool_t xdr_qemud_packet_network_get_bridge_name_request (XDR *, qemud_packet_network_get_bridge_name_request*);
+extern  bool_t xdr_qemud_packet_network_get_bridge_name_reply (XDR *, qemud_packet_network_get_bridge_name_reply*);
+extern  bool_t xdr_qemud_packet_domain_get_autostart_request (XDR *, qemud_packet_domain_get_autostart_request*);
+extern  bool_t xdr_qemud_packet_domain_get_autostart_reply (XDR *, qemud_packet_domain_get_autostart_reply*);
+extern  bool_t xdr_qemud_packet_domain_set_autostart_request (XDR *, qemud_packet_domain_set_autostart_request*);
+extern  bool_t xdr_qemud_packet_network_get_autostart_request (XDR *, qemud_packet_network_get_autostart_request*);
+extern  bool_t xdr_qemud_packet_network_get_autostart_reply (XDR *, qemud_packet_network_get_autostart_reply*);
+extern  bool_t xdr_qemud_packet_network_set_autostart_request (XDR *, qemud_packet_network_set_autostart_request*);
+extern  bool_t xdr_qemud_packet_client_data (XDR *, qemud_packet_client_data*);
+extern  bool_t xdr_qemud_packet_server_data (XDR *, qemud_packet_server_data*);
+extern  bool_t xdr_qemud_packet_client (XDR *, qemud_packet_client*);
+extern  bool_t xdr_qemud_packet_server (XDR *, qemud_packet_server*);
+extern  bool_t xdr_qemud_packet_header (XDR *, qemud_packet_header*);
+
+#else /* K&R C */
+extern bool_t xdr_qemud_domain_runstate ();
+extern bool_t xdr_qemud_packet_client_data_type ();
+extern bool_t xdr_qemud_packet_server_data_type ();
+extern bool_t xdr_qemud_packet_failure_reply ();
+extern bool_t xdr_qemud_packet_get_version_reply ();
+extern bool_t xdr_qemud_packet_get_node_info_reply ();
+extern bool_t xdr_qemud_packet_get_capabilities_reply ();
+extern bool_t xdr_qemud_packet_list_domains_reply ();
+extern bool_t xdr_qemud_packet_num_domains_reply ();
+extern bool_t xdr_qemud_packet_domain_create_request ();
+extern bool_t xdr_qemud_packet_domain_create_reply ();
+extern bool_t xdr_qemud_packet_domain_lookup_by_id_request ();
+extern bool_t xdr_qemud_packet_domain_lookup_by_id_reply ();
+extern bool_t xdr_qemud_packet_domain_lookup_by_name_request ();
+extern bool_t xdr_qemud_packet_domain_lookup_by_name_reply ();
+extern bool_t xdr_qemud_packet_domain_lookup_by_uuid_request ();
+extern bool_t xdr_qemud_packet_domain_lookup_by_uuid_reply ();
+extern bool_t xdr_qemud_packet_domain_suspend_request ();
+extern bool_t xdr_qemud_packet_domain_resume_request ();
+extern bool_t xdr_qemud_packet_domain_destroy_request ();
+extern bool_t xdr_qemud_packet_domain_get_info_request ();
+extern bool_t xdr_qemud_packet_domain_get_info_reply ();
+extern bool_t xdr_qemud_packet_domain_save_request ();
+extern bool_t xdr_qemud_packet_domain_restore_request ();
+extern bool_t xdr_qemud_packet_domain_restore_reply ();
+extern bool_t xdr_qemud_packet_domain_dump_xml_request ();
+extern bool_t xdr_qemud_packet_domain_dump_xml_reply ();
+extern bool_t xdr_qemud_packet_list_defined_domains_reply ();
+extern bool_t xdr_qemud_packet_num_defined_domains_reply ();
+extern bool_t xdr_qemud_packet_domain_start_request ();
+extern bool_t xdr_qemud_packet_domain_start_reply ();
+extern bool_t xdr_qemud_packet_domain_define_request ();
+extern bool_t xdr_qemud_packet_domain_define_reply ();
+extern bool_t xdr_qemud_packet_domain_undefine_request ();
+extern bool_t xdr_qemud_packet_num_networks_reply ();
+extern bool_t xdr_qemud_packet_list_networks_reply ();
+extern bool_t xdr_qemud_packet_num_defined_networks_reply ();
+extern bool_t xdr_qemud_packet_list_defined_networks_reply ();
+extern bool_t xdr_qemud_packet_network_lookup_by_name_request ();
+extern bool_t xdr_qemud_packet_network_lookup_by_name_reply ();
+extern bool_t xdr_qemud_packet_network_lookup_by_uuid_request ();
+extern bool_t xdr_qemud_packet_network_lookup_by_uuid_reply ();
+extern bool_t xdr_qemud_packet_network_create_request ();
+extern bool_t xdr_qemud_packet_network_create_reply ();
+extern bool_t xdr_qemud_packet_network_define_request ();
+extern bool_t xdr_qemud_packet_network_define_reply ();
+extern bool_t xdr_qemud_packet_network_undefine_request ();
+extern bool_t xdr_qemud_packet_network_start_request ();
+extern bool_t xdr_qemud_packet_network_destroy_request ();
+extern bool_t xdr_qemud_packet_network_dump_xml_request ();
+extern bool_t xdr_qemud_packet_network_dump_xml_reply ();
+extern bool_t xdr_qemud_packet_network_get_bridge_name_request ();
+extern bool_t xdr_qemud_packet_network_get_bridge_name_reply ();
+extern bool_t xdr_qemud_packet_domain_get_autostart_request ();
+extern bool_t xdr_qemud_packet_domain_get_autostart_reply ();
+extern bool_t xdr_qemud_packet_domain_set_autostart_request ();
+extern bool_t xdr_qemud_packet_network_get_autostart_request ();
+extern bool_t xdr_qemud_packet_network_get_autostart_reply ();
+extern bool_t xdr_qemud_packet_network_set_autostart_request ();
+extern bool_t xdr_qemud_packet_client_data ();
+extern bool_t xdr_qemud_packet_server_data ();
+extern bool_t xdr_qemud_packet_client ();
+extern bool_t xdr_qemud_packet_server ();
+extern bool_t xdr_qemud_packet_header ();
 
+#endif /* K&R C */
 
-/*
- * Local variables:
- *  indent-tabs-mode: nil
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 4
- * End:
- */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_PROTOCOL_H_RPCGEN */
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/protocol.x libvirt-remote/qemud/protocol.x
--- libvirt-cvs/qemud/protocol.x	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-remote/qemud/protocol.x	2007-04-17 16:04:03.000000000 +0100
@@ -0,0 +1,614 @@
+/* -*- c -*-
+ * protocol_xdr.x: wire protocol message format & data structures
+ *
+ * Copyright (C) 2006, 2007 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Daniel P. Berrange <berrange@xxxxxxxxxx>
+ */
+
+const QEMUD_UUID_RAW_LEN = 16;
+const QEMUD_MAX_NAME_LEN = 50;
+const QEMUD_MAX_XML_LEN = 4096;
+/*#define QEMUD_MAX_IFNAME_LEN IF_NAMESIZE */
+const QEMUD_MAX_IFNAME_LEN = 50;
+
+const QEMUD_MAX_NUM_DOMAINS = 100;
+const QEMUD_MAX_NUM_NETWORKS = 100;
+
+/*
+ * Damn, we can't do multiplcation when declaring
+ * constants with XDR !
+ * These two should be  QEMUD_MAX_NUM_DOMAIN * QEMUD_MAX_NAME_LEN
+ */
+const QEMUD_MAX_DOMAINS_NAME_BUF = 5000;
+const QEMUD_MAX_NETWORKS_NAME_BUF = 5000;
+
+const QEMUD_MAX_ERROR_LEN = 1024;
+
+/* Possible guest VM states */
+enum qemud_domain_runstate {
+    QEMUD_STATE_RUNNING = 1,
+    QEMUD_STATE_PAUSED,
+    QEMUD_STATE_STOPPED
+};
+
+/* Message sent by a client */
+enum qemud_packet_client_data_type {
+    QEMUD_CLIENT_PKT_GET_VERSION,
+    QEMUD_CLIENT_PKT_GET_NODEINFO,
+    QEMUD_CLIENT_PKT_LIST_DOMAINS,
+    QEMUD_CLIENT_PKT_NUM_DOMAINS,
+    QEMUD_CLIENT_PKT_DOMAIN_CREATE,
+    QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_ID,
+    QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_UUID,
+    QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_NAME,
+    QEMUD_CLIENT_PKT_DOMAIN_SUSPEND,
+    QEMUD_CLIENT_PKT_DOMAIN_RESUME,
+    QEMUD_CLIENT_PKT_DOMAIN_DESTROY,
+    QEMUD_CLIENT_PKT_DOMAIN_GET_INFO,
+    QEMUD_CLIENT_PKT_DOMAIN_SAVE,
+    QEMUD_CLIENT_PKT_DOMAIN_RESTORE,
+    QEMUD_CLIENT_PKT_DUMP_XML,
+    QEMUD_CLIENT_PKT_LIST_DEFINED_DOMAINS,
+    QEMUD_CLIENT_PKT_NUM_DEFINED_DOMAINS,
+    QEMUD_CLIENT_PKT_DOMAIN_START,
+    QEMUD_CLIENT_PKT_DOMAIN_DEFINE,
+    QEMUD_CLIENT_PKT_DOMAIN_UNDEFINE,
+    QEMUD_CLIENT_PKT_NUM_NETWORKS,
+    QEMUD_CLIENT_PKT_LIST_NETWORKS,
+    QEMUD_CLIENT_PKT_NUM_DEFINED_NETWORKS,
+    QEMUD_CLIENT_PKT_LIST_DEFINED_NETWORKS,
+    QEMUD_CLIENT_PKT_NETWORK_LOOKUP_BY_UUID,
+    QEMUD_CLIENT_PKT_NETWORK_LOOKUP_BY_NAME,
+    QEMUD_CLIENT_PKT_NETWORK_CREATE,
+    QEMUD_CLIENT_PKT_NETWORK_DEFINE,
+    QEMUD_CLIENT_PKT_NETWORK_UNDEFINE,
+    QEMUD_CLIENT_PKT_NETWORK_START,
+    QEMUD_CLIENT_PKT_NETWORK_DESTROY,
+    QEMUD_CLIENT_PKT_NETWORK_DUMP_XML,
+    QEMUD_CLIENT_PKT_NETWORK_GET_BRIDGE_NAME,
+    QEMUD_CLIENT_PKT_DOMAIN_GET_AUTOSTART,
+    QEMUD_CLIENT_PKT_DOMAIN_SET_AUTOSTART,
+    QEMUD_CLIENT_PKT_NETWORK_GET_AUTOSTART,
+    QEMUD_CLIENT_PKT_NETWORK_SET_AUTOSTART,
+    QEMUD_CLIENT_PKT_GET_CAPABILITIES,
+
+    QEMUD_CLIENT_PKT_MAX
+};
+
+/* Messages sent by a server */
+enum qemud_packet_server_data_type {
+    QEMUD_SERVER_PKT_FAILURE = 0,
+    QEMUD_SERVER_PKT_GET_VERSION,
+    QEMUD_SERVER_PKT_GET_NODEINFO,
+    QEMUD_SERVER_PKT_LIST_DOMAINS,
+    QEMUD_SERVER_PKT_NUM_DOMAINS,
+    QEMUD_SERVER_PKT_DOMAIN_CREATE,
+    QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_ID,
+    QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_UUID,
+    QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_NAME,
+    QEMUD_SERVER_PKT_DOMAIN_SUSPEND,
+    QEMUD_SERVER_PKT_DOMAIN_RESUME,
+    QEMUD_SERVER_PKT_DOMAIN_DESTROY,
+    QEMUD_SERVER_PKT_DOMAIN_GET_INFO,
+    QEMUD_SERVER_PKT_DOMAIN_SAVE,
+    QEMUD_SERVER_PKT_DOMAIN_RESTORE,
+    QEMUD_SERVER_PKT_DUMP_XML,
+    QEMUD_SERVER_PKT_LIST_DEFINED_DOMAINS,
+    QEMUD_SERVER_PKT_NUM_DEFINED_DOMAINS,
+    QEMUD_SERVER_PKT_DOMAIN_START,
+    QEMUD_SERVER_PKT_DOMAIN_DEFINE,
+    QEMUD_SERVER_PKT_DOMAIN_UNDEFINE,
+    QEMUD_SERVER_PKT_NUM_NETWORKS,
+    QEMUD_SERVER_PKT_LIST_NETWORKS,
+    QEMUD_SERVER_PKT_NUM_DEFINED_NETWORKS,
+    QEMUD_SERVER_PKT_LIST_DEFINED_NETWORKS,
+    QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_UUID,
+    QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_NAME,
+    QEMUD_SERVER_PKT_NETWORK_CREATE,
+    QEMUD_SERVER_PKT_NETWORK_DEFINE,
+    QEMUD_SERVER_PKT_NETWORK_UNDEFINE,
+    QEMUD_SERVER_PKT_NETWORK_START,
+    QEMUD_SERVER_PKT_NETWORK_DESTROY,
+    QEMUD_SERVER_PKT_NETWORK_DUMP_XML,
+    QEMUD_SERVER_PKT_NETWORK_GET_BRIDGE_NAME,
+    QEMUD_SERVER_PKT_DOMAIN_GET_AUTOSTART,
+    QEMUD_SERVER_PKT_DOMAIN_SET_AUTOSTART,
+    QEMUD_SERVER_PKT_NETWORK_GET_AUTOSTART,
+    QEMUD_SERVER_PKT_NETWORK_SET_AUTOSTART,
+    QEMUD_SERVER_PKT_GET_CAPABILITIES,
+
+    QEMUD_SERVER_PKT_MAX
+};
+
+
+
+struct qemud_packet_failure_reply {
+  uint32_t code;
+  char message[QEMUD_MAX_ERROR_LEN];
+};
+
+struct qemud_packet_get_version_reply {
+  uint32_t versionNum;
+};
+
+struct qemud_packet_get_node_info_reply {
+  char model[32];
+  uint32_t memory;
+  uint32_t cpus;
+  uint32_t mhz;
+  uint32_t nodes;
+  uint32_t sockets;
+  uint32_t cores;
+  uint32_t threads;
+};
+
+struct qemud_packet_get_capabilities_reply {
+  char xml[QEMUD_MAX_XML_LEN];
+};
+
+struct qemud_packet_list_domains_reply {
+  int32_t numDomains;
+  int32_t domains[QEMUD_MAX_NUM_DOMAINS];
+};
+
+struct qemud_packet_num_domains_reply{
+  int32_t numDomains;
+};
+
+struct qemud_packet_domain_create_request {
+  char xml[QEMUD_MAX_XML_LEN];
+};
+struct qemud_packet_domain_create_reply {
+  int32_t id;
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+  char name[QEMUD_MAX_NAME_LEN];
+};
+struct qemud_packet_domain_lookup_by_id_request {
+  int32_t id;
+};
+
+struct qemud_packet_domain_lookup_by_id_reply {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+  char name[QEMUD_MAX_NAME_LEN];
+};
+
+struct qemud_packet_domain_lookup_by_name_request {
+  char name[QEMUD_MAX_NAME_LEN];
+};
+struct qemud_packet_domain_lookup_by_name_reply {
+  int32_t id;
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_domain_lookup_by_uuid_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+
+struct qemud_packet_domain_lookup_by_uuid_reply {
+  int32_t id;
+  char name[QEMUD_MAX_NAME_LEN];
+};
+struct qemud_packet_domain_suspend_request {
+  int32_t id;
+};
+struct qemud_packet_domain_resume_request {
+  int32_t id;
+};
+struct qemud_packet_domain_destroy_request {
+  int32_t id;
+};
+struct qemud_packet_domain_get_info_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_domain_get_info_reply {
+  uint64_t cpuTime;
+  uint32_t runstate;
+  uint32_t memory;
+  uint32_t maxmem;
+  uint32_t nrVirtCpu;
+};
+struct qemud_packet_domain_save_request {
+  int32_t id;
+  char file[PATH_MAX];
+};
+struct qemud_packet_domain_restore_request {
+  char file[PATH_MAX];
+};
+struct qemud_packet_domain_restore_reply {
+  int32_t id;
+};
+struct qemud_packet_domain_dump_xml_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_domain_dump_xml_reply {
+  char xml[QEMUD_MAX_XML_LEN];
+};
+struct qemud_packet_list_defined_domains_reply{
+  uint32_t numDomains;
+  char domains[QEMUD_MAX_DOMAINS_NAME_BUF];
+};
+struct qemud_packet_num_defined_domains_reply{
+  uint32_t numDomains;
+};
+struct qemud_packet_domain_start_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_domain_start_reply {
+  int32_t id;
+};
+struct qemud_packet_domain_define_request {
+  char xml[QEMUD_MAX_XML_LEN];
+};
+struct qemud_packet_domain_define_reply {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+  char name[QEMUD_MAX_NAME_LEN];
+};
+struct qemud_packet_domain_undefine_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_num_networks_reply {
+  uint32_t numNetworks;
+};
+
+struct qemud_packet_list_networks_reply {
+  uint32_t numNetworks;
+  char networks[QEMUD_MAX_NETWORKS_NAME_BUF];
+};
+
+struct qemud_packet_num_defined_networks_reply {
+  uint32_t numNetworks;
+};
+
+struct qemud_packet_list_defined_networks_reply {
+  uint32_t numNetworks;
+  char networks[QEMUD_MAX_NETWORKS_NAME_BUF];
+};
+struct qemud_packet_network_lookup_by_name_request {
+  char name[QEMUD_MAX_NAME_LEN];
+};
+struct qemud_packet_network_lookup_by_name_reply {
+  int32_t id;
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_network_lookup_by_uuid_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_network_lookup_by_uuid_reply {
+  int32_t id;
+  char name[QEMUD_MAX_NAME_LEN];
+};
+struct qemud_packet_network_create_request {
+  char xml[QEMUD_MAX_XML_LEN];
+};
+struct qemud_packet_network_create_reply {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+  char name[QEMUD_MAX_NAME_LEN];
+};
+struct qemud_packet_network_define_request {
+  char xml[QEMUD_MAX_XML_LEN];
+};
+struct qemud_packet_network_define_reply {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+  char name[QEMUD_MAX_NAME_LEN];
+};
+struct qemud_packet_network_undefine_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_network_start_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_network_destroy_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_network_dump_xml_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_network_dump_xml_reply {
+  char xml[QEMUD_MAX_XML_LEN];
+};
+struct qemud_packet_network_get_bridge_name_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_network_get_bridge_name_reply {
+  char ifname[QEMUD_MAX_IFNAME_LEN];
+};
+struct qemud_packet_domain_get_autostart_request{
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_domain_get_autostart_reply {
+  uint32_t autostart;
+};
+struct qemud_packet_domain_set_autostart_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+  uint32_t autostart;
+};
+
+struct qemud_packet_network_get_autostart_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+};
+struct qemud_packet_network_get_autostart_reply {
+  uint32_t autostart;
+};
+struct qemud_packet_network_set_autostart_request {
+  unsigned char uuid[QEMUD_UUID_RAW_LEN];
+  uint32_t autostart;
+};
+
+union qemud_packet_client_data switch (qemud_packet_client_data_type type) {
+    case QEMUD_CLIENT_PKT_GET_VERSION:
+      void;
+
+    case QEMUD_CLIENT_PKT_GET_NODEINFO:
+      void;
+
+    case QEMUD_CLIENT_PKT_LIST_DOMAINS:
+      void;
+
+    case QEMUD_CLIENT_PKT_NUM_DOMAINS:
+      void;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_CREATE:
+      qemud_packet_domain_create_request domainCreateRequest;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_ID:
+      qemud_packet_domain_lookup_by_id_request domainLookupByIDRequest;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_UUID:
+      qemud_packet_domain_lookup_by_uuid_request domainLookupByUUIDRequest;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_NAME:
+      qemud_packet_domain_lookup_by_name_request domainLookupByNameRequest;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_SUSPEND:
+      qemud_packet_domain_suspend_request domainSuspendRequest;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_RESUME:
+      qemud_packet_domain_resume_request domainResumeRequest;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_DESTROY:
+      qemud_packet_domain_destroy_request domainDestroyRequest;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_GET_INFO:
+      qemud_packet_domain_get_info_request domainGetInfoRequest;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_SAVE:
+      qemud_packet_domain_save_request domainSaveRequest;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_RESTORE:
+      qemud_packet_domain_restore_request domainRestoreRequest;
+
+    case QEMUD_CLIENT_PKT_DUMP_XML:
+      qemud_packet_domain_dump_xml_request domainDumpXMLRequest;
+
+    case QEMUD_CLIENT_PKT_LIST_DEFINED_DOMAINS:
+      void;
+
+    case QEMUD_CLIENT_PKT_NUM_DEFINED_DOMAINS:
+      void;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_START:
+      qemud_packet_domain_start_request domainStartRequest;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_DEFINE:
+      qemud_packet_domain_define_request domainDefineRequest;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_UNDEFINE:
+      qemud_packet_domain_undefine_request domainUndefineRequest;
+
+    case QEMUD_CLIENT_PKT_NUM_NETWORKS:
+      void;
+
+    case QEMUD_CLIENT_PKT_LIST_NETWORKS:
+      void;
+
+    case QEMUD_CLIENT_PKT_NUM_DEFINED_NETWORKS:
+      void;
+
+    case QEMUD_CLIENT_PKT_LIST_DEFINED_NETWORKS:
+      void;
+
+    case QEMUD_CLIENT_PKT_NETWORK_LOOKUP_BY_UUID:
+      qemud_packet_network_lookup_by_uuid_request networkLookupByUUIDRequest;
+
+    case QEMUD_CLIENT_PKT_NETWORK_LOOKUP_BY_NAME:
+      qemud_packet_network_lookup_by_name_request networkLookupByNameRequest;
+
+    case QEMUD_CLIENT_PKT_NETWORK_CREATE:
+      qemud_packet_network_create_request networkCreateRequest;
+
+    case QEMUD_CLIENT_PKT_NETWORK_DEFINE:
+      qemud_packet_network_define_request networkDefineRequest;
+
+    case QEMUD_CLIENT_PKT_NETWORK_UNDEFINE:
+      qemud_packet_network_undefine_request networkUndefineRequest;
+
+    case QEMUD_CLIENT_PKT_NETWORK_START:
+      qemud_packet_network_start_request networkStartRequest;
+
+    case QEMUD_CLIENT_PKT_NETWORK_DESTROY:
+      qemud_packet_network_destroy_request networkDestroyRequest;
+
+    case QEMUD_CLIENT_PKT_NETWORK_DUMP_XML:
+      qemud_packet_network_dump_xml_request networkDumpXMLRequest;
+
+    case QEMUD_CLIENT_PKT_NETWORK_GET_BRIDGE_NAME:
+      qemud_packet_network_get_bridge_name_request networkGetBridgeNameRequest;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_GET_AUTOSTART:
+      qemud_packet_domain_get_autostart_request domainGetAutostartRequest;
+
+    case QEMUD_CLIENT_PKT_DOMAIN_SET_AUTOSTART:
+      qemud_packet_domain_set_autostart_request domainSetAutostartRequest;
+
+    case QEMUD_CLIENT_PKT_NETWORK_GET_AUTOSTART:
+      qemud_packet_network_get_autostart_request networkGetAutostartRequest;
+
+    case QEMUD_CLIENT_PKT_NETWORK_SET_AUTOSTART:
+      qemud_packet_network_set_autostart_request networkSetAutostartRequest;
+
+    case QEMUD_CLIENT_PKT_GET_CAPABILITIES:
+      void;
+
+};
+
+union qemud_packet_server_data switch (qemud_packet_server_data_type type) {
+    case QEMUD_SERVER_PKT_FAILURE:
+      qemud_packet_failure_reply failureReply;
+
+    case QEMUD_SERVER_PKT_GET_VERSION:
+      qemud_packet_get_version_reply getVersionReply;
+
+    case QEMUD_SERVER_PKT_GET_NODEINFO:
+      qemud_packet_get_node_info_reply getNodeInfoReply;
+
+    case QEMUD_SERVER_PKT_LIST_DOMAINS:
+      qemud_packet_list_domains_reply listDomainsReply;
+
+    case QEMUD_SERVER_PKT_NUM_DOMAINS:
+      qemud_packet_num_domains_reply numDomainsReply;
+
+    case QEMUD_SERVER_PKT_DOMAIN_CREATE:
+      qemud_packet_domain_create_reply domainCreateReply;
+
+    case QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_ID:
+      qemud_packet_domain_lookup_by_id_reply domainLookupByIDReply;
+
+    case QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_UUID:
+      qemud_packet_domain_lookup_by_uuid_reply domainLookupByUUIDReply;
+
+    case QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_NAME:
+      qemud_packet_domain_lookup_by_name_reply domainLookupByNameReply;
+
+    case QEMUD_SERVER_PKT_DOMAIN_SUSPEND:
+      void;
+
+    case QEMUD_SERVER_PKT_DOMAIN_RESUME:
+      void;
+
+    case QEMUD_SERVER_PKT_DOMAIN_DESTROY:
+      void;
+
+    case QEMUD_SERVER_PKT_DOMAIN_GET_INFO:
+      qemud_packet_domain_get_info_reply domainGetInfoReply;
+
+    case QEMUD_SERVER_PKT_DOMAIN_SAVE:
+      void;
+
+    case QEMUD_SERVER_PKT_DOMAIN_RESTORE:
+      qemud_packet_domain_restore_reply domainRestoreReply;
+
+    case QEMUD_SERVER_PKT_DUMP_XML:
+      qemud_packet_domain_dump_xml_reply domainDumpXMLReply;
+
+    case QEMUD_SERVER_PKT_LIST_DEFINED_DOMAINS:
+      qemud_packet_list_defined_domains_reply listDefinedDomainsReply;
+
+    case QEMUD_SERVER_PKT_NUM_DEFINED_DOMAINS:
+      qemud_packet_num_defined_domains_reply numDefinedDomainsReply;
+
+    case QEMUD_SERVER_PKT_DOMAIN_START:
+      qemud_packet_domain_start_reply domainStartReply;
+
+    case QEMUD_SERVER_PKT_DOMAIN_DEFINE:
+      qemud_packet_domain_define_reply domainDefineReply;
+
+    case QEMUD_SERVER_PKT_DOMAIN_UNDEFINE:
+      void;
+
+    case QEMUD_SERVER_PKT_NUM_NETWORKS:
+      qemud_packet_num_networks_reply numNetworksReply;
+
+    case QEMUD_SERVER_PKT_LIST_NETWORKS:
+      qemud_packet_list_networks_reply listNetworksReply;
+
+    case QEMUD_SERVER_PKT_NUM_DEFINED_NETWORKS:
+      qemud_packet_num_defined_networks_reply numDefinedNetworksReply;
+
+    case QEMUD_SERVER_PKT_LIST_DEFINED_NETWORKS:
+      qemud_packet_list_defined_networks_reply listDefinedNetworksReply;
+
+    case QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_UUID:
+      qemud_packet_network_lookup_by_uuid_reply networkLookupByUUIDReply;
+
+    case QEMUD_SERVER_PKT_NETWORK_LOOKUP_BY_NAME:
+      qemud_packet_network_lookup_by_name_reply networkLookupByNameReply;
+
+    case QEMUD_SERVER_PKT_NETWORK_CREATE:
+      qemud_packet_network_create_reply networkCreateReply;
+
+    case QEMUD_SERVER_PKT_NETWORK_DEFINE:
+      qemud_packet_network_define_reply networkDefineReply;
+
+    case QEMUD_SERVER_PKT_NETWORK_UNDEFINE:
+      void;
+
+    case QEMUD_SERVER_PKT_NETWORK_START:
+      void;
+
+    case QEMUD_SERVER_PKT_NETWORK_DESTROY:
+      void;
+
+    case QEMUD_SERVER_PKT_NETWORK_DUMP_XML:
+      qemud_packet_network_dump_xml_reply networkDumpXMLReply;
+
+    case QEMUD_SERVER_PKT_NETWORK_GET_BRIDGE_NAME:
+      qemud_packet_network_get_bridge_name_reply networkGetBridgeNameReply;
+
+    case QEMUD_SERVER_PKT_DOMAIN_GET_AUTOSTART:
+      qemud_packet_domain_get_autostart_reply domainGetAutostartReply;
+
+    case QEMUD_SERVER_PKT_DOMAIN_SET_AUTOSTART:
+      void;
+
+    case QEMUD_SERVER_PKT_NETWORK_GET_AUTOSTART:
+      qemud_packet_network_get_autostart_reply networkGetAutostartReply;
+
+    case QEMUD_SERVER_PKT_NETWORK_SET_AUTOSTART:
+      void;
+
+    case QEMUD_SERVER_PKT_GET_CAPABILITIES:
+      qemud_packet_get_capabilities_reply getCapabilitiesReply;
+};
+
+struct qemud_packet_client {
+  uint32_t serial;
+  struct qemud_packet_client_data data;
+};
+
+struct qemud_packet_server {
+  uint32_t serial;
+  uint32_t inReplyTo;
+  struct qemud_packet_server_data data;
+};
+
+/* The first two words in the messages are length and program number
+ * (previously called "magic").  This makes the protocol compatible
+ * with the remote protocol, although beyond the first two words
+ * the protocols are completely different.
+ *
+ * Note the length is the total number of bytes in the message
+ * _including_ the length and program number.
+ */
+
+const QEMUD_PROGRAM = 0x20001A64;
+const QEMUD_PKT_HEADER_XDR_LEN = 8;
+
+struct qemud_packet_header {
+  uint32_t length;
+  uint32_t prog;
+};
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/qemud.c libvirt-remote/qemud/qemud.c
--- libvirt-cvs/qemud/qemud.c	2007-04-12 15:18:13.000000000 +0100
+++ libvirt-remote/qemud/qemud.c	2007-04-24 11:14:18.000000000 +0100
@@ -23,6 +23,8 @@
 
 #include <config.h>
 
+#define _GNU_SOURCE /* for asprintf */
+
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
@@ -44,7 +46,7 @@
 #include <errno.h>
 #include <getopt.h>
 #include <ctype.h>
-
+#include <assert.h>
 
 #include <libvirt/virterror.h>
 
@@ -54,9 +56,12 @@
 #include "conf.h"
 #include "iptables.h"
 
-static int godaemon = 0;
-static int verbose = 0;
-static int sigwrite = -1;
+static int godaemon = 0;        /* -d: Be a daemon */
+static int verbose = 0;         /* -v: Verbose mode */
+static int remote = 0;          /* -r: Remote mode */
+static int sys = 0;             /* -s: QEMUD system mode */
+static int timeout = -1;        /* -t: QEMUD timeout */
+static int sigwrite = -1;       /* Signal handler pipe */
 
 static sig_atomic_t sig_errors = 0;
 static int sig_lasterrno = 0;
@@ -96,11 +101,13 @@
     switch (sigc) {
     case SIGHUP:
         qemudLog(QEMUD_INFO, "Reloading configuration on SIGHUP");
-        ret = qemudScanConfigs(server);
+        if (!remote) {
+            ret = qemudScanConfigs(server);
 
-        if (server->iptables) {
-            qemudLog(QEMUD_INFO, "Reloading iptables rules");
-            iptablesReloadRules(server->iptables);
+            if (server->iptables) {
+                qemudLog(QEMUD_INFO, "Reloading iptables rules");
+                iptablesReloadRules(server->iptables);
+            }
         }
         break;
 
@@ -109,45 +116,47 @@
     case SIGTERM:
         qemudLog(QEMUD_WARN, "Shutting down on signal %d", sigc);
 
-        /* shutdown active VMs */
-        vm = server->vms;
-        while (vm) {
-            struct qemud_vm *next = vm->next;
-            if (qemudIsActiveVM(vm))
-                qemudShutdownVMDaemon(server, vm);
-            vm = next;
-        }
+        if (!remote) {
+            /* shutdown active VMs */
+            vm = server->vms;
+            while (vm) {
+                struct qemud_vm *next = vm->next;
+                if (qemudIsActiveVM(vm))
+                    qemudShutdownVMDaemon(server, vm);
+                vm = next;
+            }
 
-        /* free inactive VMs */
-        vm = server->vms;
-        while (vm) {
-            struct qemud_vm *next = vm->next;
-            qemudFreeVM(vm);
-            vm = next;
+            /* free inactive VMs */
+            vm = server->vms;
+            while (vm) {
+                struct qemud_vm *next = vm->next;
+                qemudFreeVM(vm);
+                vm = next;
+            }
+            server->vms = NULL;
+            server->nactivevms = 0;
+            server->ninactivevms = 0;
+
+            /* shutdown active networks */
+            network = server->networks;
+            while (network) {
+                struct qemud_network *next = network->next;
+                if (qemudIsActiveNetwork(network))
+                    qemudShutdownNetworkDaemon(server, network);
+                network = next;
+            }
+
+            /* free inactive networks */
+            network = server->networks;
+            while (network) {
+                struct qemud_network *next = network->next;
+                qemudFreeNetwork(network);
+                network = next;
+            }
+            server->networks = NULL;
+            server->nactivenetworks = 0;
+            server->ninactivenetworks = 0;
         }
-        server->vms = NULL;
-        server->nactivevms = 0;
-        server->ninactivevms = 0;
-
-        /* shutdown active networks */
-        network = server->networks;
-        while (network) {
-            struct qemud_network *next = network->next;
-            if (qemudIsActiveNetwork(network))
-                qemudShutdownNetworkDaemon(server, network);
-            network = next;
-        }
-
-        /* free inactive networks */
-        network = server->networks;
-        while (network) {
-            struct qemud_network *next = network->next;
-            qemudFreeNetwork(network);
-            network = next;
-        }
-        server->networks = NULL;
-        server->nactivenetworks = 0;
-        server->ninactivenetworks = 0;
 
         server->shutdown = 1;
         break;
@@ -406,65 +415,105 @@
 }
 
 static int qemudInitPaths(struct qemud_server *server,
-                          int sys,
                           char *sockname,
                           char *roSockname,
                           int maxlen) {
-    const char *paths[] = {
-        "libvirt/qemu",                    /* QEMUD_DIR_DOMAINS */
-        "libvirt/qemu/autostart",          /* QEMUD_DIR_AUTO_DOMAINS */
-        "libvirt/qemu/networks",           /* QEMUD_DIR_NETWORKS */
-        "libvirt/qemu/networks/autostart", /* QEMUD_DIR_AUTO_NETWORKS */
-    };
-
-    uid_t uid;
-    struct passwd *pw;
-    char base[PATH_MAX] = SYSCONF_DIR "/";
-    int i;
-
-    uid = geteuid();
+    char *base = 0;
 
-    if (sys) {
-        if (uid != 0) {
-            qemudLog(QEMUD_ERR, "You must run the daemon as root to use system mode");
-            return -1;
-        }
+    if (remote) {               /* Remote daemon */
+        /* I'm not sure if it's meaningful to have a "session remote daemon"
+         * so currently this code ignores the --system flag. - RWMJ.
+         */
 
-        if (snprintf(sockname, maxlen, "%s/run/libvirt/qemud-sock", LOCAL_STATE_DIR) >= maxlen)
+        if (snprintf (sockname, maxlen, "%s/run/libvirt/libvirt-sock",
+                      LOCAL_STATE_DIR) >= maxlen)
             goto snprintf_error;
 
         unlink(sockname);
 
-        if (snprintf(roSockname, maxlen, "%s/run/libvirt/qemud-sock-ro", LOCAL_STATE_DIR) >= maxlen)
+        if (snprintf (roSockname, maxlen, "%s/run/libvirt/libvirt-sock-ro",
+                      LOCAL_STATE_DIR) >= maxlen)
             goto snprintf_error;
 
         unlink(roSockname);
+
+        if (asprintf (&server->configDir, SYSCONF_DIR "/libvirt") == -1)
+            goto out_of_memory;
+
+        server->autostartDir =
+            server->networkConfigDir =
+            server->networkAutostartDir = NULL;
     } else {
-        if (!(pw = getpwuid(uid))) {
-            qemudLog(QEMUD_ERR, "Failed to find user record for uid '%d': %s",
-                     uid, strerror(errno));
-            return -1;
+        uid_t uid = geteuid();
+        struct passwd *pw;
+
+        if (sys) {              /* QEMUD, system */
+            if (uid != 0) {
+                qemudLog (QEMUD_ERR,
+                      "You must run the daemon as root to use system mode");
+                return -1;
+            }
+
+            if (snprintf(sockname, maxlen, "%s/run/libvirt/qemud-sock", LOCAL_STATE_DIR) >= maxlen)
+                goto snprintf_error;
+
+            unlink(sockname);
+
+            if (snprintf(roSockname, maxlen, "%s/run/libvirt/qemud-sock-ro", LOCAL_STATE_DIR) >= maxlen)
+                goto snprintf_error;
+
+            unlink(roSockname);
+
+            if ((base = strdup (SYSCONF_DIR "/libvirt/qemu")) == NULL)
+                goto out_of_memory;
+        } else {                /* QEMUD, session */
+            if (!(pw = getpwuid(uid))) {
+                qemudLog(QEMUD_ERR, "Failed to find user record for uid '%d': %s",
+                         uid, strerror(errno));
+                return -1;
+            }
+
+            if (snprintf(sockname, maxlen, "@%s/.libvirt/qemud-sock", pw->pw_dir) >= maxlen)
+                goto snprintf_error;
+
+            if (asprintf (&base, "%s/.libvirt/qemu", pw->pw_dir) == -1) {
+                qemudLog (QEMUD_ERR, "out of memory in asprintf");
+                return -1;
+            }
         }
 
-        if (snprintf(sockname, maxlen, "@%s/.libvirt/qemud-sock", pw->pw_dir) >= maxlen)
-            goto snprintf_error;
+        /* Configuration paths are either ~/.libvirt/qemu/... (session) or
+         * /etc/libvirt/qemu/... (system).
+         */
+        if (asprintf (&server->configDir, "%s", base) == -1)
+            goto out_of_memory;
 
-        if (snprintf(base, PATH_MAX, "%s/.", pw->pw_dir) >= PATH_MAX)
-            goto snprintf_error;
-    }
+        if (asprintf (&server->autostartDir, "%s/autostart", base) == -1)
+            goto out_of_memory;
 
-    for (i = 0; i < QEMUD_N_CONFIG_DIRS; i++)
-        if (snprintf(server->configDirs[i], PATH_MAX, "%s%s", base, paths[i]) >= PATH_MAX)
-            goto snprintf_error;
+        if (asprintf (&server->networkConfigDir, "%s/networks", base) == -1)
+            goto out_of_memory;
+
+        if (asprintf (&server->networkAutostartDir, "%s/networks/autostart",
+                      base) == -1)
+            goto out_of_memory;
+    } /* !remote */
+
+    if (base) free (base);
 
     return 0;
 
  snprintf_error:
     qemudLog(QEMUD_ERR, "Resulting path to long for buffer in qemudInitPaths()");
     return -1;
+
+ out_of_memory:
+    qemudLog (QEMUD_ERR, "qemudInitPaths: out of memory");
+    if (base) free (base);
+    return -1;
 }
 
-static struct qemud_server *qemudInitialize(int sys, int sigread) {
+static struct qemud_server *qemudInitialize(int sigread) {
     struct qemud_server *server;
     char sockname[PATH_MAX];
     char roSockname[PATH_MAX];
@@ -480,21 +529,16 @@
 
     roSockname[0] = '\0';
 
-    if (qemudInitPaths(server, sys, sockname, roSockname, PATH_MAX) < 0)
+    if (qemudInitPaths(server, sockname, roSockname, PATH_MAX) < 0)
         goto cleanup;
 
-    server->configDir           = server->configDirs[QEMUD_DIR_CONFIG];
-    server->autostartDir        = server->configDirs[QEMUD_DIR_AUTOSTART];
-    server->networkConfigDir    = server->configDirs[QEMUD_DIR_NETWORK_CONFIG];
-    server->networkAutostartDir = server->configDirs[QEMUD_DIR_NETWORK_AUTOSTART];
-
     if (qemudListenUnix(server, sockname, 0) < 0)
         goto cleanup;
 
     if (roSockname[0] != '\0' && qemudListenUnix(server, roSockname, 1) < 0)
         goto cleanup;
 
-    if (qemudScanConfigs(server) < 0) {
+    if (!remote && qemudScanConfigs(server) < 0) {
         goto cleanup;
     }
 
@@ -508,6 +552,11 @@
             sock = sock->next;
         }
 
+        if (server->configDir) free (server->configDir);
+        if (server->autostartDir) free (server->autostartDir);
+        if (server->networkConfigDir) free (server->networkConfigDir);
+        if (server->networkAutostartDir) free (server->networkAutostartDir);
+
         free(server);
     }
     return NULL;
@@ -534,8 +583,11 @@
     }
 
     client = calloc(1, sizeof(struct qemud_client));
+    client->magic = QEMUD_CLIENT_MAGIC;
     client->fd = fd;
     client->readonly = sock->readonly;
+    client->mode = QEMUD_MODE_RX_HEADER;
+    client->bufferLength = QEMUD_PKT_HEADER_XDR_LEN;
 
     client->next = server->clients;
     server->clients = client;
@@ -916,108 +968,213 @@
 }
 
 
-static int qemudDispatchClientRequest(struct qemud_server *server, struct qemud_client *client) {
+static void qemudDispatchClientRequest(struct qemud_server *server,
+                                       struct qemud_client *client,
+                                       qemud_packet_client *req) {
+    qemud_packet_server res;
+    qemud_packet_header h;
+    XDR x;
+
+    assert (client->magic == QEMUD_CLIENT_MAGIC);
+
+    if (req->serial != ++client->incomingSerial) {
+        qemudDebug("Invalid serial number. Got %d expect %d",
+                   req->serial, client->incomingSerial);
+        qemudDispatchClientFailure(server, client);
+        return;
+    }
+
     if (qemudDispatch(server,
                       client,
-                      &client->incoming,
-                      &client->outgoing) < 0) {
-        return -1;
+                      &req->data,
+                      &res.data) < 0) {
+        qemudDispatchClientFailure(server, client);
+        return;
     }
 
-    client->outgoingSent = 0;
-    client->tx = 1;
-    client->incomingReceived = 0;
+    res.serial = ++client->outgoingSerial;
+    res.inReplyTo = req->serial;
 
-    return 0;
+    xdrmem_create(&x, client->buffer, sizeof client->buffer,
+                  XDR_ENCODE);
+
+    /* Encode a dummy header.  We'll come back to encode the real header. */
+    if (!xdr_qemud_packet_header (&x, &h)) {
+        qemudDebug ("failed to encode dummy header");
+        qemudDispatchClientFailure (server, client);
+        return;
+    }
+
+    /* Real payload. */
+    if (!xdr_qemud_packet_server(&x, &res)) {
+        qemudDebug("Failed to XDR encode reply payload");
+        qemudDispatchClientFailure(server, client);
+        return;
+    }
+
+    /* Go back and encode the real header. */
+    h.length = xdr_getpos (&x);
+    h.prog = QEMUD_PROGRAM;
+
+    if (xdr_setpos (&x, 0) == 0) {
+        qemudDebug("xdr_setpos failed");
+        qemudDispatchClientFailure(server, client);
+        return;
+    }
+
+    if (!xdr_qemud_packet_header(&x, &h)) {
+        qemudDebug("Failed to XDR encode reply header");
+        qemudDispatchClientFailure(server, client);
+        return;
+    }
+
+    client->mode = QEMUD_MODE_TX_PACKET;
+    client->bufferLength = h.length;
+    client->bufferOffset = 0;
 }
 
 static int qemudClientRead(struct qemud_server *server,
-                           struct qemud_client *client,
-                           char *buf, size_t want) {
+                           struct qemud_client *client) {
     int ret;
-    if ((ret = read(client->fd, buf, want)) <= 0) {
+    if ((ret = read(client->fd,
+                    client->buffer + client->bufferOffset,
+                    client->bufferLength - client->bufferOffset)) <= 0) {
         qemudDebug("Plain read error %d", ret);
         if (!ret || errno != EAGAIN)
             qemudDispatchClientFailure(server, client);
         return -1;
     }
     qemudDebug("Plain data read %d", ret);
-    return ret;
+    client->bufferOffset += ret;
+    return 0;
 }
 
 static void qemudDispatchClientRead(struct qemud_server *server, struct qemud_client *client) {
-    char *data = (char *)&client->incoming;
-    unsigned int got = client->incomingReceived;
-    int want;
-    int ret;
 
- restart:
-    if (got >= sizeof(struct qemud_packet_header)) {
-        want = sizeof(struct qemud_packet_header) + client->incoming.header.dataSize - got;
-    } else {
-        want = sizeof(struct qemud_packet_header) - got;
-    }
+    if (client->mode == QEMUD_MODE_RX_HEADER) {
+        XDR x;
+        qemud_packet_header h;
 
-    if ((ret = qemudClientRead(server, client, data+got, want)) < 0) {
-        return;
-    }
-    got += ret;
-    client->incomingReceived += ret;
+        if (qemudClientRead(server, client) < 0)
+            return; /* Error, or blocking */
+
+        if (client->bufferOffset < client->bufferLength)
+            return; /* Not read enough */
+
+        xdrmem_create(&x, client->buffer, client->bufferLength, XDR_DECODE);
+
+        if (!xdr_qemud_packet_header(&x, &h)) {
+            qemudDebug("Failed to decode packet header");
+            qemudDispatchClientFailure(server, client);
+            return;
+        }
 
-    /* If we've finished header, move onto body */
-    if (client->incomingReceived == sizeof(struct qemud_packet_header)) {
-        qemudDebug("Type %d, data %d",
-                    client->incoming.header.type,
-                    client->incoming.header.dataSize);
-        /* Client lied about dataSize */
-        if (client->incoming.header.dataSize > sizeof(union qemud_packet_data)) {
-            qemudDebug("Bogus data size %u", client->incoming.header.dataSize);
+        /* We're expecting either QEMUD_PROGRAM or REMOTE_PROGRAM,
+         * corresponding to qemud or remote calls respectively.
+         */
+        if ((!remote && h.prog != QEMUD_PROGRAM)
+            || (remote && h.prog != REMOTE_PROGRAM)) {
+            qemudDebug("Header magic %x mismatch", h.prog);
             qemudDispatchClientFailure(server, client);
             return;
         }
-        if (client->incoming.header.dataSize) {
-            qemudDebug("- Restarting recv to process body (%d bytes)",
-                        client->incoming.header.dataSize);
-            goto restart;
+
+        /* NB: h.length is unsigned. */
+        if (h.length > REMOTE_MESSAGE_MAX) {
+            qemudDebug("Packet length %u too large", h.length);
+            qemudDispatchClientFailure(server, client);
+            return;
         }
+
+        client->mode = QEMUD_MODE_RX_PAYLOAD;
+        client->bufferLength = h.length;
+        /* Note that we don't reset bufferOffset here because we want
+         * to retain the whole message, including header.
+         */
+
+        xdr_destroy (&x);
+
+        /* Fall through */
     }
 
-    /* If we've finished body, dispatch the request */
-    if (ret == want) {
-        if (qemudDispatchClientRequest(server, client) < 0)
+    if (client->mode == QEMUD_MODE_RX_PAYLOAD) {
+        XDR x;
+        qemud_packet_header h;
+
+        if (qemudClientRead(server, client) < 0)
+            return; /* Error, or blocking */
+
+        if (client->bufferOffset < client->bufferLength)
+            return; /* Not read enough */
+
+        /* Reparse the header to decide if this is for qemud or remote. */
+        xdrmem_create(&x, client->buffer, client->bufferLength, XDR_DECODE);
+
+        if (!xdr_qemud_packet_header(&x, &h)) {
+            qemudDebug("Failed to decode packet header");
             qemudDispatchClientFailure(server, client);
-        qemudDebug("Dispatch");
+            return;
+        }
+
+        if (remote && h.prog == REMOTE_PROGRAM) {
+            remoteDispatchClientRequest (server, client);
+        } else if (!remote && h.prog == QEMUD_PROGRAM) {
+            qemud_packet_client p;
+
+            if (!xdr_qemud_packet_client(&x, &p)) {
+                qemudDebug("Failed to decode client packet");
+                qemudDispatchClientFailure(server, client);
+                return;
+            }
+
+            qemudDispatchClientRequest(server, client, &p);
+        } else {
+            /* An internal error. */
+            qemudDebug ("Not REMOTE_PROGRAM or QEMUD_PROGRAM");
+            qemudDispatchClientFailure(server, client);
+        }
+
+        xdr_destroy (&x);
+    } else {
+        qemudDebug("Got unexpected data read while in %d mode", client->mode);
+        qemudDispatchClientFailure(server, client);
     }
 }
 
 
 static int qemudClientWrite(struct qemud_server *server,
-                           struct qemud_client *client,
-                           char *buf, size_t want) {
+                            struct qemud_client *client) {
     int ret;
-    if ((ret = write(client->fd, buf, want)) < 0) {
+    if ((ret = write(client->fd,
+                     client->buffer + client->bufferOffset,
+                     client->bufferLength - client->bufferOffset)) < 0) {
         qemudDebug("Plain write error %d", ret);
         if (errno != EAGAIN)
             qemudDispatchClientFailure(server, client);
         return -1;
     }
+    client->bufferOffset += ret;
     qemudDebug("Plain data write %d", ret);
-    return ret;
+    return 0;
 }
 
 
 static void qemudDispatchClientWrite(struct qemud_server *server, struct qemud_client *client) {
-    char *data = (char *)&client->outgoing;
-    int sent = client->outgoingSent;
-    int todo = sizeof(struct qemud_packet_header) + client->outgoing.header.dataSize - sent;
-    int ret;
-    if ((ret = qemudClientWrite(server, client, data+sent, todo)) < 0) {
-        return;
+    if (client->mode == QEMUD_MODE_TX_PACKET) {
+        if (qemudClientWrite(server, client) < 0)
+            return;
+
+        if (client->bufferOffset == client->bufferLength) {
+            /* Done writing, switch back to receive */
+            client->mode = QEMUD_MODE_RX_HEADER;
+            client->bufferLength = QEMUD_PKT_HEADER_XDR_LEN;
+            client->bufferOffset = 0;
+        }
+        /* Still writing */
+    } else {
+        qemudDebug("Got unexpected data write while in %d mode", client->mode);
+        qemudDispatchClientFailure(server, client);
     }
-    client->outgoingSent += ret;
-    qemudDebug("Done %d %d", todo, ret);
-    if (todo == ret)
-        client->tx = 0;
 }
 
 static int qemudVMData(struct qemud_server *server ATTRIBUTE_UNUSED,
@@ -1600,6 +1757,9 @@
     }
     while (client) {
         struct qemud_client *next = client->next;
+
+        assert (client->magic == QEMUD_CLIENT_MAGIC);
+
         if (fds[fd].revents) {
             qemudDebug("Poll data normal");
             if (fds[fd].revents == POLLOUT)
@@ -1676,7 +1836,7 @@
         fds[fd].fd = client->fd;
         /* Refuse to read more from client if tx is pending to
            rate limit */
-        if (client->tx)
+        if (client->mode == QEMUD_MODE_TX_PACKET)
             fds[fd].events = POLLOUT | POLLERR | POLLHUP;
         else
             fds[fd].events = POLLIN | POLLERR | POLLHUP;
@@ -1691,7 +1851,7 @@
 
 
 
-static int qemudOneLoop(struct qemud_server *server, int timeout) {
+static int qemudOneLoop(struct qemud_server *server) {
     int nfds = server->nsockets + server->nclients + server->nvmfds + 1; /* server->sigread */
     struct pollfd fds[nfds];
     int thistimeout = -1;
@@ -1740,10 +1900,10 @@
     return 0;
 }
 
-static int qemudRunLoop(struct qemud_server *server, int timeout) {
+static int qemudRunLoop(struct qemud_server *server) {
     int ret;
 
-    while ((ret = qemudOneLoop(server, timeout)) == 0 && !server->shutdown)
+    while ((ret = qemudOneLoop(server)) == 0 && !server->shutdown)
         ;
 
     return ret == -1 ? -1 : 0;
@@ -1767,6 +1927,11 @@
     if (server->iptables)
         iptablesContextFree(server->iptables);
 
+    if (server->configDir) free (server->configDir);
+    if (server->autostartDir) free (server->autostartDir);
+    if (server->networkConfigDir) free (server->networkConfigDir);
+    if (server->networkAutostartDir) free (server->networkAutostartDir);
+
     free(server);
 }
 
@@ -1775,52 +1940,94 @@
 usage (const char *argv0)
 {
     fprintf (stderr,
-             "\n"
-             "Usage:\n"
-             "  %s [options]\n"
-             "\n"
-             "Options:\n"
-             "  -v | --verbose         Verbose messages.\n"
-             "  -d | --daemon          Run as a daemon & write PID file.\n"
-             "  -s | --system          Run as system daemon.\n"
-             "  -t | --timeout <secs>  Exit after timeout period.\n"
-             "  -p | --pid-file <file> Change name of PID file.\n"
-             "\n"
-             "Notes:\n"
-             "\n"
-             "For '--system' option you must be running this daemon as root.\n"
-             "\n"
-             "The '--timeout' applies only when the daemon is not servicing\n"
-             "clients.\n"
-             "\n"
-             "Default paths:\n"
-             "\n"
-             "  Sockets (in system mode):\n"
-             "    " LOCAL_STATE_DIR "/run/libvirt/qemud-sock\n"
-             "    " LOCAL_STATE_DIR "/run/libvirt/qemud-sock-ro\n"
-             "\n"
-             "  Sockets (not in system mode):\n"
-             "    $HOME/.libvirt/qemud-sock (in Unix abstract namespace)\n"
-             "\n"
-             "  PID file (unless overridden by --pid-file):\n"
-             "    " QEMUD_PID_FILE "\n"
-             "\n",
-             argv0);
+             "\n\
+Usage:\n\
+  %s [options]\n\
+\n\
+Options:\n\
+  -v | --verbose         Verbose messages.\n\
+  -d | --daemon          Run as a daemon & write PID file.\n\
+  -r | --remote          Act as remote server.\n\
+  -s | --system          Run as system daemon.\n\
+  -t | --timeout <secs>  Exit after timeout period.\n\
+  -p | --pid-file <file> Change name of PID file.\n\
+\n\
+Remote and QEMU/network management:\n\
+\n\
+The '--remote' flag selects between running as a remote server\n\
+for remote libvirt requests, versus running as a QEMU\n\
+and network management daemon.\n\
+\n\
+Normally you need to have one daemon of each type.\n\
+\n\
+See also http://libvirt.org/remote.html\n\
+\n\
+For remote daemon:\n\
+\n\
+  Default paths:\n\
+\n\
+    Configuration file:\n\
+      " SYSCONF_DIR "/libvirt/libvirtd.conf\n\
+\n\
+    Sockets:\n\
+      " LOCAL_STATE_DIR "/run/libvirt/libvirt-sock\n\
+      " LOCAL_STATE_DIR "/run/libvirt/libvirt-sock-ro\n\
+\n\
+    PID file (unless overridden by --pid-file):\n\
+      %s\n\
+\n\
+For QEMU and network management daemon:\n\
+\n\
+  For '--system' option you must be running this daemon as root.\n\
+\n\
+  The '--timeout' applies only when the daemon is not servicing\n\
+  clients.\n\
+\n\
+  Default paths:\n\
+\n\
+    Configuration files (in system mode):\n\
+      " SYSCONF_DIR "/libvirt/qemu\n\
+      " SYSCONF_DIR "/libvirt/qemu/autostart\n\
+      " SYSCONF_DIR "/libvirt/qemu/networkd\n\
+      " SYSCONF_DIR "/libvirt/qemu/networks/autostart\n\
+\n\
+    Configuration files (not in system mode):\n\
+      $HOME/.libvirt/qemu\n\
+      $HOME/.libvirt/qemu/autostart\n\
+      $HOME/.libvirt/qemu/networks\n\
+      $HOME/.libvirt/qemu/networks/autostart\n\
+\n\
+    Sockets (in system mode):\n\
+      " LOCAL_STATE_DIR "/run/libvirt/qemud-sock\n\
+      " LOCAL_STATE_DIR "/run/libvirt/qemud-sock-ro\n\
+\n\
+    Sockets (not in system mode):\n\
+      $HOME/.libvirt/qemud-sock (in Unix abstract namespace)\n\
+\n\
+    PID file (unless overridden by --pid-file):\n\
+      %s\n\
+\n",
+             argv0,
+             REMOTE_PID_FILE[0] != '\0'
+               ? REMOTE_PID_FILE
+               : "(disabled in configure)",
+             QEMUD_PID_FILE[0] != '\0'
+               ? QEMUD_PID_FILE
+               : "(disabled in configure)");
 }
 
 #define MAX_LISTEN 5
 int main(int argc, char **argv) {
-    int sys = 0;
-    int timeout = -1;
     struct qemud_server *server;
     struct sigaction sig_action;
     int sigpipe[2];
-    char *pid_file = NULL;
+    const char *pid_file = NULL;
     int ret = 1;
 
     struct option opts[] = {
         { "verbose", no_argument, &verbose, 1},
         { "daemon", no_argument, &godaemon, 1},
+        { "remote", no_argument, &remote, 1},
         { "system", no_argument, &sys, 1},
         { "timeout", required_argument, NULL, 't'},
         { "pid-file", required_argument, NULL, 'p'},
@@ -1849,6 +2056,9 @@
         case 'd':
             godaemon = 1;
             break;
+        case 'r':
+            remote = 1;
+            break;
         case 's':
             sys = 1;
             break;
@@ -1862,7 +2072,7 @@
             break;
 
         case 'p':
-            pid_file = strdup(optarg);
+            pid_file = optarg;
             break;
 
         case '?':
@@ -1910,16 +2120,27 @@
         if (pid > 0)
             goto out;
 
-        if (qemudWritePidFile(pid_file ? pid_file : QEMUD_PID_FILE) < 0)
+        /* Choose the name of the PID file. */
+        if (!pid_file) {
+            if (remote) {
+                if (REMOTE_PID_FILE[0] != '\0')
+                    pid_file = REMOTE_PID_FILE;
+            } else {
+                if (QEMUD_PID_FILE[0] != '\0')
+                    pid_file = QEMUD_PID_FILE;
+            }
+        }
+
+        if (pid_file && qemudWritePidFile (pid_file) < 0)
             goto error1;
     }
 
-    if (!(server = qemudInitialize(sys, sigpipe[0]))) {
+    if (!(server = qemudInitialize(sigpipe[0]))) {
         ret = 2;
         goto error2;
     }
 
-    qemudRunLoop(server, timeout);
+    qemudRunLoop(server);
 
     qemudCleanup(server);
 
@@ -1932,13 +2153,10 @@
     ret = 0;
 
  error2:
-    if (godaemon)
-        unlink(pid_file ? pid_file : QEMUD_PID_FILE);
+    if (godaemon && pid_file)
+        unlink (pid_file);
 
  error1:
-    if (pid_file)
-        free(pid_file);
-
     return ret;
 }
 
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/remote.c libvirt-remote/qemud/remote.c
--- libvirt-cvs/qemud/remote.c	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-remote/qemud/remote.c	2007-04-17 19:33:11.000000000 +0100
@@ -0,0 +1,446 @@
+/*
+ * remote.c: code handling remote requests (from remote_internal.c)
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Richard W.M. Jones <rjones@xxxxxxxxxx>
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <limits.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include <libvirt/virterror.h>
+
+#include "internal.h"
+#include "../src/internal.h"
+#include "dispatch.h"
+#include "driver.h"
+#include "conf.h"
+#include "iptables.h"
+
+#define DEBUG 1
+
+static void remoteDispatchError (struct qemud_client *client,
+                                 remote_message_header *req,
+                                 const char *fmt, ...);
+
+static int remoteDispatchOpen (struct qemud_client *client, remote_message_header *req, struct remote_open_args *args, void *ret);
+static int remoteDispatchClose (struct qemud_client *client, remote_message_header *req, void *args, void *ret);
+static int remoteDispatchGetCapabilities (struct qemud_client *client, remote_message_header *req, void *args, remote_get_capabilities_ret *ret);
+
+typedef int (*dispatch_fn) (struct qemud_client *client, remote_message_header *req, char *args, char *ret);
+
+/* This function gets called from qemud when it detects an incoming
+ * remote protocol message.  At this point, client->buffer contains
+ * the full call message (including length word which we skip).
+ */
+void
+remoteDispatchClientRequest (struct qemud_server *server ATTRIBUTE_UNUSED,
+                             struct qemud_client *client)
+{
+    XDR xdr;
+    remote_message_header req, rep;
+    dispatch_fn fn;
+    xdrproc_t args_filter = (xdrproc_t) xdr_void;
+    xdrproc_t ret_filter = (xdrproc_t) xdr_void;
+    char *args = NULL, *ret = NULL;
+    int rv, len;
+
+    remote_open_args open_args;
+    remote_get_capabilities_ret get_capabilities_ret;
+
+    /* Parse the header. */
+    xdrmem_create (&xdr, client->buffer+4, client->bufferLength-4, XDR_DECODE);
+
+    if (!xdr_remote_message_header (&xdr, &req)) {
+        remoteDispatchError (client, NULL, "xdr_remote_message_header");
+        xdr_destroy (&xdr);
+        return;
+    }
+
+    /* Check version, etc. */
+    if (req.prog != REMOTE_PROGRAM) {
+        remoteDispatchError (client, &req, "program mismatch (actual %x, expected %x)",
+                             req.prog, REMOTE_PROGRAM);
+        xdr_destroy (&xdr);
+        return;
+    }
+    if (req.vers != REMOTE_PROTOCOL_VERSION) {
+        remoteDispatchError (client, &req, "version mismatch (actual %x, expected %x)",
+                             req.vers, REMOTE_PROTOCOL_VERSION);
+        xdr_destroy (&xdr);
+        return;
+    }
+    if (req.direction != REMOTE_CALL) {
+        remoteDispatchError (client, &req, "direction (%d) != REMOTE_CALL",
+                             (int) req.direction);
+        xdr_destroy (&xdr);
+        return;
+    }
+    if (req.status != REMOTE_OK) {
+        remoteDispatchError (client, &req, "status (%d) != REMOTE_OK",
+                             (int) req.status);
+        xdr_destroy (&xdr);
+        return;
+    }
+
+    /* Based on the procedure number, dispatch.  In future we may base
+     * this on the version number as well.
+     */
+    switch (req.proc) {
+    case REMOTE_PROC_OPEN:
+        fn = (dispatch_fn) remoteDispatchOpen;
+        args_filter = (xdrproc_t) xdr_remote_open_args;
+        args = (char *) &open_args;
+        memset (&open_args, 0, sizeof open_args);
+        break;
+
+    case REMOTE_PROC_CLOSE:
+        fn = (dispatch_fn) remoteDispatchClose;
+        break;
+
+    case REMOTE_PROC_GET_CAPABILITIES:
+        fn = (dispatch_fn) remoteDispatchGetCapabilities;
+        ret_filter = (xdrproc_t) xdr_remote_get_capabilities_ret;
+        ret = (char *) &get_capabilities_ret;
+        memset (&get_capabilities_ret, 0, sizeof get_capabilities_ret);
+        break;
+
+    default:
+        remoteDispatchError (client, &req, "unknown procedure: %d",
+                             req.proc);
+        xdr_destroy (&xdr);
+        return;
+    }
+
+    /* Parse args. */
+    if (!(*args_filter) (&xdr, args)) {
+        remoteDispatchError (client, &req, "parse args failed");
+        xdr_destroy (&xdr);
+        return;
+    }
+
+    xdr_destroy (&xdr);
+
+    /* Call function. */
+    rv = fn (client, &req, args, ret);
+
+    xdr_free (args_filter, args);
+
+    /* Dispatch error?  If so then the function has already set up the
+     * return buffer, so just return immediately.
+     */
+    if (rv == -2) return;
+
+    /* Return header. */
+    rep.prog = req.prog;
+    rep.vers = req.vers;
+    rep.proc = req.proc;
+    rep.direction = REMOTE_REPLY;
+    rep.serial = req.serial;
+    rep.status = rv == 0 ? REMOTE_OK : REMOTE_ERROR;
+
+    /* Serialise the return header. */
+    xdrmem_create (&xdr, client->buffer, sizeof client->buffer, XDR_ENCODE);
+
+    len = 0; /* We'll come back and write this later. */
+    if (!xdr_int (&xdr, &len)) {
+        remoteDispatchError (client, &req, "dummy length");
+        xdr_destroy (&xdr);
+        if (rv == 0) xdr_free (ret_filter, ret);
+        return;
+    }
+
+    if (!xdr_remote_message_header (&xdr, &rep)) {
+        remoteDispatchError (client, &req, "serialise reply header");
+        xdr_destroy (&xdr);
+        if (rv == 0) xdr_free (ret_filter, ret);
+        return;
+    }
+
+    /* If OK, serialise return structure, if error serialise error. */
+    if (rv == 0) {
+        if (!(*ret_filter) (&xdr, ret)) {
+            remoteDispatchError (client, &req, "serialise return struct");
+            xdr_destroy (&xdr);
+            return;
+        }
+        xdr_free (ret_filter, ret);
+    } else /* error */ {
+        virErrorPtr verr;
+        remote_error error;
+        remote_name domname, netname;
+
+        verr = client->conn
+            ? virConnGetLastError (client->conn)
+            : virGetLastError ();
+
+        if (verr) {
+            error.code = verr->code;
+            error.domain = verr->domain;
+            error.message = verr->message ? &verr->message : NULL;
+            error.level = verr->level;
+            if (verr->dom) {
+                domname.name = verr->dom->name;
+                memcpy (domname.uuid, verr->dom->uuid, VIR_UUID_BUFLEN);
+            }
+            error.dom = verr->dom ? &domname : NULL;
+            error.str1 = verr->str1 ? &verr->str1 : NULL;
+            error.str2 = verr->str2 ? &verr->str2 : NULL;
+            error.str3 = verr->str3 ? &verr->str3 : NULL;
+            error.int1 = verr->int1;
+            error.int2 = verr->int2;
+            if (verr->net) {
+                netname.name = verr->net->name;
+                memcpy (netname.uuid, verr->net->uuid, VIR_UUID_BUFLEN);
+            }
+            error.net = verr->net ? &netname : NULL;
+        } else {
+            /* Error was NULL so synthesize an error. */
+            char msgbuf[] = "remoteDispatchClientRequest: internal error: library function returned error but did not set virterror";
+            char *msg = msgbuf;
+
+            error.code = VIR_ERR_RPC;
+            error.domain = VIR_FROM_REMOTE;
+            error.message = &msg;
+            error.level = VIR_ERR_ERROR;
+            error.dom = NULL;
+            error.str1 = &msg;
+            error.str2 = NULL;
+            error.str3 = NULL;
+            error.int1 = 0;
+            error.int2 = 0;
+            error.net = NULL;
+        }
+
+        if (!xdr_remote_error (&xdr, &error)) {
+            remoteDispatchError (client, &req, "serialise return error");
+            xdr_destroy (&xdr);
+            return;
+        }
+    }
+
+    /* Write the length word. */
+    len = xdr_getpos (&xdr);
+    if (xdr_setpos (&xdr, 0) == 0) {
+        remoteDispatchError (client, &req, "xdr_setpos");
+        xdr_destroy (&xdr);
+        return;
+    }
+
+    if (!xdr_int (&xdr, &len)) {
+        remoteDispatchError (client, &req, "serialise return length");
+        xdr_destroy (&xdr);
+        return;
+    }
+
+    xdr_destroy (&xdr);
+
+    /* Set up the output buffer. */
+    client->mode = QEMUD_MODE_TX_PACKET;
+    client->bufferLength = len;
+    client->bufferOffset = 0;
+}
+
+/* An error occurred during the dispatching process itself (ie. not
+ * an error from the function being called).  We return an error
+ * reply.
+ */
+static void
+remoteDispatchError (struct qemud_client *client,
+                     remote_message_header *req,
+                     const char *fmt, ...)
+{
+    remote_message_header rep;
+    remote_error error;
+    va_list args;
+    char msgbuf[1024];
+    char *msg = msgbuf;
+    XDR xdr;
+    int len;
+
+    va_start (args, fmt);
+    vsnprintf (msgbuf, sizeof msgbuf, fmt, args);
+    va_end (args);
+
+    qemudDebug ("%s", msgbuf);
+
+    /* Future versions of the protocol may use different vers or prog.  Try
+     * our hardest to send back a message that such clients could see.
+     */
+    if (req) {
+        rep.prog = req->prog;
+        rep.vers = req->vers;
+        rep.proc = req->proc;
+        rep.direction = REMOTE_REPLY;
+        rep.serial = req->serial;
+        rep.status = REMOTE_ERROR;
+    } else {
+        rep.prog = REMOTE_PROGRAM;
+        rep.vers = REMOTE_PROTOCOL_VERSION;
+        rep.proc = REMOTE_PROC_OPEN;
+        rep.direction = REMOTE_REPLY;
+        rep.serial = 1;
+        rep.status = REMOTE_ERROR;
+    }
+
+    /* Construct the error. */
+    error.code = VIR_ERR_RPC;
+    error.domain = VIR_FROM_REMOTE;
+    error.message = &msg;
+    error.level = VIR_ERR_ERROR;
+    error.dom = NULL;
+    error.str1 = &msg;
+    error.str2 = NULL;
+    error.str3 = NULL;
+    error.int1 = 0;
+    error.int2 = 0;
+    error.net = NULL;
+
+    /* Serialise the return header and error. */
+    xdrmem_create (&xdr, client->buffer, sizeof client->buffer, XDR_ENCODE);
+
+    len = 0; /* We'll come back and write this later. */
+    if (!xdr_int (&xdr, &len)) {
+        xdr_destroy (&xdr);
+        return;
+    }
+
+    if (!xdr_remote_message_header (&xdr, &rep)) {
+        xdr_destroy (&xdr);
+        return;
+    }
+
+    if (!xdr_remote_error (&xdr, &error)) {
+        xdr_destroy (&xdr);
+        return;
+    }
+
+    len = xdr_getpos (&xdr);
+    if (xdr_setpos (&xdr, 0) == 0) {
+        xdr_destroy (&xdr);
+        return;
+    }
+
+    if (!xdr_int (&xdr, &len)) {
+        xdr_destroy (&xdr);
+        return;
+    }
+
+    xdr_destroy (&xdr);
+
+    /* Send it. */
+    client->mode = QEMUD_MODE_TX_PACKET;
+    client->bufferLength = len;
+    client->bufferOffset = 0;
+}
+
+/*----- Functions. -----*/
+
+static int
+remoteDispatchOpen (struct qemud_client *client, remote_message_header *req,
+                    struct remote_open_args *args, void *ret ATTRIBUTE_UNUSED)
+{
+    const char *name;
+
+    /* Already opened? */
+    if (client->conn) {
+        remoteDispatchError (client, req, "connection already open");
+        return -2;
+    }
+
+    name = args->name ? *args->name : NULL;
+
+#if DEBUG
+    fprintf (stderr, "remoteDispatchOpen: name = %s\n", name);
+#endif
+
+    client->conn =
+        args->flags & VIR_CONNECT_RO
+        ? virConnectOpenReadOnly (name)
+        : virConnectOpen (name);
+
+    return client->conn ? 0 : -1;
+}
+
+static int
+remoteDispatchClose (struct qemud_client *client, remote_message_header *req,
+                     void *args ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED)
+{
+    int rv;
+
+    if (!client->conn) {
+        remoteDispatchError (client, req, "connection not open");
+        return -2;
+    }
+
+    rv = virConnectClose (client->conn);
+    if (rv == 0) client->conn = NULL;
+
+    return rv;
+}
+
+static int
+remoteDispatchGetCapabilities (struct qemud_client *client,
+                               remote_message_header *req,
+                               void *args ATTRIBUTE_UNUSED,
+                               remote_get_capabilities_ret *ret)
+{
+    char *caps;
+
+    if (!client->conn) {
+        remoteDispatchError (client, req, "connection not open");
+        return -2;
+    }
+
+    caps = virConnectGetCapabilities (client->conn);
+    if (caps == NULL) return -1;
+
+    ret->capabilities = caps;
+    return 0;
+}
+
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/remote_protocol.c libvirt-remote/qemud/remote_protocol.c
--- libvirt-cvs/qemud/remote_protocol.c	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-remote/qemud/remote_protocol.c	2007-04-23 12:35:33.000000000 +0100
@@ -0,0 +1,149 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "remote_protocol.h"
+#include "libvirt/libvirt.h"
+
+bool_t
+xdr_remote_nonnull_string (XDR *xdrs, remote_nonnull_string *objp)
+{
+
+	 if (!xdr_string (xdrs, objp, REMOTE_STRING_MAX))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_string (XDR *xdrs, remote_string *objp)
+{
+
+	 if (!xdr_pointer (xdrs, (char **)objp, sizeof (remote_nonnull_string), (xdrproc_t) xdr_remote_nonnull_string))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_name (XDR *xdrs, remote_name *objp)
+{
+
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->name))
+		 return FALSE;
+	 if (!xdr_opaque (xdrs, objp->uuid, VIR_UUID_BUFLEN))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain (XDR *xdrs, remote_domain *objp)
+{
+
+	 if (!xdr_pointer (xdrs, (char **)objp, sizeof (remote_name), (xdrproc_t) xdr_remote_name))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network (XDR *xdrs, remote_network *objp)
+{
+
+	 if (!xdr_pointer (xdrs, (char **)objp, sizeof (remote_name), (xdrproc_t) xdr_remote_name))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_error (XDR *xdrs, remote_error *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->code))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->domain))
+		 return FALSE;
+	 if (!xdr_remote_string (xdrs, &objp->message))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->level))
+		 return FALSE;
+	 if (!xdr_remote_domain (xdrs, &objp->dom))
+		 return FALSE;
+	 if (!xdr_remote_string (xdrs, &objp->str1))
+		 return FALSE;
+	 if (!xdr_remote_string (xdrs, &objp->str2))
+		 return FALSE;
+	 if (!xdr_remote_string (xdrs, &objp->str3))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->int1))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->int2))
+		 return FALSE;
+	 if (!xdr_remote_network (xdrs, &objp->net))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_open_args (XDR *xdrs, remote_open_args *objp)
+{
+
+	 if (!xdr_remote_string (xdrs, &objp->name))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->flags))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_get_capabilities_ret (XDR *xdrs, remote_get_capabilities_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->capabilities))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_procedure (XDR *xdrs, remote_procedure *objp)
+{
+
+	 if (!xdr_enum (xdrs, (enum_t *) objp))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_message_direction (XDR *xdrs, remote_message_direction *objp)
+{
+
+	 if (!xdr_enum (xdrs, (enum_t *) objp))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_message_status (XDR *xdrs, remote_message_status *objp)
+{
+
+	 if (!xdr_enum (xdrs, (enum_t *) objp))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_message_header (XDR *xdrs, remote_message_header *objp)
+{
+
+	 if (!xdr_u_int (xdrs, &objp->prog))
+		 return FALSE;
+	 if (!xdr_u_int (xdrs, &objp->vers))
+		 return FALSE;
+	 if (!xdr_remote_procedure (xdrs, &objp->proc))
+		 return FALSE;
+	 if (!xdr_remote_message_direction (xdrs, &objp->direction))
+		 return FALSE;
+	 if (!xdr_u_int (xdrs, &objp->serial))
+		 return FALSE;
+	 if (!xdr_remote_message_status (xdrs, &objp->status))
+		 return FALSE;
+	return TRUE;
+}
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/remote_protocol.h libvirt-remote/qemud/remote_protocol.h
--- libvirt-cvs/qemud/remote_protocol.h	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-remote/qemud/remote_protocol.h	2007-04-23 12:35:29.000000000 +0100
@@ -0,0 +1,128 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _REMOTE_PROTOCOL_H_RPCGEN
+#define _REMOTE_PROTOCOL_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "libvirt/libvirt.h"
+#define REMOTE_MESSAGE_MAX 262144
+#define REMOTE_STRING_MAX 65536
+
+typedef char *remote_nonnull_string;
+
+typedef remote_nonnull_string *remote_string;
+
+struct remote_name {
+	remote_nonnull_string name;
+	char uuid[VIR_UUID_BUFLEN];
+};
+typedef struct remote_name remote_name;
+
+typedef remote_name *remote_domain;
+
+typedef remote_name *remote_network;
+
+struct remote_error {
+	int code;
+	int domain;
+	remote_string message;
+	int level;
+	remote_domain dom;
+	remote_string str1;
+	remote_string str2;
+	remote_string str3;
+	int int1;
+	int int2;
+	remote_network net;
+};
+typedef struct remote_error remote_error;
+
+struct remote_open_args {
+	remote_string name;
+	int flags;
+};
+typedef struct remote_open_args remote_open_args;
+
+struct remote_get_capabilities_ret {
+	remote_nonnull_string capabilities;
+};
+typedef struct remote_get_capabilities_ret remote_get_capabilities_ret;
+#define REMOTE_PROGRAM 0x20008086
+#define REMOTE_PROTOCOL_VERSION 1
+
+enum remote_procedure {
+	REMOTE_PROC_OPEN = 1,
+	REMOTE_PROC_CLOSE = 2,
+	REMOTE_PROC_GET_CAPABILITIES = 3,
+};
+typedef enum remote_procedure remote_procedure;
+
+enum remote_message_direction {
+	REMOTE_CALL = 0,
+	REMOTE_REPLY = 1,
+	REMOTE_MESSAGE = 2,
+};
+typedef enum remote_message_direction remote_message_direction;
+
+enum remote_message_status {
+	REMOTE_OK = 0,
+	REMOTE_ERROR = 1,
+};
+typedef enum remote_message_status remote_message_status;
+
+struct remote_message_header {
+	u_int prog;
+	u_int vers;
+	remote_procedure proc;
+	remote_message_direction direction;
+	u_int serial;
+	remote_message_status status;
+};
+typedef struct remote_message_header remote_message_header;
+
+/* the xdr functions */
+
+#if defined(__STDC__) || defined(__cplusplus)
+extern  bool_t xdr_remote_nonnull_string (XDR *, remote_nonnull_string*);
+extern  bool_t xdr_remote_string (XDR *, remote_string*);
+extern  bool_t xdr_remote_name (XDR *, remote_name*);
+extern  bool_t xdr_remote_domain (XDR *, remote_domain*);
+extern  bool_t xdr_remote_network (XDR *, remote_network*);
+extern  bool_t xdr_remote_error (XDR *, remote_error*);
+extern  bool_t xdr_remote_open_args (XDR *, remote_open_args*);
+extern  bool_t xdr_remote_get_capabilities_ret (XDR *, remote_get_capabilities_ret*);
+extern  bool_t xdr_remote_procedure (XDR *, remote_procedure*);
+extern  bool_t xdr_remote_message_direction (XDR *, remote_message_direction*);
+extern  bool_t xdr_remote_message_status (XDR *, remote_message_status*);
+extern  bool_t xdr_remote_message_header (XDR *, remote_message_header*);
+
+#else /* K&R C */
+extern bool_t xdr_remote_nonnull_string ();
+extern bool_t xdr_remote_string ();
+extern bool_t xdr_remote_name ();
+extern bool_t xdr_remote_domain ();
+extern bool_t xdr_remote_network ();
+extern bool_t xdr_remote_error ();
+extern bool_t xdr_remote_open_args ();
+extern bool_t xdr_remote_get_capabilities_ret ();
+extern bool_t xdr_remote_procedure ();
+extern bool_t xdr_remote_message_direction ();
+extern bool_t xdr_remote_message_status ();
+extern bool_t xdr_remote_message_header ();
+
+#endif /* K&R C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_REMOTE_PROTOCOL_H_RPCGEN */
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/remote_protocol.x libvirt-remote/qemud/remote_protocol.x
--- libvirt-cvs/qemud/remote_protocol.x	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-remote/qemud/remote_protocol.x	2007-04-18 14:05:06.000000000 +0100
@@ -0,0 +1,183 @@
+/* -*- c -*-
+ * remote_protocol.x: private protocol for communicating between
+ *   remote_internal driver and libvirtd.  This protocol is
+ *   internal and may change at any time.
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Richard Jones <rjones@xxxxxxxxxx>
+ */
+
+/* Notes:
+ *
+ * (1) The protocol is internal and may change at any time, without
+ * notice.  Do not use it.  Instead link to libvirt and use the remote
+ * driver.
+ *
+ * (2) See bottom of this file for a description of the home-brew RPC.
+ *
+ * (3) Authentication/encryption is done outside this protocol.
+ *
+ * (4) For namespace reasons, all exported names begin 'remote_' or
+ * 'REMOTE_'.  This makes names quite long.
+ */
+
+%#include "libvirt/libvirt.h"
+
+/*----- Data types. -----*/
+
+/* Maximum total message size (serialised). */
+const REMOTE_MESSAGE_MAX = 262144;
+
+/* Length of long, but not unbounded, strings.
+ * This is an arbitrary limit designed to stop the decoder from trying
+ * to allocate unbounded amounts of memory when fed with a bad message.
+ */
+const REMOTE_STRING_MAX = 65536;
+
+/* A long string, which may NOT be NULL. */
+typedef string remote_nonnull_string<REMOTE_STRING_MAX>;
+
+/* A long string, which may be NULL. */
+typedef remote_nonnull_string *remote_string;
+
+/* Domains and networks are represented on the wire by (name, UUID). */
+struct remote_name {
+    remote_nonnull_string name;
+    opaque uuid[VIR_UUID_BUFLEN];
+};
+typedef struct remote_name *remote_domain;
+typedef struct remote_name *remote_network;
+
+/* Error message. See <virterror.h> for explanation of fields. */
+
+/* NB. Fields "code", "domain" and "level" are really enums.  The
+ * numeric value should remain compatible between libvirt and
+ * libvirtd.  This means, no changing or reordering the enums as
+ * defined in <virterror.h> (but we don't do that anyway, for separate
+ * ABI reasons).
+ */
+struct remote_error {
+    int code;
+    int domain;
+    remote_string message;
+    int level;
+    remote_domain dom;
+    remote_string str1;
+    remote_string str2;
+    remote_string str3;
+    int int1;
+    int int2;
+    remote_network net;
+};
+
+/*----- Calls. -----*/
+
+/* NB. "name" might be NULL although in practice you can't set it
+ * using the remote_internal driver.
+ */
+struct remote_open_args {
+    remote_string name;
+    int flags;
+};
+
+/*typedef void remote_open_ret;*/
+
+/*typedef void remote_close_args;*/
+
+/*typedef void remote_close_ret;*/
+
+/*typedef void remote_get_capabilities_args;*/
+
+struct remote_get_capabilities_ret {
+    remote_nonnull_string capabilities;
+};
+
+
+
+
+
+
+
+
+
+/*----- Protocol. -----*/
+
+/* Define the program number, protocol version and procedure numbers here. */
+const REMOTE_PROGRAM = 0x20008086;
+const REMOTE_PROTOCOL_VERSION = 1;
+
+enum remote_procedure {
+    REMOTE_PROC_OPEN = 1,
+    REMOTE_PROC_CLOSE = 2,
+    REMOTE_PROC_GET_CAPABILITIES = 3
+};
+
+/* Custom RPC structure. */
+/* Each message consists of:
+ *    int length               Number of bytes in message _including_ length.
+ *    remote_message_header    Header.
+ * then either: args           Arguments (for REMOTE_CALL).
+ *          or: ret            Return (for REMOTE_REPLY, status = REMOTE_OK)
+ *          or: remote_error   Error (for REMOTE_REPLY, status = REMOTE_ERROR)
+ *
+ * The first two words (length, program number) are meant to be compatible
+ * with the qemud protocol (qemud/protocol.x), although the rest of the
+ * messages are completely different.
+ */
+
+enum remote_message_direction {
+    REMOTE_CALL = 0,            /* client -> server */
+    REMOTE_REPLY = 1,           /* server -> client */
+    REMOTE_MESSAGE = 2          /* server -> client, asynchronous [NYI] */
+};
+
+enum remote_message_status {
+    /* Status is always REMOTE_OK for calls.
+     * For replies, indicates no error.
+     */
+    REMOTE_OK = 0,
+
+    /* For replies, indicates that an error happened, and a struct
+     * remote_error follows.
+     */
+    REMOTE_ERROR = 1
+};
+
+struct remote_message_header {
+    unsigned prog;              /* REMOTE_PROGRAM */
+    unsigned vers;              /* REMOTE_PROTOCOL_VERSION */
+    remote_procedure proc;      /* REMOTE_PROC_x */
+    remote_message_direction direction;
+    unsigned serial;            /* Serial number of message. */
+    remote_message_status status;
+};
+
+
+/*
+ * vim: set tabstop=4:
+ * vim: set shiftwidth=4:
+ * vim: set expandtab:
+ */
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/rpcgen_fix.pl libvirt-remote/qemud/rpcgen_fix.pl
--- libvirt-cvs/qemud/rpcgen_fix.pl	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-remote/qemud/rpcgen_fix.pl	2007-04-17 15:38:46.000000000 +0100
@@ -0,0 +1,68 @@
+# Fix XDR code (generated by rpcgen) so that it compiles
+# with warnings turned on.
+#
+# This code is evil.  Arguably better would be just to compile
+# without -Werror.
+#
+# Copyright (C) 2007 Red Hat, Inc.
+#
+# See COPYING for the license of this software.
+#
+# Richard Jones <rjones@xxxxxxxxxx>
+
+use strict;
+
+my $in_function = 0;
+my @function = ();
+
+while (<>) {
+    if (m/^{/) {
+	$in_function = 1;
+	print;
+	next;
+    }
+
+    if (m/^}/) {
+	$in_function = 0;
+
+	# Note: The body of the function is in @function.
+
+	# Remove decl of buf, if buf isn't used in the function.
+	my @uses = grep /\bbuf\b/, @function;
+	@function = grep !/\bbuf\b/, @function if @uses == 1;
+
+	# Remove decl of i, if i isn't used in the function.
+	@uses = grep /\bi\b/, @function;
+	@function = grep !/\bi\b/, @function if @uses == 1;
+
+# 	# (char **)&objp->... gives:
+# 	# warning: dereferencing type-punned pointer will break
+# 	#   strict-aliasing rules
+# 	# so rewrite it.
+# 	@uses = grep /\(char \*\*\)\&objp->remote_listDomains_ret_u\.ids\.ids_val/, @function;
+# 	if (@uses >= 1) {
+# 	    unshift @function,
+# 	      ("\tchar *objp_cp = (char *) objp->remote_listDomains_ret_u.ids.ids_val;\n",
+# 	       "\tchar **objp_cpp = &objp_cp;\n");
+# 	    @function =
+# 		map { s{\(char \*\*\)\&objp->remote_listDomains_ret_u\.ids\.ids_val}{objp_cpp}g; $_ } @function;
+# 	}
+
+	# The code uses 'IXDR_PUT_{U_,}LONG' but it's wrong in two
+	# ways: Firstly these functions are deprecated and don't
+	# work on 64 bit platforms.  Secondly the return value should
+	# be ignored.  Correct both these mistakes.
+	@function =
+	    map { s/\bIXDR_PUT_((U_)?)LONG\b/(void)IXDR_PUT_$1INT32/; $_ }
+	    @function;
+
+	print (join ("", @function));
+	@function = ();
+    }
+
+    unless ($in_function) {
+	print;
+    } else {
+	push @function, $_;
+    }
+}
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/qemud/uuid.c libvirt-remote/qemud/uuid.c
--- libvirt-cvs/qemud/uuid.c	2007-02-26 15:34:24.000000000 +0000
+++ libvirt-remote/qemud/uuid.c	2007-04-17 11:20:18.000000000 +0100
@@ -32,7 +32,6 @@
 #include <time.h>
 #include <unistd.h>
 
-#include "protocol.h"
 #include "internal.h"
 
 static int
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/RENAMES libvirt-remote/RENAMES
--- libvirt-cvs/RENAMES	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-remote/RENAMES	2007-04-23 12:21:08.000000000 +0100
@@ -0,0 +1,32 @@
+# Suggested list of file renames.
+#
+# File renames don't normally go into patches because they make
+# the patches much harder to read, so list them here instead.
+#
+# $Id$
+
+# Clearer naming scheme after Xen-unified patch went in.
+src/xen_internal.c	src/xen_internal_hv.c
+src/xen_internal.h	src/xen_internal_hv.h
+src/proxy_internal.c	src/xen_internal_proxy.c
+src/proxy_internal.h	src/xen_internal_proxy.h
+src/xend_internal.c	src/xen_internal_xend.c
+src/xend_internal.h	src/xen_internal_xend.h
+src/xm_internal.c	src/xen_internal_inactive.c
+src/xm_internal.h	src/xen_internal_inactive.h
+src/xs_internal.c	src/xen_internal_xenstore.c
+src/xs_internal.h	src/xen_internal_xenstore.h
+src/xen_unified.c	src/xen_internal.c
+src/xen_unified.h	src/xen_internal.h
+
+# Test driver should really be called test_internal.
+src/test.c		src/test_internal.c
+src/test.h		src/test_internal.h
+
+# This would be better:
+src/*_internal*.c	src/*_driver*.c
+src/*_internal*.h	src/*_driver*.h
+
+# Qemud is now the qemud + remote driver.
+qemud/protocol.x	qemud/qemud_protocol.x
+qemud/*			remote/*
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/src/driver.h libvirt-remote/src/driver.h
--- libvirt-cvs/src/driver.h	2007-04-04 15:39:43.000000000 +0100
+++ libvirt-remote/src/driver.h	2007-04-17 11:18:28.000000000 +0100
@@ -20,6 +20,7 @@
     VIR_DRV_XEN_UNIFIED = 1,
     VIR_DRV_TEST = 2,
     VIR_DRV_QEMU = 3,
+    VIR_DRV_REMOTE = 4,
 } virDrvNo;
 
 
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/src/libvirt.c libvirt-remote/src/libvirt.c
--- libvirt-cvs/src/libvirt.c	2007-04-26 11:23:39.000000000 +0100
+++ libvirt-remote/src/libvirt.c	2007-04-18 11:18:19.000000000 +0100
@@ -28,6 +28,7 @@
 #include "test.h"
 #include "xen_unified.h"
 #include "qemu_internal.h"
+#include "remote_internal.h"
 
 /*
  * TODO:
@@ -64,6 +65,9 @@
      * Note that the order is important: the first ones have a higher
      * priority when calling virConnectOpen.
      */
+#ifdef WITH_REMOTE
+    if (remoteRegister () == -1) return -1;
+#endif
 #ifdef WITH_TEST
     if (testRegister() == -1) return -1;
 #endif
@@ -378,6 +382,9 @@
  * Get the name of the Hypervisor software used.
  *
  * Returns NULL in case of error, a static zero terminated string otherwise.
+ *
+ * See also:
+ * http://www.redhat.com/archives/libvir-list/2007-February/msg00096.html
  */
 const char *
 virConnectGetType(virConnectPtr conn)
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/src/Makefile.am libvirt-remote/src/Makefile.am
--- libvirt-cvs/src/Makefile.am	2007-04-04 15:39:43.000000000 +0100
+++ libvirt-remote/src/Makefile.am	2007-04-17 14:50:28.000000000 +0100
@@ -1,9 +1,16 @@
 ## Process this file with automake to produce Makefile.in
 
-INCLUDES = -I$(top_builddir)/include -I@top_srcdir@/include @LIBXML_CFLAGS@ -I@top_srcdir@/qemud \
-	   -DBINDIR=\""$(libexecdir)"\" -DSBINDIR=\""$(sbindir)"\" -DLOCALEBASEDIR=\""$(datadir)/locale"\" \
+INCLUDES = -I$(top_builddir)/include \
+	   -I@top_srcdir@/include \
+	   -I@top_srcdir@/qemud \
+	   @LIBXML_CFLAGS@ \
+	   -DBINDIR=\""$(libexecdir)"\" \
+	   -DSBINDIR=\""$(sbindir)"\" \
+	   -DLOCALEBASEDIR=\""$(datadir)/locale"\" \
            -DLOCAL_STATE_DIR=\""$(localstatedir)"\" \
-           -DGETTEXT_PACKAGE=\"$(PACKAGE)\" $(WARN_CFLAGS) $(LIBVIRT_FEATURES)
+           -DGETTEXT_PACKAGE=\"$(PACKAGE)\" \
+	   $(WARN_CFLAGS) \
+	   $(LIBVIRT_FEATURES)
 DEPS = libvirt.la
 LDADDS = @STATIC_BINARIES@ libvirt.la
 VIRSH_LIBS = @VIRSH_LIBS@
@@ -31,7 +38,10 @@
 		proxy_internal.c proxy_internal.h		\
 		conf.c conf.h                                   \
 		xm_internal.c xm_internal.h                     \
-		qemu_internal.c qemu_internal.h
+		../qemud/protocol.h ../qemud/protocol.c		\
+		qemu_internal.c qemu_internal.h			\
+		../qemud/remote_protocol.c ../qemud/remote_protocol.h \
+		remote_internal.c remote_internal.h
 
 bin_PROGRAMS = virsh
 
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/src/qemu_internal.c libvirt-remote/src/qemu_internal.c
--- libvirt-cvs/src/qemu_internal.c	2007-04-17 19:49:32.000000000 +0100
+++ libvirt-remote/src/qemu_internal.c	2007-04-17 17:56:27.000000000 +0100
@@ -47,6 +47,7 @@
 #include "qemu_internal.h"
 #include "xml.h"
 #include "protocol.h"
+#include "remote_protocol.h"
 
 /**
  * qemuPrivatePtr:
@@ -55,6 +56,8 @@
  */
 struct _qemuPrivate {
     int qemud_fd;               /* Connection to libvirt qemu daemon. */
+    unsigned int qemud_serial_out;
+    unsigned int qemud_serial_in;
 };
 struct _qemuNetworkPrivate {
     int qemud_fd;
@@ -79,28 +82,6 @@
                     errmsg, info, NULL, 0, 0, errmsg, info, 0);
 }
 
-static void qemuPacketError(virConnectPtr con,
-                             virDomainPtr dom,
-                             struct qemud_packet *pkt) {
-    if (!pkt) {
-        qemuError(con, dom, VIR_ERR_INTERNAL_ERROR, "Malformed data packet");
-        return;
-    }
-    if (pkt->header.type == QEMUD_PKT_FAILURE) {
-        /* Paranoia in case remote side didn't terminate it */
-        if (pkt->data.failureReply.message[0])
-            pkt->data.failureReply.message[QEMUD_MAX_ERROR_LEN-1] = '\0';
-
-        qemuError(con,
-                   dom,
-                   pkt->data.failureReply.code,
-                   pkt->data.failureReply.message[0] ?
-                   pkt->data.failureReply.message : NULL);
-    } else {
-        qemuError(con, dom, VIR_ERR_INTERNAL_ERROR, "Incorrect reply type");
-    }
-}
-
 
 /**
  * qemuFindServerPath:
@@ -262,6 +243,33 @@
     return fd;
 }
 
+static int
+qemudXdrWrite(int qemud_fd, char *buffer, int length)
+{
+    int done = 0;
+
+    while (done < length) {
+        int ret = write(qemud_fd, buffer+done, length-done);
+        if (ret <= 0)
+            return -1;
+        done += ret;
+    }
+    return done;
+}
+
+static int
+qemudXdrRead(int qemud_fd, char *buffer, int length)
+{
+    int done = 0;
+
+    while (done < length) {
+        int ret = read(qemud_fd, buffer+done, length-done);
+        if (ret <= 0)
+            return -1;
+        done += ret;
+    }
+    return done;
+}
 
 /* Takes a single request packet, does a blocking send on it.
  * then blocks until the complete reply has come back, or
@@ -270,70 +278,119 @@
 static int qemuProcessRequest(virConnectPtr conn,
                               int qemud_fd,
                               virDomainPtr dom,
-                              struct qemud_packet *req,
-                              struct qemud_packet *reply) {
-    char *out = (char *)req;
-    int outDone = 0;
-    int outLeft = sizeof(struct qemud_packet_header) + req->header.dataSize;
-    char *in = (char *)reply;
-    int inGot = 0;
-    int inLeft = sizeof(struct qemud_packet_header);
-
-    /* printf("Send request %d\n", req->header.type); */
-
-    /* Block sending entire outgoing packet */
-    while (outLeft) {
-        int got = write(qemud_fd, out+outDone, outLeft);
-        if (got < 0) {
-            return -1;
-        }
-        outDone += got;
-        outLeft -= got;
+                              qemud_packet_client *req,
+                              qemud_packet_server *reply) {
+    XDR x;
+    char buffer[REMOTE_MESSAGE_MAX];
+    qemud_packet_header h;
+    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
+
+    req->serial = ++priv->qemud_serial_out;
+
+    /* Create the buffer. */
+    xdrmem_create(&x, buffer, sizeof buffer, XDR_ENCODE);
+
+    /* Encode a dummy header first - we'll come back for the real header. */
+    if (!xdr_qemud_packet_header (&x, &h)) {
+        fprintf (stderr, "Encoding dummy header\n");
+        return -1;
     }
 
-    /* Block waiting for header to come back */
-    while (inLeft) {
-        int done = read(qemud_fd, in+inGot, inLeft);
-        if (done <= 0) {
-            return -1;
-        }
-        inGot += done;
-        inLeft -= done;
+    /* Client payload. */
+    if (!xdr_qemud_packet_client(&x, req)) {
+        fprintf(stderr, "Cannot encode client payload\n");
+        return -1;
     }
 
-    /* Validate header isn't bogus (bigger than
-       maximum defined packet size) */
-    if (reply->header.dataSize > sizeof(union qemud_packet_data)) {
-        /*
-        printf("Got type %ds body %d (max %ld)\n",
-               reply->header.type,
-               reply->header.dataSize,
-               sizeof(union qemud_packet_data));
-        printf("%ld == %ld + %ld\n",
-               sizeof(struct qemud_packet),
-               sizeof(struct qemud_packet_header),
-               sizeof(union qemud_packet_data));
-        */
-        qemuPacketError(conn, dom, NULL);
+    /* Get the total length. */
+    h.length = xdr_getpos (&x);
+    h.prog = QEMUD_PROGRAM;
+
+    /* Encode the real header at the start of the message. */
+    if (xdr_setpos (&x, 0) == 0) {
+        fprintf (stderr, "xdr_setpos\n");
         return -1;
     }
 
-    /* Now block reading in body */
-    inLeft = reply->header.dataSize;
-    while (inLeft) {
-        int done = read(qemud_fd, in+inGot, inLeft);
-        if (done <= 0) {
-            return -1;
-        }
-        inGot += done;
-        inLeft -= done;
+    if (!xdr_qemud_packet_header(&x, &h)) {
+        fprintf(stderr, "Cannot encode client header\n");
+        return -1;
+    }
+    xdr_destroy (&x);
+
+    if (qemudXdrWrite(qemud_fd, buffer, h.length) < 0) {
+        fprintf(stderr, "Cannot write client packet\n");
+        return -1;
+    }
+
+    /* Read the reply header. */
+    if (qemudXdrRead(qemud_fd, buffer, QEMUD_PKT_HEADER_XDR_LEN) < 0) {
+        fprintf(stderr, "Cannot read server header\n");
+        return -1;
+    }
+
+    xdrmem_create(&x, buffer, QEMUD_PKT_HEADER_XDR_LEN, XDR_DECODE);
+
+    if (!xdr_qemud_packet_header(&x, &h)) {
+        fprintf(stderr, "Cannot decode server header\n");
+        return -1;
+    }
+
+    if (h.prog != QEMUD_PROGRAM) {
+        fprintf(stderr, "Server header magic %d does not match %d\n",
+                h.prog, QEMUD_PROGRAM);
+        return -1;
+    }
+
+    /* Adjust h.length to the number of bytes remaining to be read. */
+    h.length -= 8;
+
+    /* NB: h.length is unsigned. */
+    if (h.length > REMOTE_MESSAGE_MAX) {
+        fprintf(stderr, "Server payload length %d is longer than max %d\n",
+                h.length, REMOTE_MESSAGE_MAX);
+        return -1;
     }
 
-    if (reply->header.type != req->header.type) {
-        qemuPacketError(conn, dom, reply);
+    /* Read and parse the remainder of the message. */
+    if (qemudXdrRead(qemud_fd, buffer, h.length) < 0) {
+        fprintf(stderr, "Cannot read server payload\n");
         return -1;
     }
 
+    xdrmem_create(&x, buffer, h.length, XDR_DECODE);
+
+    if (!xdr_qemud_packet_server(&x, reply)) {
+        fprintf(stderr, "Cannot decode server payload\n");
+        return -1;
+    }
+
+    if (reply->serial != ++priv->qemud_serial_in) {
+        fprintf(stderr, "Server serial %d did not match expected %d\n",
+                reply->serial, priv->qemud_serial_in);
+        return -1;
+    }
+    if (reply->inReplyTo != req->serial) {
+        fprintf(stderr, "Server inReplyTo %d did not match expected %d\n",
+                reply->inReplyTo, priv->qemud_serial_out);
+        return -1;
+    }
+
+    if (reply->data.type == QEMUD_SERVER_PKT_FAILURE) {
+        /* Paranoia in case remote side didn't terminate it */
+        if (reply->data.qemud_packet_server_data_u.failureReply.message[0])
+            reply->data.qemud_packet_server_data_u.failureReply.message[QEMUD_MAX_ERROR_LEN-1] = '\0';
+
+        qemuError(conn,
+                  dom,
+                  reply->data.qemud_packet_server_data_u.failureReply.code,
+                  reply->data.qemud_packet_server_data_u.failureReply.message[0] ?
+                  reply->data.qemud_packet_server_data_u.failureReply.message : NULL);
+        return -1;
+    }
+
+    /* XXX validate type is what we expect */
+
     return 0;
 }
 
@@ -408,7 +465,7 @@
     }
 
     /* Create per-connection private data. */
-    priv = conn->privateData = malloc (sizeof *priv);
+    priv = conn->privateData = calloc (1, sizeof *priv);
     if (!priv) {
         qemuError (conn, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__);
         return VIR_DRV_OPEN_ERROR;
@@ -448,41 +505,41 @@
 
 static int qemuGetVersion(virConnectPtr conn,
                           unsigned long *hvVer) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
-    req.header.type = QEMUD_PKT_GET_VERSION;
-    req.header.dataSize = 0;
+    req.data.type = QEMUD_CLIENT_PKT_GET_VERSION;
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
-    *hvVer = reply.data.getVersionReply.version;
+    *hvVer = reply.data.qemud_packet_server_data_u.getVersionReply.versionNum;
     return 0;
 }
 
 
 static int qemuNodeGetInfo(virConnectPtr conn,
                            virNodeInfoPtr info) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
-    req.header.type = QEMUD_PKT_GET_NODEINFO;
-    req.header.dataSize = 0;
+    req.data.type = QEMUD_CLIENT_PKT_GET_NODEINFO;
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
-    info->cores = reply.data.getNodeInfoReply.cores;
-    info->threads = reply.data.getNodeInfoReply.threads;
-    info->sockets = reply.data.getNodeInfoReply.sockets;
-    info->nodes = reply.data.getNodeInfoReply.nodes;
-    strncpy(info->model, reply.data.getNodeInfoReply.model, sizeof(info->model));
-    info->mhz = reply.data.getNodeInfoReply.mhz;
-    info->cpus = reply.data.getNodeInfoReply.cpus;
-    info->memory = reply.data.getNodeInfoReply.memory;
+    info->cores = reply.data.qemud_packet_server_data_u.getNodeInfoReply.cores;
+    info->threads = reply.data.qemud_packet_server_data_u.getNodeInfoReply.threads;
+    info->sockets = reply.data.qemud_packet_server_data_u.getNodeInfoReply.sockets;
+    info->nodes = reply.data.qemud_packet_server_data_u.getNodeInfoReply.nodes;
+    strncpy(info->model, reply.data.qemud_packet_server_data_u.getNodeInfoReply.model, sizeof(info->model));
+    info->mhz = reply.data.qemud_packet_server_data_u.getNodeInfoReply.mhz;
+    info->cpus = reply.data.qemud_packet_server_data_u.getNodeInfoReply.cpus;
+    info->memory = reply.data.qemud_packet_server_data_u.getNodeInfoReply.memory;
     return 0;
 }
 
@@ -490,23 +547,23 @@
 static char *
 qemuGetCapabilities (virConnectPtr conn)
 {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     char *xml;
     qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     /* Punt the request across to the daemon, because the daemon
      * has tables describing available architectures.
      */
-    req.header.type = QEMUD_PKT_GET_CAPABILITIES;
-    req.header.dataSize = 0;
+    req.data.type = QEMUD_CLIENT_PKT_GET_CAPABILITIES;
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
-    reply.data.getCapabilitiesReply.xml[QEMUD_MAX_XML_LEN-1] = '\0';
+    reply.data.qemud_packet_server_data_u.getCapabilitiesReply.xml[QEMUD_MAX_XML_LEN-1] = '\0';
 
-    xml = strdup (reply.data.getCapabilitiesReply.xml);
+    xml = strdup (reply.data.qemud_packet_server_data_u.getCapabilitiesReply.xml);
     if (!xml) {
         qemuError (conn, NULL, VIR_ERR_NO_MEMORY, NULL);
         return NULL;
@@ -516,40 +573,40 @@
 }
 
 static int qemuNumOfDomains(virConnectPtr conn) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
-    req.header.type = QEMUD_PKT_NUM_DOMAINS;
-    req.header.dataSize = 0;
+    req.data.type = QEMUD_CLIENT_PKT_NUM_DOMAINS;
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
-    return reply.data.numDomainsReply.numDomains;
+    return reply.data.qemud_packet_server_data_u.numDomainsReply.numDomains;
 }
 
 
 static int qemuListDomains(virConnectPtr conn,
                            int *ids,
                            int maxids) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     int i, nDomains;
     qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
-    req.header.type = QEMUD_PKT_LIST_DOMAINS;
-    req.header.dataSize = 0;
+    req.data.type = QEMUD_CLIENT_PKT_LIST_DOMAINS;
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
-    nDomains = reply.data.listDomainsReply.numDomains;
+    nDomains = reply.data.qemud_packet_server_data_u.listDomainsReply.numDomains;
     if (nDomains > maxids)
         nDomains = maxids;
 
     for (i = 0 ; i < nDomains ; i++) {
-        ids[i] = reply.data.listDomainsReply.domains[i];
+        ids[i] = reply.data.qemud_packet_server_data_u.listDomainsReply.domains[i];
     }
 
     return nDomains;
@@ -559,7 +616,8 @@
 static virDomainPtr
 qemuDomainCreateLinux(virConnectPtr conn, const char *xmlDesc,
                        unsigned int flags ATTRIBUTE_UNUSED) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     virDomainPtr dom;
     int len = strlen(xmlDesc);
     qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
@@ -568,46 +626,45 @@
         return NULL;
     }
 
-    req.header.type = QEMUD_PKT_DOMAIN_CREATE;
-    req.header.dataSize = sizeof(req.data.domainCreateRequest);
-    strcpy(req.data.domainCreateRequest.xml, xmlDesc);
-    req.data.domainCreateRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0';
+    req.data.type = QEMUD_CLIENT_PKT_DOMAIN_CREATE;
+    strcpy(req.data.qemud_packet_client_data_u.domainCreateRequest.xml, xmlDesc);
+    req.data.qemud_packet_client_data_u.domainCreateRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0';
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
-    reply.data.domainCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+    reply.data.qemud_packet_server_data_u.domainCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
 
     if (!(dom = virGetDomain(conn,
-                             reply.data.domainCreateReply.name,
-                             reply.data.domainCreateReply.uuid)))
+                             reply.data.qemud_packet_server_data_u.domainCreateReply.name,
+                             reply.data.qemud_packet_server_data_u.domainCreateReply.uuid)))
         return NULL;
 
-    dom->id = reply.data.domainCreateReply.id;
+    dom->id = reply.data.qemud_packet_server_data_u.domainCreateReply.id;
     return dom;
 }
 
 
 static virDomainPtr qemuLookupDomainByID(virConnectPtr conn,
                                          int id) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     virDomainPtr dom;
     qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
-    req.header.type = QEMUD_PKT_DOMAIN_LOOKUP_BY_ID;
-    req.header.dataSize = sizeof(req.data.domainLookupByIDRequest);
-    req.data.domainLookupByIDRequest.id = id;
+    req.data.type = QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_ID;
+    req.data.qemud_packet_client_data_u.domainLookupByIDRequest.id = id;
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
-    reply.data.domainLookupByIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+    reply.data.qemud_packet_server_data_u.domainLookupByIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
 
     if (!(dom = virGetDomain(conn,
-                             reply.data.domainLookupByIDReply.name,
-                             reply.data.domainLookupByIDReply.uuid)))
+                             reply.data.qemud_packet_server_data_u.domainLookupByIDReply.name,
+                             reply.data.qemud_packet_server_data_u.domainLookupByIDReply.uuid)))
         return NULL;
 
     dom->id = id;
@@ -617,42 +674,42 @@
 
 static virDomainPtr qemuLookupDomainByUUID(virConnectPtr conn,
                                            const unsigned char *uuid) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     virDomainPtr dom;
     qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
-    req.header.type = QEMUD_PKT_DOMAIN_LOOKUP_BY_UUID;
-    req.header.dataSize = sizeof(req.data.domainLookupByUUIDRequest);
-    memmove(req.data.domainLookupByUUIDRequest.uuid, uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_UUID;
+    memmove(req.data.qemud_packet_client_data_u.domainLookupByUUIDRequest.uuid, uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
-    reply.data.domainLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+    reply.data.qemud_packet_server_data_u.domainLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
 
     if (!(dom = virGetDomain(conn,
-                             reply.data.domainLookupByUUIDReply.name,
+                             reply.data.qemud_packet_server_data_u.domainLookupByUUIDReply.name,
                              uuid)))
         return NULL;
 
-    dom->id = reply.data.domainLookupByUUIDReply.id;
+    dom->id = reply.data.qemud_packet_server_data_u.domainLookupByUUIDReply.id;
     return dom;
 }
 
 
 static virDomainPtr qemuLookupDomainByName(virConnectPtr conn,
                                            const char *name) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     virDomainPtr dom;
     qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     if (strlen(name) > (QEMUD_MAX_NAME_LEN-1))
         return NULL;
 
-    req.header.type = QEMUD_PKT_DOMAIN_LOOKUP_BY_NAME;
-    req.header.dataSize = sizeof(req.data.domainLookupByNameRequest);
-    strcpy(req.data.domainLookupByNameRequest.name, name);
+    req.data.type = QEMUD_CLIENT_PKT_DOMAIN_LOOKUP_BY_NAME;
+    strcpy(req.data.qemud_packet_client_data_u.domainLookupByNameRequest.name, name);
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
@@ -660,20 +717,20 @@
 
     if (!(dom = virGetDomain(conn,
                              name,
-                             reply.data.domainLookupByNameReply.uuid)))
+                             reply.data.qemud_packet_server_data_u.domainLookupByNameReply.uuid)))
         return NULL;
 
-    dom->id = reply.data.domainLookupByNameReply.id;
+    dom->id = reply.data.qemud_packet_server_data_u.domainLookupByNameReply.id;
     return dom;
 }
 
 static int qemuDestroyDomain(virDomainPtr domain) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuPrivatePtr priv = (qemuPrivatePtr) domain->conn->privateData;
 
-    req.header.type = QEMUD_PKT_DOMAIN_DESTROY;
-    req.header.dataSize = sizeof(req.data.domainDestroyRequest);
-    req.data.domainDestroyRequest.id = domain->id;
+    req.data.type = QEMUD_CLIENT_PKT_DOMAIN_DESTROY;
+    req.data.qemud_packet_client_data_u.domainDestroyRequest.id = domain->id;
 
     if (qemuProcessRequest(domain->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
@@ -698,12 +755,12 @@
 }
 
 static int qemuResumeDomain(virDomainPtr domain) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuPrivatePtr priv = (qemuPrivatePtr) domain->conn->privateData;
 
-    req.header.type = QEMUD_PKT_DOMAIN_RESUME;
-    req.header.dataSize = sizeof(req.data.domainResumeRequest);
-    req.data.domainResumeRequest.id = domain->id;
+    req.data.type = QEMUD_CLIENT_PKT_DOMAIN_RESUME;
+    req.data.qemud_packet_client_data_u.domainResumeRequest.id = domain->id;
 
     if (qemuProcessRequest(domain->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
@@ -713,12 +770,12 @@
 }
 
 static int qemuPauseDomain(virDomainPtr domain) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuPrivatePtr priv = (qemuPrivatePtr) domain->conn->privateData;
 
-    req.header.type = QEMUD_PKT_DOMAIN_SUSPEND;
-    req.header.dataSize = sizeof(req.data.domainSuspendRequest);
-    req.data.domainSuspendRequest.id = domain->id;
+    req.data.type = QEMUD_CLIENT_PKT_DOMAIN_SUSPEND;
+    req.data.qemud_packet_client_data_u.domainSuspendRequest.id = domain->id;
 
     if (qemuProcessRequest(domain->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
@@ -729,19 +786,19 @@
 
 static int qemuGetDomainInfo(virDomainPtr domain,
                              virDomainInfoPtr info) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuPrivatePtr priv = (qemuPrivatePtr) domain->conn->privateData;
 
-    req.header.type = QEMUD_PKT_DOMAIN_GET_INFO;
-    req.header.dataSize = sizeof(req.data.domainGetInfoRequest);
-    memmove(req.data.domainGetInfoRequest.uuid, domain->uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_DOMAIN_GET_INFO;
+    memmove(req.data.qemud_packet_client_data_u.domainGetInfoRequest.uuid, domain->uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(domain->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
     memset(info, 0, sizeof(virDomainInfo));
-    switch (reply.data.domainGetInfoReply.runstate) {
+    switch (reply.data.qemud_packet_server_data_u.domainGetInfoReply.runstate) {
     case QEMUD_STATE_RUNNING:
         info->state = VIR_DOMAIN_RUNNING;
         break;
@@ -757,29 +814,29 @@
     default:
         return -1;
     }
-    info->maxMem = reply.data.domainGetInfoReply.maxmem;
-    info->memory = reply.data.domainGetInfoReply.memory;
-    info->nrVirtCpu = reply.data.domainGetInfoReply.nrVirtCpu;
-    info->cpuTime = reply.data.domainGetInfoReply.cpuTime;
+    info->maxMem = reply.data.qemud_packet_server_data_u.domainGetInfoReply.maxmem;
+    info->memory = reply.data.qemud_packet_server_data_u.domainGetInfoReply.memory;
+    info->nrVirtCpu = reply.data.qemud_packet_server_data_u.domainGetInfoReply.nrVirtCpu;
+    info->cpuTime = reply.data.qemud_packet_server_data_u.domainGetInfoReply.cpuTime;
 
     return 0;
 }
 
 static char *qemuDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuPrivatePtr priv = (qemuPrivatePtr) domain->conn->privateData;
 
-    req.header.type = QEMUD_PKT_DUMP_XML;
-    req.header.dataSize = sizeof(req.data.domainDumpXMLRequest);
-    memmove(req.data.domainDumpXMLRequest.uuid, domain->uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_DUMP_XML;
+    memmove(req.data.qemud_packet_client_data_u.domainDumpXMLRequest.uuid, domain->uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(domain->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
-    reply.data.domainDumpXMLReply.xml[QEMUD_MAX_XML_LEN-1] = '\0';
+    reply.data.qemud_packet_server_data_u.domainDumpXMLReply.xml[QEMUD_MAX_XML_LEN-1] = '\0';
 
-    return strdup(reply.data.domainDumpXMLReply.xml);
+    return strdup(reply.data.qemud_packet_server_data_u.domainDumpXMLReply.xml);
 }
 
 static int qemuSaveDomain(virDomainPtr domain ATTRIBUTE_UNUSED, const char *file ATTRIBUTE_UNUSED) {
@@ -792,64 +849,65 @@
 
 
 static int qemuNumOfDefinedDomains(virConnectPtr conn) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
-    req.header.type = QEMUD_PKT_NUM_DEFINED_DOMAINS;
-    req.header.dataSize = 0;
+    req.data.type = QEMUD_CLIENT_PKT_NUM_DEFINED_DOMAINS;
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
-    return reply.data.numDefinedDomainsReply.numDomains;
+    return reply.data.qemud_packet_server_data_u.numDefinedDomainsReply.numDomains;
 }
 
 static int qemuListDefinedDomains(virConnectPtr conn,
                                   char **const names,
                                   int maxnames){
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     int i, nDomains;
     qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
-    req.header.type = QEMUD_PKT_LIST_DEFINED_DOMAINS;
-    req.header.dataSize = 0;
+    req.data.type = QEMUD_CLIENT_PKT_LIST_DEFINED_DOMAINS;
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
-    nDomains = reply.data.listDefinedDomainsReply.numDomains;
+    nDomains = reply.data.qemud_packet_server_data_u.listDefinedDomainsReply.numDomains;
     if (nDomains > maxnames)
         nDomains = maxnames;
 
     for (i = 0 ; i < nDomains ; i++) {
-        reply.data.listDefinedDomainsReply.domains[i][QEMUD_MAX_NAME_LEN-1] = '\0';
-        names[i] = strdup(reply.data.listDefinedDomainsReply.domains[i]);
+        reply.data.qemud_packet_server_data_u.listDefinedDomainsReply.domains[((i+1)*QEMUD_MAX_NAME_LEN)-1] = '\0';
+        names[i] = strdup(&reply.data.qemud_packet_server_data_u.listDefinedDomainsReply.domains[i*QEMUD_MAX_NAME_LEN]);
     }
 
     return nDomains;
 }
 
 static int qemuDomainCreate(virDomainPtr dom) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuPrivatePtr priv = (qemuPrivatePtr) dom->conn->privateData;
 
-    req.header.type = QEMUD_PKT_DOMAIN_START;
-    req.header.dataSize = sizeof(req.data.domainStartRequest);
-    memcpy(req.data.domainStartRequest.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_DOMAIN_START;
+    memcpy(req.data.qemud_packet_client_data_u.domainStartRequest.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(dom->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
-    dom->id = reply.data.domainStartReply.id;
+    dom->id = reply.data.qemud_packet_server_data_u.domainStartReply.id;
 
     return 0;
 }
 
 static virDomainPtr qemuDomainDefineXML(virConnectPtr conn, const char *xml) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     virDomainPtr dom;
     int len = strlen(xml);
     qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
@@ -858,20 +916,19 @@
         return NULL;
     }
 
-    req.header.type = QEMUD_PKT_DOMAIN_DEFINE;
-    req.header.dataSize = sizeof(req.data.domainDefineRequest);
-    strcpy(req.data.domainDefineRequest.xml, xml);
-    req.data.domainDefineRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0';
+    req.data.type = QEMUD_CLIENT_PKT_DOMAIN_DEFINE;
+    strcpy(req.data.qemud_packet_client_data_u.domainDefineRequest.xml, xml);
+    req.data.qemud_packet_client_data_u.domainDefineRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0';
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
-    reply.data.domainDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+    reply.data.qemud_packet_server_data_u.domainDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
 
     if (!(dom = virGetDomain(conn,
-                             reply.data.domainDefineReply.name,
-                             reply.data.domainDefineReply.uuid)))
+                             reply.data.qemud_packet_server_data_u.domainDefineReply.name,
+                             reply.data.qemud_packet_server_data_u.domainDefineReply.uuid)))
         return NULL;
 
     dom->id = -1;
@@ -879,13 +936,13 @@
 }
 
 static int qemuUndefine(virDomainPtr dom) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     int ret = 0;
     qemuPrivatePtr priv = (qemuPrivatePtr) dom->conn->privateData;
 
-    req.header.type = QEMUD_PKT_DOMAIN_UNDEFINE;
-    req.header.dataSize = sizeof(req.data.domainUndefineRequest);
-    memcpy(req.data.domainUndefineRequest.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_DOMAIN_UNDEFINE;
+    memcpy(req.data.qemud_packet_client_data_u.domainUndefineRequest.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(dom->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         ret = -1;
@@ -901,31 +958,33 @@
 
 static int qemuDomainGetAutostart(virDomainPtr dom,
                                   int *autostart) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuPrivatePtr priv = (qemuPrivatePtr) dom->conn->privateData;
 
-    req.header.type = QEMUD_PKT_DOMAIN_GET_AUTOSTART;
-    req.header.dataSize = sizeof(req.data.domainGetAutostartRequest);
-    memmove(req.data.domainGetAutostartRequest.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_DOMAIN_GET_AUTOSTART;
+    memmove(req.data.qemud_packet_client_data_u.domainGetAutostartRequest.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(dom->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
-    *autostart = reply.data.domainGetAutostartReply.autostart;
+    *autostart = reply.data.qemud_packet_server_data_u.domainGetAutostartReply.autostart;
 
     return 0;
 }
 
 static int qemuDomainSetAutostart(virDomainPtr dom,
                                   int autostart) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuPrivatePtr priv = (qemuPrivatePtr) dom->conn->privateData;
 
-    req.header.type = QEMUD_PKT_DOMAIN_SET_AUTOSTART;
-    req.header.dataSize = sizeof(req.data.domainSetAutostartRequest);
-    req.data.domainSetAutostartRequest.autostart = (autostart != 0);
-    memmove(req.data.domainSetAutostartRequest.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_DOMAIN_SET_AUTOSTART;
+    req.data.qemud_packet_client_data_u.domainSetAutostartRequest.autostart = (
+autostart != 0);
+    memmove(req.data.qemud_packet_client_data_u.domainSetAutostartRequest.uuid,
+ dom->uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(dom->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
@@ -984,80 +1043,80 @@
 }
 
 static int qemuNumOfNetworks(virConnectPtr conn) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
-    req.header.type = QEMUD_PKT_NUM_NETWORKS;
-    req.header.dataSize = 0;
+    req.data.type = QEMUD_CLIENT_PKT_NUM_NETWORKS;
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
-    return reply.data.numNetworksReply.numNetworks;
+    return reply.data.qemud_packet_server_data_u.numNetworksReply.numNetworks;
 }
 
 static int qemuListNetworks(virConnectPtr conn,
                             char **const names,
                             int maxnames) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     int i, nNetworks;
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
-    req.header.type = QEMUD_PKT_LIST_NETWORKS;
-    req.header.dataSize = 0;
+    req.data.type = QEMUD_CLIENT_PKT_LIST_NETWORKS;
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
-    nNetworks = reply.data.listNetworksReply.numNetworks;
+    nNetworks = reply.data.qemud_packet_server_data_u.listNetworksReply.numNetworks;
     if (nNetworks > maxnames)
         return -1;
 
     for (i = 0 ; i < nNetworks ; i++) {
-        reply.data.listNetworksReply.networks[i][QEMUD_MAX_NAME_LEN-1] = '\0';
-        names[i] = strdup(reply.data.listNetworksReply.networks[i]);
+        reply.data.qemud_packet_server_data_u.listNetworksReply.networks[((i+1)*QEMUD_MAX_NAME_LEN)-1] = '\0';
+        names[i] = strdup(&reply.data.qemud_packet_server_data_u.listNetworksReply.networks[i*QEMUD_MAX_NAME_LEN]);
     }
 
     return nNetworks;
 }
 
 static int qemuNumOfDefinedNetworks(virConnectPtr conn) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
-    req.header.type = QEMUD_PKT_NUM_DEFINED_NETWORKS;
-    req.header.dataSize = 0;
+    req.data.type = QEMUD_CLIENT_PKT_NUM_DEFINED_NETWORKS;
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
-    return reply.data.numDefinedNetworksReply.numNetworks;
+    return reply.data.qemud_packet_server_data_u.numDefinedNetworksReply.numNetworks;
 }
 
 static int qemuListDefinedNetworks(virConnectPtr conn,
                                    char **const names,
                                    int maxnames) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     int i, nNetworks;
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
-    req.header.type = QEMUD_PKT_LIST_DEFINED_NETWORKS;
-    req.header.dataSize = 0;
+    req.data.type = QEMUD_CLIENT_PKT_LIST_DEFINED_NETWORKS;
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
-    nNetworks = reply.data.listDefinedNetworksReply.numNetworks;
+    nNetworks = reply.data.qemud_packet_server_data_u.listDefinedNetworksReply.numNetworks;
     if (nNetworks > maxnames)
         return -1;
 
     for (i = 0 ; i < nNetworks ; i++) {
-        reply.data.listDefinedNetworksReply.networks[i][QEMUD_MAX_NAME_LEN-1] = '\0';
-        names[i] = strdup(reply.data.listDefinedNetworksReply.networks[i]);
+        reply.data.qemud_packet_server_data_u.listDefinedNetworksReply.networks[((i+1)*QEMUD_MAX_NAME_LEN)-1] = '\0';
+        names[i] = strdup(&reply.data.qemud_packet_server_data_u.listDefinedNetworksReply.networks[i*QEMUD_MAX_NAME_LEN]);
     }
 
     return nNetworks;
@@ -1065,22 +1124,22 @@
 
 static virNetworkPtr qemuNetworkLookupByUUID(virConnectPtr conn,
                                              const unsigned char *uuid) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     virNetworkPtr network;
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
-    req.header.type = QEMUD_PKT_NETWORK_LOOKUP_BY_UUID;
-    req.header.dataSize = sizeof(req.data.networkLookupByUUIDRequest);
-    memmove(req.data.networkLookupByUUIDRequest.uuid, uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_NETWORK_LOOKUP_BY_UUID;
+    memmove(req.data.qemud_packet_client_data_u.networkLookupByUUIDRequest.uuid, uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
-    reply.data.networkLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+    reply.data.qemud_packet_server_data_u.networkLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
 
     if (!(network = virGetNetwork(conn,
-                                  reply.data.networkLookupByUUIDReply.name,
+                                  reply.data.qemud_packet_server_data_u.networkLookupByUUIDReply.name,
                                   uuid)))
         return NULL;
 
@@ -1089,16 +1148,16 @@
 
 static virNetworkPtr qemuNetworkLookupByName(virConnectPtr conn,
                                              const char *name) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     virNetworkPtr network;
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
     if (strlen(name) > (QEMUD_MAX_NAME_LEN-1))
         return NULL;
 
-    req.header.type = QEMUD_PKT_NETWORK_LOOKUP_BY_NAME;
-    req.header.dataSize = sizeof(req.data.networkLookupByNameRequest);
-    strcpy(req.data.networkLookupByNameRequest.name, name);
+    req.data.type = QEMUD_CLIENT_PKT_NETWORK_LOOKUP_BY_NAME;
+    strcpy(req.data.qemud_packet_client_data_u.networkLookupByNameRequest.name, name);
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
@@ -1106,7 +1165,7 @@
 
     if (!(network = virGetNetwork(conn,
                                   name,
-                                  reply.data.networkLookupByNameReply.uuid)))
+                                  reply.data.qemud_packet_server_data_u.networkLookupByNameReply.uuid)))
         return NULL;
 
     return network;
@@ -1114,7 +1173,8 @@
 
 static virNetworkPtr qemuNetworkCreateXML(virConnectPtr conn,
                                           const char *xmlDesc) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     virNetworkPtr network;
     int len = strlen(xmlDesc);
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
@@ -1123,20 +1183,19 @@
         return NULL;
     }
 
-    req.header.type = QEMUD_PKT_NETWORK_CREATE;
-    req.header.dataSize = sizeof(req.data.networkCreateRequest);
-    strcpy(req.data.networkCreateRequest.xml, xmlDesc);
-    req.data.networkCreateRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0';
+    req.data.type = QEMUD_CLIENT_PKT_NETWORK_CREATE;
+    strcpy(req.data.qemud_packet_client_data_u.networkCreateRequest.xml, xmlDesc);
+    req.data.qemud_packet_client_data_u.networkCreateRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0';
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
-    reply.data.networkCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+    reply.data.qemud_packet_server_data_u.networkCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
 
     if (!(network = virGetNetwork(conn,
-                                  reply.data.networkCreateReply.name,
-                                  reply.data.networkCreateReply.uuid)))
+                                  reply.data.qemud_packet_server_data_u.networkCreateReply.name,
+                                  reply.data.qemud_packet_server_data_u.networkCreateReply.uuid)))
         return NULL;
 
     return network;
@@ -1145,7 +1204,8 @@
 
 static virNetworkPtr qemuNetworkDefineXML(virConnectPtr conn,
                                           const char *xml) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     virNetworkPtr network;
     int len = strlen(xml);
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
@@ -1154,33 +1214,32 @@
         return NULL;
     }
 
-    req.header.type = QEMUD_PKT_NETWORK_DEFINE;
-    req.header.dataSize = sizeof(req.data.networkDefineRequest);
-    strcpy(req.data.networkDefineRequest.xml, xml);
-    req.data.networkDefineRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0';
+    req.data.type = QEMUD_CLIENT_PKT_NETWORK_DEFINE;
+    strcpy(req.data.qemud_packet_client_data_u.networkDefineRequest.xml, xml);
+    req.data.qemud_packet_client_data_u.networkDefineRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0';
 
     if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
-    reply.data.networkDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
+    reply.data.qemud_packet_server_data_u.networkDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
 
     if (!(network = virGetNetwork(conn,
-                                  reply.data.networkDefineReply.name,
-                                  reply.data.networkDefineReply.uuid)))
+                                  reply.data.qemud_packet_server_data_u.networkDefineReply.name,
+                                  reply.data.qemud_packet_server_data_u.networkDefineReply.uuid)))
         return NULL;
 
     return network;
 }
 
 static int qemuNetworkUndefine(virNetworkPtr network) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     int ret = 0;
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
-    req.header.type = QEMUD_PKT_NETWORK_UNDEFINE;
-    req.header.dataSize = sizeof(req.data.networkUndefineRequest);
-    memcpy(req.data.networkUndefineRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_NETWORK_UNDEFINE;
+    memcpy(req.data.qemud_packet_client_data_u.networkUndefineRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         ret = -1;
@@ -1195,12 +1254,12 @@
 }
 
 static int qemuNetworkCreate(virNetworkPtr network) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
-    req.header.type = QEMUD_PKT_NETWORK_START;
-    req.header.dataSize = sizeof(req.data.networkStartRequest);
-    memcpy(req.data.networkStartRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_NETWORK_START;
+    memcpy(req.data.qemud_packet_client_data_u.networkStartRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
@@ -1210,12 +1269,12 @@
 }
 
 static int qemuNetworkDestroy(virNetworkPtr network) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
-    req.header.type = QEMUD_PKT_NETWORK_DESTROY;
-    req.header.dataSize = sizeof(req.data.networkDestroyRequest);
-    memcpy(req.data.networkDestroyRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_NETWORK_DESTROY;
+    memcpy(req.data.qemud_packet_client_data_u.networkDestroyRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
@@ -1225,66 +1284,66 @@
 }
 
 static char * qemuNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
-    req.header.type = QEMUD_PKT_NETWORK_DUMP_XML;
-    req.header.dataSize = sizeof(req.data.networkDumpXMLRequest);
-    memmove(req.data.networkDumpXMLRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_NETWORK_DUMP_XML;
+    memmove(req.data.qemud_packet_client_data_u.networkDumpXMLRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
-    reply.data.networkDumpXMLReply.xml[QEMUD_MAX_XML_LEN-1] = '\0';
-
-    return strdup(reply.data.networkDumpXMLReply.xml);
+    reply.data.qemud_packet_server_data_u.networkDumpXMLReply.xml[QEMUD_MAX_XML_LEN-1] = '\0';
+ 
+    return strdup(reply.data.qemud_packet_server_data_u.networkDumpXMLReply.xml);
 }
 
 static char * qemuNetworkGetBridgeName(virNetworkPtr network) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
-    req.header.type = QEMUD_PKT_NETWORK_GET_BRIDGE_NAME;
-    req.header.dataSize = sizeof(req.data.networkGetBridgeNameRequest);
-    memmove(req.data.networkGetBridgeNameRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_NETWORK_GET_BRIDGE_NAME;
+    memmove(req.data.qemud_packet_client_data_u.networkGetBridgeNameRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
-    reply.data.networkGetBridgeNameReply.ifname[QEMUD_MAX_IFNAME_LEN-1] = '\0';
-
-    return strdup(reply.data.networkGetBridgeNameReply.ifname);
+    reply.data.qemud_packet_server_data_u.networkGetBridgeNameReply.ifname[QEMUD_MAX_IFNAME_LEN-1] = '\0';
+ 
+    return strdup(reply.data.qemud_packet_server_data_u.networkGetBridgeNameReply.ifname);
 }
 
 static int qemuNetworkGetAutostart(virNetworkPtr network,
                                    int *autostart) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
-    req.header.type = QEMUD_PKT_NETWORK_GET_AUTOSTART;
-    req.header.dataSize = sizeof(req.data.networkGetAutostartRequest);
-    memmove(req.data.networkGetAutostartRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_NETWORK_GET_AUTOSTART;
+    memmove(req.data.qemud_packet_client_data_u.networkGetAutostartRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
-    *autostart = reply.data.networkGetAutostartReply.autostart;
+    *autostart = reply.data.qemud_packet_server_data_u.networkGetAutostartReply.autostart;
 
     return 0;
 }
 
 static int qemuNetworkSetAutostart(virNetworkPtr network,
                                    int autostart) {
-    struct qemud_packet req, reply;
+    qemud_packet_client req;
+    qemud_packet_server reply;
     qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
-    req.header.type = QEMUD_PKT_NETWORK_SET_AUTOSTART;
-    req.header.dataSize = sizeof(req.data.networkSetAutostartRequest);
-    req.data.networkSetAutostartRequest.autostart = (autostart != 0);
-    memmove(req.data.networkSetAutostartRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
+    req.data.type = QEMUD_CLIENT_PKT_NETWORK_SET_AUTOSTART;
+    req.data.qemud_packet_client_data_u.networkSetAutostartRequest.autostart = (autostart != 0);
+    memmove(req.data.qemud_packet_client_data_u.networkSetAutostartRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
     if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/src/remote_internal.c libvirt-remote/src/remote_internal.c
--- libvirt-cvs/src/remote_internal.c	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-remote/src/remote_internal.c	2007-04-26 11:17:47.000000000 +0100
@@ -0,0 +1,1298 @@
+/*
+ * remote_internal.c: driver to provide access to libvirtd running
+ *   on a remote machine
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Richard Jones <rjones@xxxxxxxxxx>
+ */
+
+#define _GNU_SOURCE /* for asprintf */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#include <rpc/xdr.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <libxml/uri.h>
+
+#include "internal.h"
+#include "driver.h"
+#include "remote_internal.h"
+#include "remote_protocol.h"
+
+#define DEBUG 1                 /* Enable verbose messages on stderr. */
+
+/* Per-connection private data. */
+#define MAGIC 999               /* private_data->magic if OK */
+#define DEAD 998                /* private_data->magic if dead/closed */
+
+struct private_data {
+    int magic;                  /* Should be MAGIC or DEAD. */
+    int sock;                   /* Socket. */
+    int uses_tls;               /* TLS enabled on socket? */
+    gnutls_session_t session;   /* GnuTLS session (if uses_tls != 0). */
+};
+
+#define GET_PRIVATE(conn,retcode)                                       \
+    struct private_data *priv = (struct private_data *) (conn)->privateData; \
+    assert (priv);                                                      \
+    if (priv->magic == DEAD) {                                          \
+        error (conn, VIR_ERR_INVALID_ARG,                               \
+               "tried to use a closed or uninitialised handle");        \
+        return (retcode);                                               \
+    }                                                                   \
+    assert (priv->magic == MAGIC)
+
+static int call (virConnectPtr conn, struct private_data *priv, int proc_nr, xdrproc_t args_filter, char *args, xdrproc_t ret_filter, char *ret);
+static void error (virConnectPtr conn, virErrorNumber code, const char *info);
+static void server_error (virConnectPtr conn, remote_error *err);
+static virDomainPtr get_domain_from_name (virConnectPtr conn, remote_domain domain);
+static virNetworkPtr get_network_from_name (virConnectPtr conn, remote_network network);
+
+/*----------------------------------------------------------------------*/
+
+/* Helper functions. */
+static char *get_transport_from_scheme (char *scheme);
+
+/* Parse query string. */
+struct query_fields {
+    struct query_fields *next;	/* Linked list chain. */
+    char *name;			/* Field name (unescaped). */
+    char *value;		/* Field value (unescaped). */
+    int ignore;			/* Ignore field in query_create. */
+};
+
+static int query_parse (const char *query,
+                        const char *separator,
+                        struct query_fields **fields_out);
+static int query_create (const struct query_fields *fields,
+                         const char *separator,
+                         char **query_out);
+static void query_free (struct query_fields *fields);
+
+/* Supported transports. */
+enum transport {
+    trans_tls,
+    trans_unix,
+    trans_ssh,
+    trans_ext,
+    trans_tcp,
+};
+
+/* GnuTLS functions used by remoteOpen. */
+static int initialise_gnutls (virConnectPtr conn);
+static gnutls_session_t negotiate_gnutls_on_connection (virConnectPtr conn, int sock, int no_verify, const char *hostname);
+
+static int
+remoteOpen (virConnectPtr conn, const char *uri_str, int flags)
+{
+    if (!uri_str) return VIR_DRV_OPEN_DECLINED;
+
+    /* We have to parse the URL every time to discover whether
+     * it contains a transport or remote server name.  There's no
+     * way to get around this.
+     */
+    xmlURIPtr uri = xmlParseURI (uri_str);
+    if (!uri || !uri->scheme)
+        return VIR_DRV_OPEN_DECLINED; /* Decline - not a URL. */
+
+    char *transport_str = get_transport_from_scheme (uri->scheme);
+    if (!uri->server && !transport_str)
+        return VIR_DRV_OPEN_DECLINED; /* Decline - not a remote URL. */
+
+    /* What transport? */
+    enum transport transport;
+    if (!transport_str || strcasecmp (transport_str, "tls") == 0)
+        transport = trans_tls;
+    else if (strcasecmp (transport_str, "unix") == 0)
+        transport = trans_unix;
+    else if (strcasecmp (transport_str, "ssh") == 0)
+        transport = trans_ssh;
+    else if (strcasecmp (transport_str, "ext") == 0)
+        transport = trans_ext;
+    else if (strcasecmp (transport_str, "tcp") == 0)
+        transport = trans_tcp;
+    else {
+        error (conn, VIR_ERR_INVALID_ARG,
+               "remote_open: transport in URL not recognised "
+               "(should be tls|unix|ssh|ext|tcp)");
+        return VIR_DRV_OPEN_ERROR;
+    }
+
+    /* Return code from this function, and the private data. */
+    int retcode = VIR_DRV_OPEN_ERROR;
+    struct private_data priv = { .magic = DEAD, .sock = -1 };
+    char *name = 0, *command = 0, *sockname = 0, *netcat = 0, *username = 0;
+    char *server, *port;
+    int no_verify = 0;
+    char **cmd_argv = 0;
+
+    /* Remote server defaults to "localhost" if not specified. */
+    server = strdup (uri->server ? uri->server : "localhost");
+    if (!server) {
+    out_of_memory:
+        error (conn, VIR_ERR_NO_MEMORY, "remote_open");
+        goto failed;
+    }
+    if (uri->port != 0) {
+        if (asprintf (&port, "%d", uri->port) == -1) goto out_of_memory;
+    } else if (transport == trans_tls) {
+        port = strdup (LIBVIRTD_TLS_PORT);
+        if (!port) goto out_of_memory;
+    } else if (transport == trans_tcp) {
+        port = strdup (LIBVIRTD_TCP_PORT);
+        if (!port) goto out_of_memory;
+    } else if (transport == trans_ssh) {
+        port = strdup ("22");
+        if (!port) goto out_of_memory;
+        if (uri->user) {
+            username = strdup (uri->user);
+            if (!username) goto out_of_memory;
+        }
+    } else
+        port = NULL;           /* Port not used for unix, ext. */
+
+    /* Get the variables from the query string.
+     * Then we need to reconstruct the query string (because
+     * feasibly it might contain variables needed by the real driver,
+     * although that won't be the case for now).
+     */
+    struct query_fields *vars, *var;
+    char *query;
+#if HAVE_XMLURI_QUERY_RAW
+    query = uri->query_raw;
+#else
+    query = uri->query;
+#endif
+    if (query_parse (query, NULL, &vars) != 0) goto failed;
+
+    for (var = vars; var; var = var->next) {
+        if (strcasecmp (var->name, "name") == 0) {
+            name = strdup (var->value);
+            if (!name) goto out_of_memory;
+            var->ignore = 1;
+        } else if (strcasecmp (var->name, "command") == 0) {
+            command = strdup (var->value);
+            if (!command) goto out_of_memory;
+            var->ignore = 1;
+        } else if (strcasecmp (var->name, "socket") == 0) {
+            sockname = strdup (var->value);
+            if (!sockname) goto out_of_memory;
+            var->ignore = 1;
+        } else if (strcasecmp (var->name, "netcat") == 0) {
+            netcat = strdup (var->value);
+            if (!netcat) goto out_of_memory;
+            var->ignore = 1;
+        } else if (strcasecmp (var->name, "no_verify") == 0) {
+            no_verify = atoi (var->value);
+            var->ignore = 1;
+        }
+#if DEBUG
+        else
+            fprintf (stderr,
+                     "remoteOpen: "
+                     "passing through variable '%s' to remote end\n",
+                     var->name);
+#endif
+    }
+
+#if HAVE_XMLURI_QUERY_RAW
+    if (uri->query_raw) xmlFree (uri->query_raw);
+#else
+    if (uri->query) xmlFree (uri->query);
+#endif
+
+    if (query_create (vars, NULL,
+#if HAVE_XMLURI_QUERY_RAW
+                      &uri->query_raw
+#else
+                      &uri->query
+#endif
+                      ) != 0) goto failed;
+    query_free (vars);
+
+    /* For ext transport, command is required. */
+    if (transport == trans_ext && !command) {
+        error (conn, VIR_ERR_INVALID_ARG, "remote_open: for 'ext' transport, command is required");
+        goto failed;
+    }
+
+    /* Construct the original name. */
+    if (!name) {
+        /* Remove the transport (if any) from the scheme. */
+        if (transport_str) {
+            assert (transport_str[-1] == '+');
+            transport_str[-1] = '\0';
+        }
+        /* Remove the username, server name and port number. */
+        if (uri->user) xmlFree (uri->user);
+        uri->user = 0;
+
+        if (uri->server) xmlFree (uri->server);
+        uri->server = 0;
+
+        uri->port = 0;
+
+        name = (char *) xmlSaveUri (uri);
+    }
+
+    assert (name);
+#if DEBUG
+    fprintf (stderr, "remoteOpen: proceeding with name = %s\n", name);
+#endif
+
+    /* Connect to the remote service. */
+    switch (transport) {
+    case trans_tls:
+        if (initialise_gnutls (conn) == -1) goto failed;
+        priv.uses_tls = 1;
+
+        /*FALLTHROUGH*/
+    case trans_tcp: {
+        // http://people.redhat.com/drepper/userapi-ipv6.html
+        struct addrinfo *res, *r;
+        struct addrinfo hints;
+        memset (&hints, 0, sizeof hints);
+        hints.ai_socktype = SOCK_STREAM;
+        hints.ai_flags = AI_ADDRCONFIG;
+        int e = getaddrinfo (server, port, &hints, &res);
+        if (e != 0) {
+            error (conn, VIR_ERR_INVALID_ARG, gai_strerror (e));
+            goto failed;
+        }
+
+        /* Try to connect to each returned address in turn. */
+        /* XXX This loop contains a subtle problem.  In the case
+         * where a host is accessible over IPv4 and IPv6, it will
+         * try the IPv4 and IPv6 addresses in turn.  However it
+         * should be able to present different client certificates
+         * (because the commonName field in a client cert contains
+         * the client IP address, which is different for IPv4 and
+         * IPv6).  At the moment we only have a single client
+         * certificate, and no way to specify what address family
+         * that certificate belongs to.
+         */
+        for (r = res; r; r = r->ai_next) {
+            priv.sock = socket (r->ai_family, SOCK_STREAM, 0);
+            if (priv.sock == -1) {
+                error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+                continue;
+            }
+            if (connect (priv.sock, r->ai_addr, r->ai_addrlen) == -1) {
+                error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+                close (priv.sock);
+                continue;
+            }
+            if (priv.uses_tls) {
+                priv.session =
+                    negotiate_gnutls_on_connection
+                      (conn, priv.sock, no_verify, server);
+                if (!priv.session) {
+                    close (priv.sock);
+                    priv.sock = -1;
+                    continue;
+                }
+                goto tcp_connected;
+            }
+        }
+
+        freeaddrinfo (res);
+        goto failed;
+
+       tcp_connected:
+        freeaddrinfo (res);
+
+        // NB. All versioning is done by the RPC headers, so we don't
+        // need to worry (at this point anyway) about versioning.
+        break;
+    }
+
+    case trans_unix: {
+        if (!sockname) {
+            if (flags & VIR_CONNECT_RO)
+                sockname = strdup (LIBVIRTD_UNIX_SOCKET_RO);
+            else
+                sockname = strdup (LIBVIRTD_UNIX_SOCKET);
+        }
+
+#ifndef UNIX_PATH_MAX
+#define UNIX_PATH_MAX(addr) (sizeof (addr).sun_path)
+#endif
+        struct sockaddr_un addr;
+        memset (&addr, 0, sizeof addr);
+        addr.sun_family = AF_UNIX;
+        strncpy (addr.sun_path, sockname, UNIX_PATH_MAX (addr));
+
+        priv.sock = socket (AF_UNIX, SOCK_STREAM, 0);
+        if (priv.sock == -1) {
+            error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+            goto failed;
+        }
+        if (connect (priv.sock, (struct sockaddr *) &addr, sizeof addr) == -1){
+            error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+            goto failed;
+        }
+
+        break;
+    }
+
+    case trans_ssh: {
+        int j, nr_args = username ? 10 : 8;
+
+        command = command ? : strdup ("ssh");
+
+        // Generate the final command argv[] array.
+        //   ssh -p $port [-l $username] $hostname $netcat -U $sockname [NULL]
+        cmd_argv = malloc (nr_args * sizeof (char *));
+        j = 0;
+        cmd_argv[j++] = strdup (command);
+        cmd_argv[j++] = strdup ("-p");
+        cmd_argv[j++] = strdup (port);
+        if (username) {
+            cmd_argv[j++] = strdup ("-l");
+            cmd_argv[j++] = strdup (username);
+        }
+        cmd_argv[j++] = strdup (server);
+        cmd_argv[j++] = strdup (netcat ? netcat : "nc");
+        cmd_argv[j++] = strdup ("-U");
+        cmd_argv[j++] = strdup (sockname ? sockname : LIBVIRTD_UNIX_SOCKET);
+        cmd_argv[j++] = 0;
+        assert (j == nr_args);
+    }
+
+        /*FALLTHROUGH*/
+    case trans_ext: {
+        int pid;
+        int sv[2];
+
+        /* Fork off the external process.  Use socketpair to create a private
+         * (unnamed) Unix domain socket to the child process so we don't have
+         * to faff around with two file descriptors (a la 'pipe(2)').
+         */
+        if (socketpair (PF_UNIX, SOCK_STREAM, 0, sv) == -1) {
+            error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+            goto failed;
+        }
+
+        pid = fork ();
+        if (pid == -1) {
+            error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+            goto failed;
+        } else if (pid == 0) { /* Child. */
+            close (sv[0]);
+            // Connect socket (sv[1]) to stdin/stdout.
+            close (0);
+            if (dup (sv[1]) == -1) perror ("dup");
+            close (1);
+            if (dup (sv[1]) == -1) perror ("dup");
+            close (sv[1]);
+
+            // Run the external process.
+            if (!cmd_argv) {
+                cmd_argv = malloc (2 * sizeof (char *));
+                cmd_argv[0] = command;
+                cmd_argv[1] = 0;
+            }
+            execvp (command, cmd_argv);
+            perror (command);
+            _exit (1);
+        }
+
+        /* Parent continues here. */
+        close (sv[1]);
+        priv.sock = sv[0];
+    }
+    } /* switch (transport) */
+
+    /* Finally we can call the remote side's open function. */
+    remote_open_args args = { &name, flags };
+
+    if (call (conn, &priv, REMOTE_PROC_OPEN,
+              (xdrproc_t) xdr_remote_open_args, (char *) &args,
+              (xdrproc_t) xdr_void, (char *) NULL) == -1)
+        goto failed;
+
+    /* Finally allocate private data. */
+    conn->privateData = malloc (sizeof priv);
+    if (!conn->privateData) {
+        error (conn, VIR_ERR_NO_MEMORY, "malloc");
+        goto failed;
+    }
+    priv.magic = MAGIC;
+    memcpy (conn->privateData, &priv, sizeof priv);
+
+    /* Successful. */
+    retcode = VIR_DRV_OPEN_SUCCESS;
+
+    /*FALLTHROUGH*/
+ failed:
+    /* Close the socket if we failed. */
+    if (retcode != VIR_DRV_OPEN_SUCCESS && priv.sock >= 0) {
+        close (priv.sock);
+    }
+
+    /* Free up the URL and strings. */
+    xmlFreeURI (uri);
+    if (name) free (name);
+    if (command) free (command);
+    if (sockname) free (sockname);
+    if (netcat) free (netcat);
+    if (username) free (username);
+    if (server) free (server);
+    if (port) free (port);
+    if (cmd_argv) {
+        char **cmd_argv_ptr = cmd_argv;
+        while (*cmd_argv_ptr) {
+            free (*cmd_argv_ptr);
+            cmd_argv_ptr++;
+        }
+        free (cmd_argv);
+    }
+
+    return retcode;
+}
+
+/* In a string "driver+transport" return a pointer to "transport". */
+static char *
+get_transport_from_scheme (char *scheme)
+{
+    char *p = strchr (scheme, '+');
+    return p ? p+1 : 0;
+}
+
+static int
+query_create (const struct query_fields *fields,
+              const char *separator,
+              char **query_out)
+{
+    /* List of characters which are safe inside names or values,
+     * apart from '@', IS_MARK and IS_ALPHANUM.  Best to escape
+     * as much as possible.  Certainly '=', '&' and '#' must NEVER
+     * be added to this list.
+     */
+    static const xmlChar *special_chars = BAD_CAST "";
+
+    int append_sep = 0, sep_len;
+    xmlBufferPtr buf;
+    xmlChar *str;
+    int rv;
+
+    if (query_out) *query_out = NULL;
+    if (!fields) return 0;
+
+    if (separator == NULL) {
+	separator = "&";
+	sep_len = 1;
+    } else
+	sep_len = xmlStrlen (BAD_CAST separator);
+
+    buf = xmlBufferCreate ();
+    if (!buf) return -1;
+
+    rv = 0;
+    while (fields) {
+	if (!fields->ignore) {
+	    if (append_sep) {
+		rv = xmlBufferAdd (buf, BAD_CAST separator, sep_len);
+		if (rv != 0) goto error;
+	    }
+	    append_sep = 1;
+
+	    str = xmlURIEscapeStr (BAD_CAST fields->name, special_chars);
+	    if (!str) { rv = XML_ERR_NO_MEMORY; goto error; }
+	    rv = xmlBufferAdd (buf, str, xmlStrlen (str));
+	    xmlFree (str);
+	    if (rv != 0) goto error;
+
+	    rv = xmlBufferAdd (buf, BAD_CAST "=", 1);
+	    if (rv != 0) goto error;
+	    str = xmlURIEscapeStr (BAD_CAST fields->value, special_chars);
+	    if (!str) { rv = XML_ERR_NO_MEMORY; goto error; }
+	    rv = xmlBufferAdd (buf, str, xmlStrlen (str));
+	    xmlFree (str);
+	    if (rv != 0) goto error;
+	}
+
+	fields = fields->next;
+    }
+
+    if (query_out && buf->content) {
+	*query_out = (char *) xmlStrdup (buf->content);
+	if (!*query_out) {
+	    rv = XML_ERR_NO_MEMORY;
+	    goto error;
+	}
+    }
+
+ error:
+    if (buf)
+	xmlBufferFree (buf);
+    return rv;
+}
+
+static int
+query_parse (const char *query_,
+             const char *separator,
+             struct query_fields **fields_out)
+{
+    struct query_fields *fields, *field, **prev;
+    int sep_len;
+    const xmlChar *query = BAD_CAST query_, *end, *eq;
+    char *name, *value;
+
+    if (fields_out) *fields_out = NULL;
+    if (!query || query[0] == '\0') return 0;
+
+    if (separator == NULL) {
+	separator = "&";
+	sep_len = 1;
+    } else
+	sep_len = xmlStrlen (BAD_CAST separator);
+
+    fields = NULL;
+    prev = &fields;
+
+    while (*query) {
+	/* Find the next separator, or end of the string. */
+	end = xmlStrstr (query, BAD_CAST separator);
+	if (!end) end = query + xmlStrlen (query);
+
+	/* Find the first '=' character between here and end. */
+	eq = xmlStrchr (query, '=');
+	if (eq && eq >= end) eq = NULL;
+
+	/* Empty section (eg. "?&"). */
+	if (end == query)
+	    goto next;
+	/* If there is no '=' character, then we have just "name"
+	 * and consistent with CGI.pm we assume value is "".
+	 */
+	else if (!eq) {
+	    name = xmlURIUnescapeString ((const char *) query,
+					 end - query, NULL);
+	    value = (char *) xmlStrdup (BAD_CAST "");
+	    if (!name || !value) goto out_of_memory;
+	}
+	/* Or if we have "name=" here (works around annoying
+	 * problem when calling xmlURIUnescapeString with len = 0).
+	 */
+	else if (eq+1 == end) {
+	    name = xmlURIUnescapeString ((const char *) query,
+					 eq - query, NULL);
+	    value = (char *) xmlStrdup (BAD_CAST "");
+	    if (!name || !value) goto out_of_memory;
+	}
+	/* If the '=' character is at the beginning then we have
+	 * "=value" and consistent with CGI.pm we _ignore_ this.
+	 */
+	else if (query == eq)
+	    goto next;
+	/* Otherwise it's "name=value". */
+	else {
+	    name = xmlURIUnescapeString ((const char *) query,
+					 eq - query, NULL);
+	    value = xmlURIUnescapeString ((const char *) eq+1,
+					  end - (eq+1), NULL);
+	    if (!name || !value) goto out_of_memory;
+	}
+
+	/* Allocate this field and append to the list. */
+	field = xmlMalloc (sizeof *field);
+	if (!field) goto out_of_memory;
+	field->next = NULL;
+	field->name = name;
+	field->value = value;
+	field->ignore = 0;
+	*prev = field;
+	prev = &field->next;
+
+    next:
+	query = end;
+	if (*query) query += sep_len; /* skip separator */
+    }
+
+    if (fields_out) *fields_out = fields;
+    return 0;
+
+ out_of_memory:
+    query_free (fields);
+    return XML_ERR_NO_MEMORY;
+}
+
+static void
+query_free (struct query_fields *fields)
+{
+    struct query_fields *t;
+
+    while (fields) {
+        if (fields->name) xmlFree (fields->name);
+        if (fields->value) xmlFree (fields->value);
+        t = fields;
+        fields = fields->next;
+        xmlFree (t);
+    }
+}
+
+/* GnuTLS functions used by remoteOpen. */
+#define CAFILE "demoCA/cacert.pem" /* XXX */
+#define KEY_FILE "127001key.pem" /* XXX */
+#define CERT_FILE "127001cert.pem" /* XXX */
+
+static gnutls_certificate_credentials_t x509_cred;
+
+static int
+initialise_gnutls (virConnectPtr conn)
+{
+    static int initialised = 0;
+    int err;
+
+    if (initialised) return 0;
+
+    gnutls_global_init ();
+
+    /* X509 stuff */
+    err = gnutls_certificate_allocate_credentials (&x509_cred);
+    if (err) {
+        error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err));
+        return -1;
+    }
+
+    /* Set the trusted CA cert. */
+#if DEBUG
+    fprintf (stderr, "loading CA file %s\n", CAFILE);
+#endif
+    err =
+        gnutls_certificate_set_x509_trust_file (x509_cred, CAFILE,
+                                                GNUTLS_X509_FMT_PEM);
+    if (err < 0) {
+        error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err));
+        return -1;
+    }
+
+    /* Set the client certificate and private key. */
+#if DEBUG
+    fprintf (stderr, "loading client cert and key from files %s and %s\n",
+             CERT_FILE, KEY_FILE);
+#endif
+    err =
+        gnutls_certificate_set_x509_key_file (x509_cred,
+                                              CERT_FILE, KEY_FILE,
+                                              GNUTLS_X509_FMT_PEM);
+    if (err < 0) {
+        error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err));
+        return -1;
+    }
+
+    initialised = 1;
+    return 0;
+}
+
+static int verify_certificate (virConnectPtr conn, gnutls_session_t session, const char *hostname);
+
+static gnutls_session_t
+negotiate_gnutls_on_connection (virConnectPtr conn,
+                                int sock, int no_verify, const char *hostname)
+{
+    const int cert_type_priority[3] = {
+        GNUTLS_CRT_X509,
+        GNUTLS_CRT_OPENPGP,
+        0
+    };
+    int err;
+    gnutls_session_t session;
+
+    /* Initialize TLS session 
+     */
+    err = gnutls_init (&session, GNUTLS_CLIENT);
+    if (err) {
+        error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err));
+        return NULL;
+    }
+
+    /* Use default priorities */
+    err = gnutls_set_default_priority (session);
+    if (err) {
+        error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err));
+        return NULL;
+    }
+    err =
+        gnutls_certificate_type_set_priority (session,
+                                              cert_type_priority);
+    if (err) {
+        error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err));
+        return NULL;
+    }
+
+    /* put the x509 credentials to the current session
+     */
+    err = gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+    if (err) {
+        error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err));
+        return NULL;
+    }
+
+    gnutls_transport_set_ptr (session,
+                              (gnutls_transport_ptr_t) (long) sock);
+
+    /* Perform the TLS handshake. */
+ again:
+    err = gnutls_handshake (session);
+    if (err < 0) {
+        if (err == GNUTLS_E_AGAIN || err == GNUTLS_E_INTERRUPTED)
+            goto again;
+        error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err));
+        return NULL;
+    }
+
+    /* Verify certificate. */
+    if (verify_certificate (conn, session, hostname) == -1) {
+            fprintf (stderr,
+                     "remote_internal: failed to verify peer's certificate\n");
+            if (!no_verify) return NULL;
+        }
+
+    /* At this point, the server is verifying _our_ certificate, IP address,
+     * etc.  If we make the grade, it will send us a '\1' byte.
+     */
+    char buf[1];
+    int len;
+ again_2:
+    len = gnutls_record_recv (session, buf, 1);
+    if (len < 0 && len != GNUTLS_E_UNEXPECTED_PACKET_LENGTH) {
+        if (len == GNUTLS_E_AGAIN || len == GNUTLS_E_INTERRUPTED)
+            goto again_2;
+        error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (len));
+        return NULL;
+    }
+    if (len != 1 || buf[0] != '\1') {
+        error (conn, VIR_ERR_RPC,
+               "server verification (of our certificate or IP address) failed\n");
+        return NULL;
+    }
+
+#if 0
+    /* Print session info. */
+    print_info (session);
+#endif
+
+    return session;
+}
+
+static int
+verify_certificate (virConnectPtr conn, gnutls_session_t session,
+                    const char *hostname)
+{
+    int ret;
+    unsigned int status;
+    const gnutls_datum_t *certs;
+    unsigned int nCerts, i;
+    time_t now;
+
+    if ((ret = gnutls_certificate_verify_peers2 (session, &status)) < 0) {
+        error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (ret));
+        return -1;
+    }
+  
+    if ((now = time(NULL)) == ((time_t)-1)) {
+        error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+        return -1;
+    }
+
+    if (status != 0) {
+        const char *reason = "Invalid certificate";
+
+        if (status & GNUTLS_CERT_INVALID)
+            reason = "The certificate is not trusted.";
+        
+        if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
+            reason = "The certificate hasn't got a known issuer.";
+    
+        if (status & GNUTLS_CERT_REVOKED)
+            reason = "The certificate has been revoked.";
+    
+        if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
+            reason = "The certificate uses an insecure algorithm";
+    
+        error (conn, VIR_ERR_RPC, reason);
+        return -1;
+    }
+
+    if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) {
+        error (conn, VIR_ERR_RPC, "Certificate type is not X.509");
+        return -1;
+    }
+  
+    if (!(certs = gnutls_certificate_get_peers(session, &nCerts))) {
+        error (conn, VIR_ERR_RPC, "gnutls_certificate_get_peers failed");
+        return -1;
+    }
+  
+    for (i = 0 ; i < nCerts ; i++) {
+        gnutls_x509_crt_t cert;
+
+        ret = gnutls_x509_crt_init (&cert);
+        if (ret < 0) {
+            error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (ret));
+            return -1;
+        }
+        
+        ret = gnutls_x509_crt_import (cert, &certs[i], GNUTLS_X509_FMT_DER);
+        if (ret < 0) {
+            error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (ret));
+            gnutls_x509_crt_deinit (cert);
+            return -1;
+        }
+    
+        if (gnutls_x509_crt_get_expiration_time (cert) < now) {
+            error (conn, VIR_ERR_RPC, "The certificate has expired");
+            gnutls_x509_crt_deinit (cert);
+            return -1;
+        }
+    
+        if (gnutls_x509_crt_get_activation_time (cert) > now) {
+            error (conn, VIR_ERR_RPC, "The certificate is not yet activated");
+            gnutls_x509_crt_deinit (cert);
+            return -1;
+        }
+    
+        if (i == 0) {
+            if (!gnutls_x509_crt_check_hostname (cert, hostname)) {
+                __virRaiseError
+                    (conn, NULL, NULL,
+                     VIR_FROM_REMOTE, VIR_ERR_RPC,
+                     VIR_ERR_ERROR, hostname, NULL, NULL,
+                     0, 0,
+                     "Certificate's owner does not match the hostname (%s)",
+                     hostname);
+                gnutls_x509_crt_deinit (cert);
+                return -1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+/*----------------------------------------------------------------------*/
+
+static int
+remoteClose (virConnectPtr conn)
+{
+    GET_PRIVATE (conn, -1);
+
+    if (call (conn, priv, REMOTE_PROC_CLOSE,
+              (xdrproc_t) xdr_void, (char *) NULL,
+              (xdrproc_t) xdr_void, (char *) NULL) == -1)
+        return -1;
+
+    return 0;
+}
+
+static char *
+remoteGetCapabilities (virConnectPtr conn)
+{
+    remote_get_capabilities_ret ret;
+    GET_PRIVATE (conn, NULL);
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, REMOTE_PROC_GET_CAPABILITIES,
+              (xdrproc_t) xdr_void, (char *) NULL,
+              (xdrproc_t) xdr_remote_get_capabilities_ret, (char *)&ret) == -1)
+        return NULL;
+
+    /* Caller frees this. */
+    return ret.capabilities;
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------*/
+
+static int really_write (virConnectPtr conn, struct private_data *priv,
+                         char *bytes, int len);
+static int really_read (virConnectPtr conn, struct private_data *priv,
+                        char *bytes, int len);
+
+/* This function performs a remote procedure call to procedure PROC_NR. */
+static int
+call (virConnectPtr conn, struct private_data *priv, int proc_nr,
+      xdrproc_t args_filter, char *args,
+      xdrproc_t ret_filter, char *ret)
+{
+    char buffer[REMOTE_MESSAGE_MAX];
+    char buffer2[4];
+    struct remote_message_header hdr;
+    XDR xdr;
+    int len;
+    struct remote_error rerror;
+
+    /* Get a unique serial number for this message. */
+    /* XXX This is supposed to be atomic over threads, but I don't know
+     * if it is.
+     */
+    static sig_atomic_t counter = 1;
+    sig_atomic_t serial = counter++;
+
+    hdr.prog = REMOTE_PROGRAM;
+    hdr.vers = REMOTE_PROTOCOL_VERSION;
+    hdr.proc = proc_nr;
+    hdr.direction = REMOTE_CALL;
+    hdr.serial = serial;
+    hdr.status = REMOTE_OK;
+
+    /* Serialise header followed by args. */
+    xdrmem_create (&xdr, buffer, sizeof buffer, XDR_ENCODE);
+    if (!xdr_remote_message_header (&xdr, &hdr)) {
+        error (conn, VIR_ERR_RPC, "xdr_remote_message_header");
+        return -1;
+    }
+
+    if (!(*args_filter) (&xdr, args)) {
+        error (conn, VIR_ERR_RPC, "marshalling args");
+        return -1;
+    }
+
+    /* Get the length stored in buffer. */
+    len = xdr_getpos (&xdr);
+    xdr_destroy (&xdr);
+
+    /* Length must include the length word itself (always encoded in
+     * 4 bytes as per RFC 4506).
+     */
+    len += 4;
+
+    /* Encode the length word. */
+    xdrmem_create (&xdr, buffer2, sizeof buffer2, XDR_ENCODE);
+    if (!xdr_int (&xdr, &len)) {
+        error (conn, VIR_ERR_RPC, "xdr_int (length word)");
+        return -1;
+    }
+    xdr_destroy (&xdr);
+
+    /* Send length word followed by header+args. */
+    if (really_write (conn, priv, buffer2, sizeof buffer2) == -1 ||
+        really_write (conn, priv, buffer, len-4) == -1)
+        return -1;
+
+    /* Read and deserialise length word. */
+    if (really_read (conn, priv, buffer2, sizeof buffer2) == -1)
+        return -1;
+
+    xdrmem_create (&xdr, buffer2, sizeof buffer2, XDR_DECODE);
+    if (!xdr_int (&xdr, &len)) {
+        error (conn, VIR_ERR_RPC, "xdr_int (length word, reply)");
+        return -1;
+    }
+    xdr_destroy (&xdr);
+
+    /* Length includes length word - adjust to real length to read. */
+    len -= 4;
+
+    if (len < 0 || len > REMOTE_MESSAGE_MAX) {
+        error (conn, VIR_ERR_RPC, "packet received from server too large");
+        return -1;
+    }
+
+    /* Read reply header and what follows (either a ret or an error). */
+    if (really_read (conn, priv, buffer, len) == -1)
+        return -1;
+
+    /* Deserialise reply header. */
+    xdrmem_create (&xdr, buffer, len, XDR_DECODE);
+    if (!xdr_remote_message_header (&xdr, &hdr)) {
+        error (conn, VIR_ERR_RPC, "xdr_remote_message_header (reply)");
+        return -1;
+    }
+
+    /* Check program, version, etc. are what we expect. */
+    if (hdr.prog != REMOTE_PROGRAM) {
+        __virRaiseError (conn, NULL, NULL, VIR_FROM_REMOTE,
+                         VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+                         "unknown program (received %x, expected %x)",
+                         hdr.prog, REMOTE_PROGRAM);
+        return -1;
+    }
+    if (hdr.vers != REMOTE_PROTOCOL_VERSION) {
+        __virRaiseError (conn, NULL, NULL, VIR_FROM_REMOTE,
+                         VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+                         "unknown protocol version (received %x, expected %x)",
+                         hdr.vers, REMOTE_PROTOCOL_VERSION);
+        return -1;
+    }
+
+    /* If we extend the server to actually send asynchronous messages, then
+     * we'll need to change this so that it can recognise an asynch
+     * message being received at this point.
+     */
+    if (hdr.proc != proc_nr) {
+        __virRaiseError (conn, NULL, NULL, VIR_FROM_REMOTE,
+                         VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+                         "unknown procedure (received %x, expected %x)",
+                         hdr.proc, proc_nr);
+        return -1;
+    }
+    if (hdr.direction != REMOTE_REPLY) {
+        __virRaiseError (conn, NULL, NULL, VIR_FROM_REMOTE,
+                         VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+                         "unknown direction (received %x, expected %x)",
+                         hdr.direction, REMOTE_REPLY);
+        return -1;
+    }
+    if (hdr.serial != serial) {
+        __virRaiseError (conn, NULL, NULL, VIR_FROM_REMOTE,
+                         VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+                         "unknown serial (received %x, expected %x)",
+                         hdr.serial, serial);
+        return -1;
+    }
+
+    /* Status is either REMOTE_OK (meaning that what follows is a ret
+     * structure), or REMOTE_ERROR (and what follows is a remote_error
+     * structure).
+     */
+    switch (hdr.status) {
+    case REMOTE_OK:
+        if (!(*ret_filter) (&xdr, ret)) {
+            error (conn, VIR_ERR_RPC, "unmarshalling ret");
+            return -1;
+        }
+        xdr_destroy (&xdr);
+        return 0;
+
+    case REMOTE_ERROR:
+        memset (&rerror, 0, sizeof rerror);
+        if (!xdr_remote_error (&xdr, &rerror)) {
+            error (conn, VIR_ERR_RPC, "unmarshalling remote_error");
+            return -1;
+        }
+        xdr_destroy (&xdr);
+        server_error (conn, &rerror);
+        xdr_free ((xdrproc_t) xdr_remote_error, (char *) &rerror);
+        return -1;
+
+    default:
+        __virRaiseError (conn, NULL, NULL, VIR_FROM_REMOTE,
+                         VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0,
+                         "unknown status (received %x)",
+                         hdr.status);
+        xdr_destroy (&xdr);
+        return -1;
+    }
+}
+
+static int
+really_write (virConnectPtr conn, struct private_data *priv,
+              char *bytes, int len)
+{
+    char *p;
+    int err;
+
+    p = bytes;
+    if (priv->uses_tls) {
+        do {
+            err = gnutls_record_send (priv->session, p, len);
+            if (err < 0) {
+                if (err == GNUTLS_E_INTERRUPTED || err == GNUTLS_E_AGAIN)
+                    continue;
+                error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err));
+                return -1;
+            }
+            len -= err;
+            p += err;
+        }
+        while (len > 0);
+    } else {
+        do {
+            err = write (priv->sock, p, len);
+            if (err == -1) {
+                if (errno == EINTR || errno == EAGAIN)
+                    continue;
+                error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+                return -1;
+            }
+            len -= err;
+            p += err;
+        }
+        while (len > 0);
+    }
+
+    return 0;
+}
+
+static int
+really_read (virConnectPtr conn, struct private_data *priv,
+             char *bytes, int len)
+{
+    char *p;
+    int err;
+
+    p = bytes;
+    if (priv->uses_tls) {
+        do {
+            err = gnutls_record_recv (priv->session, p, len);
+            if (err < 0) {
+                if (err == GNUTLS_E_INTERRUPTED || err == GNUTLS_E_AGAIN)
+                    continue;
+                error (conn, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err));
+                return -1;
+            }
+            if (err == 0) {
+                error (conn, VIR_ERR_RPC, "socket closed unexpectedly");
+                return -1;
+            }
+            len -= err;
+            p += err;
+        }
+        while (len > 0);
+    } else {
+        do {
+            err = read (priv->sock, p, len);
+            if (err == -1) {
+                if (errno == EINTR || errno == EAGAIN)
+                    continue;
+                error (conn, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+                return -1;
+            }
+            if (err == 0) {
+                error (conn, VIR_ERR_RPC, "socket closed unexpectedly");
+                return -1;
+            }
+            len -= err;
+            p += err;
+        }
+        while (len > 0);
+    }
+
+    return 0;
+}
+
+/* For errors internal to this library. */
+static void
+error (virConnectPtr conn, virErrorNumber code, const char *info)
+{
+    const char *errmsg;
+
+    /* XXX I don't think this is correct use of virErrorMsg. */
+    errmsg = __virErrorMsg (code, info);
+    __virRaiseError (conn, NULL, NULL, VIR_FROM_REMOTE,
+                     code, VIR_ERR_ERROR, errmsg, info, NULL, 0, 0,
+                     errmsg, info);
+}
+
+/* For errors generated on the server side and sent back to us. */
+static void
+server_error (virConnectPtr conn, remote_error *err)
+{
+    virDomainPtr dom = get_domain_from_name (conn, err->dom);
+    virNetworkPtr net = get_network_from_name (conn, err->net);
+
+    /* These strings are nullable.  OK to ignore the return value
+     * of strdup since these strings are informational.
+     */
+    char *str1 = err->str1 ? strdup (*err->str1) : NULL;
+    char *str2 = err->str2 ? strdup (*err->str2) : NULL;
+    char *str3 = err->str3 ? strdup (*err->str3) : NULL;
+
+    char *message = err->message ? strdup (*err->message) : NULL;
+
+    /* XXX I don't think this is correct use of virErrorMsg. */
+    const char *msg = __virErrorMsg (err->code, message);
+
+    __virRaiseError (conn, dom, net,
+                     err->domain, err->code, err->level,
+                     str1, str2, str3,
+                     err->int1, err->int2,
+                     msg);
+}
+
+/* Domains and networks are represented on the wire by an
+ * optional (name, uuid) pair.  If omitted, it stands for NULL.
+ */
+static virDomainPtr
+get_domain_from_name (virConnectPtr conn, remote_domain domain)
+{
+    if (!conn || !domain) return NULL;
+    return virGetDomain (conn, domain->name, BAD_CAST domain->uuid);
+}
+
+static virNetworkPtr
+get_network_from_name (virConnectPtr conn, remote_network network)
+{
+    if (!conn || !network) return NULL;
+    return virGetNetwork (conn, network->name, BAD_CAST network->uuid);
+}
+
+/*----------------------------------------------------------------------*/
+
+static virDriver driver = {
+    .no = VIR_DRV_REMOTE,
+    .name = "remote",
+    .ver = REMOTE_PROTOCOL_VERSION,
+    .open = remoteOpen,
+    .close = remoteClose,
+    .getCapabilities = remoteGetCapabilities,
+    /* XXX */
+};
+
+#if 0
+static virNetworkDriver network_driver = {
+    .open = remoteNetworkOpen,
+    .close = remoteNetworkClose,
+    /* XXX */
+};
+#endif
+
+/* remoteRegister:
+ *
+ * Register driver with libvirt driver system.
+ */
+int
+remoteRegister (void)
+{
+    if (virRegisterDriver (&driver) == -1) return -1;
+#if 0
+    if (virRegisterNetworkDriver (&network_driver) == -1) return -1;
+#endif
+
+    return 0;
+}
+
+/*
+ * vim: set tabstop=4:
+ * vim: set shiftwidth=4:
+ * vim: set expandtab:
+ */
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/src/remote_internal.h libvirt-remote/src/remote_internal.h
--- libvirt-cvs/src/remote_internal.h	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-remote/src/remote_internal.h	2007-04-26 11:16:24.000000000 +0100
@@ -0,0 +1,58 @@
+/*
+ * remote_internal.h: driver to provide access to libvirtd running
+ *   on a remote machine
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Richard Jones <rjones@xxxxxxxxxx>
+ */
+
+#ifndef __VIR_REMOTE_INTERNAL_H__
+#define __VIR_REMOTE_INTERNAL_H__
+
+#include <libvirt/virterror.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int remoteRegister (void);
+
+#define LIBVIRTD_TLS_PORT "16514"
+#define LIBVIRTD_TCP_PORT "16509"
+#define LIBVIRTD_UNIX_SOCKET (LOCAL_STATE_DIR "/run/libvirt/libvirt-sock")
+#define LIBVIRTD_UNIX_SOCKET_RO (LOCAL_STATE_DIR "/run/libvirt/libvirt-sock-ro")
+#define LIBVIRTD_CONFIGURATION_FILE (SYSCONFDIR "/libvirtd.conf")
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __VIR_REMOTE_INTERNAL_H__ */
+
+/*
+ * vim: set tabstop=4:
+ * vim: set shiftwidth=4:
+ * vim: set expandtab:
+ */
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/src/virterror.c libvirt-remote/src/virterror.c
--- libvirt-cvs/src/virterror.c	2007-04-26 11:23:39.000000000 +0100
+++ libvirt-remote/src/virterror.c	2007-04-18 11:18:47.000000000 +0100
@@ -277,6 +277,9 @@
         case VIR_FROM_TEST:
             dom = "Test ";
             break;
+        case VIR_FROM_REMOTE:
+            dom = "Remote ";
+            break;
     }
     if ((err->dom != NULL) && (err->code != VIR_ERR_INVALID_DOMAIN)) {
         domain = err->dom->name;
@@ -613,6 +616,18 @@
         else
             errmsg = "%s";
         break;
+    case VIR_ERR_RPC:
+        if (info == NULL)
+            errmsg = _("RPC error");
+        else
+            errmsg = "%s";
+        break;
+    case VIR_ERR_GNUTLS_ERROR:
+        if (info == NULL)
+            errmsg = _("GNUTLS call error");
+        else
+            errmsg = "%s";
+        break;
     }
     return (errmsg);
 }

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]