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

[Libvir] Remote patch, 2007-05-01



This is a patch against CVS -- in other words, it includes the two previous patches I sent to this list today.

Compared to the previous patch, it's just bug fixes and testing.

Sorry, these patches are getting rather huge. Unfortunately I can't see any sensible way to split it up. For the most part you either have remote support or you don't.

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 17:50:20.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-26 17:50:19.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-26 17:48:41.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-27 11:29:47.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-26 17:50:18.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/libvirtd.conf libvirt-remote/libvirtd.conf
--- libvirt-cvs/libvirtd.conf	1970-01-01 01:00:00.000000000 +0100
+++ libvirt-remote/libvirtd.conf	2007-04-27 14:13:08.000000000 +0100
@@ -0,0 +1,3 @@
+# Example /etc/libvirt/libvirtd.conf file.
+
+tls_no_verify_certificate = 1
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-26 17:47:55.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-26 17:47:51.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-26 17:47:55.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-27 14:38:58.000000000 +0100
@@ -27,8 +27,11 @@
 
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
 
 #include "protocol.h"
+#include "remote_protocol.h"
 #include "bridge.h"
 #include "iptables.h"
 
@@ -58,15 +61,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,22 +267,61 @@
     struct qemud_network *next;
 };
 
+
+enum qemud_mode {
+    QEMUD_MODE_RX_HEADER,
+    QEMUD_MODE_RX_PAYLOAD,
+    QEMUD_MODE_TX_PACKET,
+    QEMUD_MODE_TLS_HANDSHAKE,
+};
+
+/* These have to remain compatible with gnutls_record_get_direction. */
+enum qemud_tls_direction {
+    QEMUD_TLS_DIRECTION_READ = 0,
+    QEMUD_TLS_DIRECTION_WRITE = 1,
+};
+
 /* 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;
+    enum qemud_mode mode;
+
+    struct sockaddr_storage addr;
+    socklen_t addrlen;
+
+    /* If set, TLS is required on this socket. */
+    int tls;
+    gnutls_session_t session;
+    enum qemud_tls_direction direction;
+
+    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;
     int readonly;
+    /* If set, TLS is required on this socket. */
+    int tls;
+
     struct qemud_socket *next;
 };
 
@@ -311,7 +344,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 +374,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-26 17:47:31.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-27 11:29:40.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-26 17:47:55.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 redhat com>
+ * 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-26 17:47:27.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 redhat com>
+ */
+
+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-27 15:37:19.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,19 +46,48 @@
 #include <errno.h>
 #include <getopt.h>
 #include <ctype.h>
-
+#include <assert.h>
+#include <fnmatch.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
 
 #include <libvirt/virterror.h>
 
 #include "internal.h"
+#include "../src/remote_internal.h"
+#include "../src/conf.h"
 #include "dispatch.h"
 #include "driver.h"
 #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 only) system mode */
+static int timeout = -1;        /* -t: (QEMUD only) timeout */
+static int sigwrite = -1;       /* Signal handler pipe */
+
+/* Defaults for configuration file elements (remote only). */
+static int listen_tls = 1;
+static int listen_tcp = 0;
+static const char *tls_port = LIBVIRTD_TLS_PORT;
+static const char *tcp_port = LIBVIRTD_TCP_PORT;
+
+static int tls_no_verify_certificate = 0;
+static int tls_no_verify_address = 0;
+static const char **tls_allowed_clients = 0;
+
+/* XXX Still to decide where these certificates should be located. */
+static const char *key_file = "serverkey.pem";
+static const char *cert_file = "servercert.pem";
+static const char *ca_file = "demoCA/cacert.pem";
+static const char *crl_file = "";
+
+static gnutls_certificate_credentials_t x509_cred;
+static gnutls_dh_params_t dh_params;
+
+#define DH_BITS 1024
 
 static sig_atomic_t sig_errors = 0;
 static int sig_lasterrno = 0;
@@ -78,6 +109,80 @@
     errno = origerrno;
 }
 
+static int
+remoteInitializeGnuTLS (void)
+{
+    int err;
+
+    /* Initialise GnuTLS. */
+    gnutls_global_init ();
+
+    err = gnutls_certificate_allocate_credentials (&x509_cred);
+    if (err) {
+        qemudLog (QEMUD_ERR, "gnutls_certificate_allocate_credentials: %s",
+                  gnutls_strerror (err));
+        return -1;
+    }
+
+    if (ca_file && ca_file[0] != '\0') {
+        qemudDebug ("loading CA cert from %s", ca_file);
+        err = gnutls_certificate_set_x509_trust_file (x509_cred, ca_file,
+                                                      GNUTLS_X509_FMT_PEM);
+        if (err < 0) {
+            qemudLog (QEMUD_ERR, "gnutls_certificate_set_x509_trust_file: %s",
+                      gnutls_strerror (err));
+            return -1;
+        }
+    }
+
+    if (crl_file && crl_file[0] != '\0') {
+        qemudDebug ("loading CRL from %s", crl_file);
+        err = gnutls_certificate_set_x509_crl_file (x509_cred, crl_file,
+                                                    GNUTLS_X509_FMT_PEM);
+        if (err < 0) {
+            qemudLog (QEMUD_ERR, "gnutls_certificate_set_x509_crl_file: %s",
+                      gnutls_strerror (err));
+            return -1;
+        }
+    }
+
+    if (cert_file && cert_file[0] != '\0' && key_file && key_file[0] != '\0') {
+        qemudDebug ("loading cert and key from %s and %s",
+                    cert_file, key_file);
+        err =
+            gnutls_certificate_set_x509_key_file (x509_cred,
+                                                  cert_file, key_file,
+                                                  GNUTLS_X509_FMT_PEM);
+        if (err < 0) {
+            qemudLog (QEMUD_ERR, "gnutls_certificate_set_x509_key_file: %s",
+                      gnutls_strerror (err));
+            return -1;
+        }
+    }
+
+    /* Generate Diffie Hellman parameters - for use with DHE
+     * kx algorithms. These should be discarded and regenerated
+     * once a day, once a week or once a month. Depending on the
+     * security requirements.
+     */
+    err = gnutls_dh_params_init (&dh_params);
+    if (err < 0) {
+        qemudLog (QEMUD_ERR, "gnutls_dh_params_init: %s",
+                  gnutls_strerror (err));
+        return -1;
+    }
+    err = gnutls_dh_params_generate2 (dh_params, DH_BITS);
+    if (err < 0) {
+        qemudLog (QEMUD_ERR, "gnutls_dh_params_generate2: %s",
+                  gnutls_strerror (err));
+        return -1;
+    }
+
+    gnutls_certificate_set_dh_params (x509_cred, dh_params);
+
+    return 0;
+}
+
 static int qemudDispatchSignal(struct qemud_server *server)
 {
     unsigned char sigc;
@@ -96,11 +201,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 +216,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;
@@ -405,66 +514,200 @@
     return 0;
 }
 
-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 */
-    };
+// See: http://people.redhat.com/drepper/userapi-ipv6.html
+static int
+remoteMakeSockets (int *fds, int max_fds, int *nfds_r, const char *service)
+{
+    struct addrinfo *ai;
+    struct addrinfo hints;
+    memset (&hints, 0, sizeof hints);
+    hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
+    hints.ai_socktype = SOCK_STREAM;
+
+    int e = getaddrinfo (NULL, service, &hints, &ai);
+    if (e != 0) {
+        qemudLog (QEMUD_ERR, "getaddrinfo: %s\n", gai_strerror (e));
+        return -1;
+    }
 
-    uid_t uid;
-    struct passwd *pw;
-    char base[PATH_MAX] = SYSCONF_DIR "/";
+    struct addrinfo *runp = ai;
+    while (runp && *nfds_r < max_fds) {
+        fds[*nfds_r] = socket (runp->ai_family, runp->ai_socktype,
+                               runp->ai_protocol);
+        if (fds[*nfds_r] == -1) {
+            qemudLog (QEMUD_ERR, "socket: %s", strerror (errno));
+            return -1;
+        }
+
+        int opt = 1;
+        setsockopt (fds[*nfds_r], SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt);
+
+        if (bind (fds[*nfds_r], runp->ai_addr, runp->ai_addrlen) == -1) {
+            if (errno != EADDRINUSE) {
+                qemudLog (QEMUD_ERR, "bind: %s", strerror (errno));
+                return -1;
+            }
+            close (fds[*nfds_r]);
+        }
+        else {
+            if (listen (fds[*nfds_r], SOMAXCONN) == -1) {
+                qemudLog (QEMUD_ERR, "listen: %s", strerror (errno));
+                return -1;
+            }
+            ++*nfds_r;
+        }
+        runp = runp->ai_next;
+    }
+
+    freeaddrinfo (ai);
+    return 0;
+}
+
+/* Listen on the named/numbered TCP port.  On a machine with IPv4 and
+ * IPv6 interfaces this may generate several sockets.
+ */
+static int
+remoteListenTCP (struct qemud_server *server,
+                 const char *port,
+                 int tls)
+{
+    int fds[2];
+    int nfds = 0;
     int i;
+    struct qemud_socket *sock;
+
+    if (remoteMakeSockets (fds, 2, &nfds, port) == -1)
+        return -1;
+
+    for (i = 0; i < nfds; ++i) {
+        sock = calloc (1, sizeof *sock);
 
-    uid = geteuid();
+        if (!sock) {
+            qemudLog (QEMUD_ERR,
+                      "remoteListenTCP: calloc: %s", strerror (errno));
+            return -1;
+        }
+
+        sock->readonly = 0;
+        sock->next = server->sockets;
+        server->sockets = sock;
+        server->nsockets++;
+
+        sock->fd = fds[i];
+        sock->tls = tls;
+
+        if (qemudSetCloseExec(sock->fd) < 0 ||
+            qemudSetNonBlock(sock->fd) < 0)
+            return -1;
 
-    if (sys) {
-        if (uid != 0) {
-            qemudLog(QEMUD_ERR, "You must run the daemon as root to use system mode");
+        if (listen (sock->fd, 30) < 0) {
+            qemudLog (QEMUD_ERR,
+                      "remoteListenTCP: listen: %s", strerror (errno));
             return -1;
         }
+    }
+
+    return 0;
+}
+
+static int qemudInitPaths(struct qemud_server *server,
+                          char *sockname,
+                          char *roSockname,
+                          int maxlen) {
+    char *base = 0;
+
+    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);
+
+        server->configDir =
+            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,22 +723,30 @@
 
     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) {
-        goto cleanup;
+    if (!remote) /* qemud only */ {
+        if (qemudScanConfigs(server) < 0) {
+            goto cleanup;
+        }
+    } else /* remote only */ {
+        if (listen_tcp && remoteListenTCP (server, tcp_port, 0) < 0)
+            goto cleanup;
+
+        if (listen_tls) {
+            if (remoteInitializeGnuTLS () < 0)
+                goto cleanup;
+
+            if (remoteListenTCP (server, tls_port, 1) < 0)
+                goto cleanup;
+        }
     }
 
     return server;
@@ -508,16 +759,232 @@
             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;
 }
 
+static gnutls_session_t
+remoteInitializeTLSSession (void)
+{
+  gnutls_session_t session;
+  int err;
+
+  err = gnutls_init (&session, GNUTLS_SERVER);
+  if (err != 0) goto failed;
+
+  /* avoid calling all the priority functions, since the defaults
+   * are adequate.
+   */
+  err = gnutls_set_default_priority (session);
+  if (err != 0) goto failed;
+
+  err = gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+  if (err != 0) goto failed;
+
+  /* request client certificate if any.
+   */
+  gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
+
+  gnutls_dh_set_prime_bits (session, DH_BITS);
+
+  return session;
+
+ failed:
+  qemudLog (QEMUD_ERR, "remoteInitializeTLSSession: %s",
+            gnutls_strerror (err));
+  return NULL;
+}
+
+/* Modified version of gnutls_x509_crt_check_hostname which checks
+ * a numeric IP address against iPAddress in the certificate.  If
+ * and only if there is no subjectAltName iPAddress extension, then
+ * we check against the CN.  It currently only allows exact matches
+ * (ie. not wildcards).  See RFC 2818 sections 3.1 & 3.2.  Also
+ * updated in RFC 3280.  Also see lib/x509/rfc2818_hostname.c in
+ * the GnuTLS source.
+ */
+static int
+my_gnutls_x509_crt_check_address (gnutls_x509_crt_t cert, const char *addr)
+{
+    char name[256]; // This is hard-coded in original too.
+    size_t namesize;
+    int i, ret = 0, found_iPAddress = 0;
+
+    for (i = 0; ret >= 0; ++i) {
+        namesize = sizeof name;
+        ret = gnutls_x509_crt_get_subject_alt_name (cert, i,
+                                                    name, &namesize, NULL);
+        if (ret == GNUTLS_SAN_IPADDRESS) {
+            found_iPAddress = 1;
+            if (strcmp (name, addr) == 0) return 1;
+        }
+    }
+
+    if (!found_iPAddress) {
+        namesize = sizeof name;
+        if (gnutls_x509_crt_get_dn_by_oid (cert,
+                                           GNUTLS_OID_X520_COMMON_NAME, 0,
+                                           0, name, &namesize) < 0)
+            return 0;
+
+        if (strcmp (name, addr) == 0) return 1;
+    }
+
+    return 0; // Not found.
+}
+
+static int
+remoteCheckCertificate (gnutls_session_t session, const char *addr)
+{
+    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){
+        qemudLog (QEMUD_ERR, "remoteCheckCertificate: verify failed: %s",
+                  gnutls_strerror (ret));
+        return -1;
+    }
+
+    if (status != 0) {
+        if (status & GNUTLS_CERT_INVALID)
+            qemudLog (QEMUD_ERR, "remoteCheckCertificate: the client certificate is not trusted.");
+
+        if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
+            qemudLog (QEMUD_ERR, "remoteCheckCertificate: the client certificate hasn't got a known issuer.");
+
+        if (status & GNUTLS_CERT_REVOKED)
+            qemudLog (QEMUD_ERR, "remoteCheckCertificate: the client certificate has been revoked.");
+
+        if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
+            qemudLog (QEMUD_ERR, "remoteCheckCertificate: the client certificate uses an insecure algorithm.");
+
+        return -1;
+    }
+
+    if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) {
+        qemudLog (QEMUD_ERR, "remoteCheckCertificate: certificate is not X.509");
+        return -1;
+    }
+
+    if (!(certs = gnutls_certificate_get_peers(session, &nCerts))) {
+        qemudLog (QEMUD_ERR, "remoteCheckCertificate: no peers");
+        return -1;
+    }
+
+    now = time (NULL);
+
+    for (i = 0; i < nCerts; i++) {
+        gnutls_x509_crt_t cert;
+
+        if (gnutls_x509_crt_init (&cert) < 0) {
+            qemudLog (QEMUD_ERR, "remoteCheckCertificate: gnutls_x509_crt_init failed");
+            return -1;
+        }
+
+        if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) {
+            gnutls_x509_crt_deinit (cert);
+            return -1;
+        }
+    
+        if (gnutls_x509_crt_get_expiration_time (cert) < now) {
+            qemudLog (QEMUD_ERR, "remoteCheckCertificate: the client certificate has expired");
+            gnutls_x509_crt_deinit (cert);
+            return -1;
+        }
+    
+        if (gnutls_x509_crt_get_activation_time (cert) > now) {
+            qemudLog (QEMUD_ERR, "remoteCheckCertificate: the client certificate is not yet activated");
+            gnutls_x509_crt_deinit (cert);
+            return -1;
+        }
+
+        if (i == 0) {
+            if (!my_gnutls_x509_crt_check_address (cert, addr))
+                return -1;
+            gnutls_x509_crt_deinit (cert);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+/* Check the client's access. */
+static int
+remoteCheckAccess (struct qemud_client *client)
+{
+    char addr[NI_MAXHOST];
+    const char **wildcards;
+    int found, err;
+
+    /* Convert IP address to printable string (eg. "127.0.0.1" or "::1"). */
+    err = getnameinfo ((struct sockaddr *) &client->addr, client->addrlen,
+                       addr, sizeof addr, NULL, 0,
+                       NI_NUMERICHOST);
+    if (err != 0) {
+        qemudLog (QEMUD_ERR, "getnameinfo: %s", gai_strerror (err));
+        return -1;
+    }
+
+    /* Verify client certificate. */
+    if (remoteCheckCertificate (client->session, addr) == -1) {
+        qemudLog (QEMUD_ERR, "remoteCheckCertificate: failed to verify client's certificate");
+        if (!tls_no_verify_certificate) return -1;
+        else qemudLog (QEMUD_INFO, "remoteCheckCertificate: tls_no_verify_certificate is set so the bad certificate is ignored");
+    }
+
+    /* Verify the client is on the list of allowed clients.
+     *
+     * NB: No tls_allowed_clients in config file means anyone can access.
+     * If tls_allowed_clients is in the config file but empty, means no
+     * one can access (not particularly useful, but it's what the sysadmin
+     * would expect).
+     */
+    wildcards = tls_allowed_clients;
+    if (wildcards) {
+        found = 0;
+
+        while (*wildcards) {
+            if (fnmatch (*wildcards, addr, 0) == 0) {
+                found = 1;
+                break;
+            }
+            wildcards++;
+        }
+    } else
+        found = 1;
+
+    if (!found) {
+        qemudLog (QEMUD_ERR, "remoteCheckAccess: client is not on the list of allowed clients (tls_allowed_clients)");
+        if (!tls_no_verify_address) return -1;
+        else qemudLog (QEMUD_INFO, "remoteCheckAccess: tls_no_verify_address is set so the client address is ignored");
+    }
+
+    /* Checks have succeeded.  Write a '\1' byte back to the client to
+     * indicate this (otherwise the socket is abruptly closed).
+     * (NB. The '\1' byte is sent in an encrypted record).
+     */
+    client->bufferLength = 1;
+    client->bufferOffset = 0;
+    client->buffer[0] = '\1';
+    client->mode = QEMUD_MODE_TX_PACKET;
+    client->direction = QEMUD_TLS_DIRECTION_WRITE;
+    return 0;
+}
 
 static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket *sock) {
     int fd;
     struct sockaddr_storage addr;
-    unsigned int addrlen = sizeof(addr);
+    socklen_t addrlen = (socklen_t) (sizeof addr);
     struct qemud_client *client;
 
     if ((fd = accept(sock->fd, (struct sockaddr *)&addr, &addrlen)) < 0) {
@@ -534,14 +1001,54 @@
     }
 
     client = calloc(1, sizeof(struct qemud_client));
+    client->magic = QEMUD_CLIENT_MAGIC;
     client->fd = fd;
     client->readonly = sock->readonly;
+    client->tls = sock->tls;
+    memcpy (&client->addr, &addr, sizeof addr);
+    client->addrlen = addrlen;
+
+    if (!client->tls) {
+        client->mode = QEMUD_MODE_RX_HEADER;
+        client->bufferLength = QEMUD_PKT_HEADER_XDR_LEN;
+    } else {
+        int ret;
+
+        client->session = remoteInitializeTLSSession ();
+        if (client->session == NULL) goto tls_failed;
+
+        gnutls_transport_set_ptr (client->session,
+                                  (gnutls_transport_ptr_t) (long) fd);
+
+        /* Begin the TLS handshake. */
+        ret = gnutls_handshake (client->session);
+        if (ret == 0) {
+            /* Unlikely, but ...  Next step is to check the certificate. */
+            if (remoteCheckAccess (client) == -1)
+                goto tls_failed;
+        } else if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
+            /* Most likely. */
+            client->mode = QEMUD_MODE_TLS_HANDSHAKE;
+            client->bufferLength = -1;
+            client->direction = gnutls_record_get_direction (client->session);
+        } else {
+            qemudLog (QEMUD_ERR, "TLS handshake failed: %s",
+                      gnutls_strerror (ret));
+            goto tls_failed;
+        }
+    }
 
     client->next = server->clients;
     server->clients = client;
     server->nclients++;
 
     return 0;
+
+ tls_failed:
+    if (client->session) gnutls_deinit (client->session);
+    close (fd);
+    free (client);
+    return -1;
 }
 
 
@@ -911,113 +1418,310 @@
         prev = tmp;
         tmp = tmp->next;
     }
+
+    if (client->tls && client->session) gnutls_deinit (client->session);
     close(client->fd);
     free(client);
 }
 
 
-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) {
-    int ret;
-    if ((ret = read(client->fd, buf, want)) <= 0) {
-        qemudDebug("Plain read error %d", ret);
-        if (!ret || errno != EAGAIN)
-            qemudDispatchClientFailure(server, client);
-        return -1;
+                           struct qemud_client *client) {
+    int ret, len;
+    char *data;
+
+    data = client->buffer + client->bufferOffset;
+    len = client->bufferLength - client->bufferOffset;
+
+    /*qemudDebug ("qemudClientRead: len = %d", len);*/
+
+    if (!client->tls) {
+        if ((ret = read (client->fd, data, len)) == -1) {
+            if (ret == 0 || errno != EAGAIN) {
+                if (ret != 0)
+                    qemudLog (QEMUD_ERR, "read: %s", strerror (errno));
+                qemudDispatchClientFailure(server, client);
+            }
+            return -1;
+        }
+    } else {
+        ret = gnutls_record_recv (client->session, data, len);
+        client->direction = gnutls_record_get_direction (client->session);
+        if (ret <= 0) {
+            if (ret == 0 || (ret != GNUTLS_E_AGAIN &&
+                             ret != GNUTLS_E_INTERRUPTED)) {
+                if (ret != 0)
+                    qemudLog (QEMUD_ERR, "gnutls_record_recv: %s",
+                              gnutls_strerror (ret));
+                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;
-    }
+    /*qemudDebug ("qemudDispatchClientRead: mode = %d", client->mode);*/
 
-    if ((ret = qemudClientRead(server, client, data+got, want)) < 0) {
-        return;
-    }
-    got += ret;
-    client->incomingReceived += ret;
+    switch (client->mode) {
+    case QEMUD_MODE_RX_HEADER: {
+        XDR x;
+        qemud_packet_header h;
+
+        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 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);
+        if (!xdr_qemud_packet_header(&x, &h)) {
+            qemudDebug("Failed to decode packet header");
             qemudDispatchClientFailure(server, client);
             return;
         }
-        if (client->incoming.header.dataSize) {
-            qemudDebug("- Restarting recv to process body (%d bytes)",
-                        client->incoming.header.dataSize);
-            goto restart;
+
+        /* 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;
         }
+
+        /* 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;
+        if (client->tls) client->direction = QEMUD_TLS_DIRECTION_READ;
+        /* 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)
+    case 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);
+
+        break;
+    }
+
+    case QEMUD_MODE_TLS_HANDSHAKE: {
+        int ret;
+
+        /* Continue the handshake. */
+        ret = gnutls_handshake (client->session);
+        if (ret == 0) {
+            /* Finished.  Next step is to check the certificate. */
+            if (remoteCheckAccess (client) == -1)
+                qemudDispatchClientFailure (server, client);
+        } else if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED) {
+            qemudLog (QEMUD_ERR, "TLS handshake failed: %s",
+                      gnutls_strerror (ret));
+            qemudDispatchClientFailure (server, client);
+        } else
+            client->direction = gnutls_record_get_direction (client->session);
+
+        break;
+    }
+
+    default:
+        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) {
-    int ret;
-    if ((ret = write(client->fd, buf, want)) < 0) {
-        qemudDebug("Plain write error %d", ret);
-        if (errno != EAGAIN)
-            qemudDispatchClientFailure(server, client);
-        return -1;
+                            struct qemud_client *client) {
+    int ret, len;
+    char *data;
+
+    data = client->buffer + client->bufferOffset;
+    len = client->bufferLength - client->bufferOffset;
+
+    if (!client->tls) {
+        if ((ret = write(client->fd, data, len)) == -1) {
+            if (errno != EAGAIN) {
+                qemudLog (QEMUD_ERR, "write: %s", strerror (errno));
+                qemudDispatchClientFailure(server, client);
+            }
+            return -1;
+        }
+    } else {
+        ret = gnutls_record_send (client->session, data, len);
+        client->direction = gnutls_record_get_direction (client->session);
+        if (ret < 0) {
+            if (ret != GNUTLS_E_INTERRUPTED && ret != GNUTLS_E_AGAIN) {
+                qemudLog (QEMUD_ERR, "gnutls_record_send: %s",
+                          gnutls_strerror (ret));
+                qemudDispatchClientFailure (server, client);
+            }
+            return -1;
+        }
     }
-    qemudDebug("Plain data write %d", ret);
-    return ret;
+
+    client->bufferOffset += 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;
+    switch (client->mode) {
+    case 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;
+            if (client->tls) client->direction = QEMUD_TLS_DIRECTION_READ;
+        }
+        /* Still writing */
+        break;
+    }
+
+    case QEMUD_MODE_TLS_HANDSHAKE: {
+        int ret;
+
+        /* Continue the handshake. */
+        ret = gnutls_handshake (client->session);
+        if (ret == 0) {
+            /* Finished.  Next step is to check the certificate. */
+            if (remoteCheckAccess (client) == -1)
+                qemudDispatchClientFailure (server, client);
+        } else if (ret != GNUTLS_E_AGAIN && ret != GNUTLS_E_INTERRUPTED) {
+            qemudLog (QEMUD_ERR, "TLS handshake failed: %s",
+                      gnutls_strerror (ret));
+            qemudDispatchClientFailure (server, client);
+        } else
+            client->direction = gnutls_record_get_direction (client->session);
+
+        break;
+    }
+
+    default:
+        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 +2304,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)
@@ -1674,12 +2381,19 @@
     }
     for (client = server->clients ; client ; client = client->next) {
         fds[fd].fd = client->fd;
-        /* Refuse to read more from client if tx is pending to
-           rate limit */
-        if (client->tx)
-            fds[fd].events = POLLOUT | POLLERR | POLLHUP;
-        else
-            fds[fd].events = POLLIN | POLLERR | POLLHUP;
+        if (!client->tls) {
+            /* Refuse to read more from client if tx is pending to
+               rate limit */
+            if (client->mode == QEMUD_MODE_TX_PACKET)
+                fds[fd].events = POLLOUT | POLLERR | POLLHUP;
+            else
+                fds[fd].events = POLLIN | POLLERR | POLLHUP;
+        } else {
+            qemudDebug ("direction = %s",
+                        client->direction ? "WRITE" : "READ");
+            fds[fd].events = client->direction ? POLLOUT : POLLIN;
+            fds[fd].events |= POLLERR | POLLHUP;
+        }
         fd++;
     }
     for (sock = server->sockets ; sock ; sock = sock->next) {
@@ -1691,7 +2405,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 +2454,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,60 +2481,212 @@
     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);
 }
 
+/* Read the config file if it exists.
+ * Only used in the remote case, hence the name.
+ */
+static int
+remoteReadConfigFile (const char *filename)
+{
+    virConfPtr conf;
+
+    /* Just check the file is readable before opening it, otherwise
+     * libvirt emits an error.
+     */
+    if (access (filename, R_OK) == -1) return 0;
+
+    conf = virConfReadFile (filename);
+    if (!conf) return 0;
+
+    virConfValuePtr p;
+
+#define CHECK_TYPE(name,typ) if (p && p->type != (typ)) {               \
+        qemudLog (QEMUD_ERR,                                            \
+                  "remoteReadConfigFile: %s: %s: expected type " #typ "\n", \
+                  filename, (name));                                    \
+        return -1;                                                      \
+    }
+
+    p = virConfGetValue (conf, "listen_tls");
+    CHECK_TYPE ("listen_tls", VIR_CONF_LONG);
+    listen_tls = p ? p->l : listen_tls;
+
+    p = virConfGetValue (conf, "listen_tcp");
+    CHECK_TYPE ("listen_tcp", VIR_CONF_LONG);
+    listen_tcp = p ? p->l : listen_tcp;
+
+    p = virConfGetValue (conf, "tls_port");
+    CHECK_TYPE ("tls_port", VIR_CONF_STRING);
+    tls_port = p ? strdup (p->str) : tls_port;
+
+    p = virConfGetValue (conf, "tcp_port");
+    CHECK_TYPE ("tcp_port", VIR_CONF_STRING);
+    tcp_port = p ? strdup (p->str) : tcp_port;
+
+    p = virConfGetValue (conf, "tls_no_verify_certificate");
+    CHECK_TYPE ("tls_no_verify_certificate", VIR_CONF_LONG);
+    tls_no_verify_certificate = p ? p->l : tls_no_verify_certificate;
+
+    p = virConfGetValue (conf, "tls_no_verify_address");
+    CHECK_TYPE ("tls_no_verify_address", VIR_CONF_LONG);
+    tls_no_verify_address = p ? p->l : tls_no_verify_address;
+
+    p = virConfGetValue (conf, "key_file");
+    CHECK_TYPE ("key_file", VIR_CONF_STRING);
+    key_file = p ? strdup (p->str) : key_file;
+
+    p = virConfGetValue (conf, "cert_file");
+    CHECK_TYPE ("cert_file", VIR_CONF_STRING);
+    cert_file = p ? strdup (p->str) : cert_file;
+
+    p = virConfGetValue (conf, "ca_file");
+    CHECK_TYPE ("ca_file", VIR_CONF_STRING);
+    ca_file = p ? strdup (p->str) : ca_file;
+
+    p = virConfGetValue (conf, "crl_file");
+    CHECK_TYPE ("crl_file", VIR_CONF_STRING);
+    crl_file = p ? strdup (p->str) : crl_file;
+
+    p = virConfGetValue (conf, "tls_allowed_clients");
+    if (p) {
+        switch (p->type) {
+        case VIR_CONF_STRING:
+            tls_allowed_clients = malloc (2 * sizeof (char *));
+            tls_allowed_clients[0] = strdup (p->str);
+            tls_allowed_clients[1] = 0;
+            break;
+
+        case VIR_CONF_LIST: {
+            int i, len = 0;
+            virConfValuePtr pp;
+            for (pp = p->list; pp; pp = p->next)
+                len++;
+            tls_allowed_clients =
+                malloc ((1+len) * sizeof (char *));
+            for (i = 0, pp = p->list; pp; ++i, pp = p->next) {
+                if (pp->type != VIR_CONF_STRING) {
+                    qemudLog (QEMUD_ERR, "remoteReadConfigFile: %s: tls_allowed_clients: should be a string or list of strings\n", filename);
+                    return -1;
+                }
+                tls_allowed_clients[i] = strdup (pp->str);
+            }
+            tls_allowed_clients[i] = 0;
+            break;
+        }
+
+        default:
+            qemudLog (QEMUD_ERR, "remoteReadConfigFile: %s: tls_allowed_clients: should be a string or list of strings\n", filename);
+            return -1;
+        }
+    }
+
+    virConfFree (conf);
+    return 0;
+}
+
 /* Print command-line usage. */
 static void
 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 (QEMUD only).\n\
+  -t | --timeout <secs>  Exit after timeout period (QEMUD only).\n\
+  -f | --config <file>   Configuration file (remote only).\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 (unless overridden by -f):\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;
+    const char *remote_config_file = SYSCONF_DIR "/libvirt/libvirtd.conf";
     int ret = 1;
 
     struct option opts[] = {
         { "verbose", no_argument, &verbose, 1},
         { "daemon", no_argument, &godaemon, 1},
+        { "remote", no_argument, &remote, 1},
+        { "config", required_argument, NULL, 'f'},
         { "system", no_argument, &sys, 1},
         { "timeout", required_argument, NULL, 't'},
         { "pid-file", required_argument, NULL, 'p'},
@@ -1833,7 +2699,7 @@
         int c;
         char *tmp;
 
-        c = getopt_long(argc, argv, "vsdt:p:", opts, &optidx);
+        c = getopt_long(argc, argv, "dfp:s:t:v", opts, &optidx);
 
         if (c == -1) {
             break;
@@ -1849,6 +2715,9 @@
         case 'd':
             godaemon = 1;
             break;
+        case 'r':
+            remote = 1;
+            break;
         case 's':
             sys = 1;
             break;
@@ -1862,7 +2731,11 @@
             break;
 
         case 'p':
-            pid_file = strdup(optarg);
+            pid_file = optarg;
+            break;
+
+        case 'f':
+            remote_config_file = optarg;
             break;
 
         case '?':
@@ -1874,6 +2747,12 @@
         }
     }
 
+    /* In remote mode only, now read the config file (if it exists). */
+    if (remote) {
+        if (remoteReadConfigFile (remote_config_file) < 0)
+            goto error1;
+    }
+
     if (godaemon)
         openlog("libvirt-qemud", 0, 0);
 
@@ -1910,16 +2789,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 +2822,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-05-01 18:38:28.000000000 +0100
@@ -0,0 +1,578 @@
+/*
+ * 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 redhat com>
+ */
+
+#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 remoteDispatchType (struct qemud_client *client, remote_message_header *req, void *args, remote_get_type_ret *ret);
+static int remoteDispatchVersion (struct qemud_client *client, remote_message_header *req, void *args, remote_get_version_ret *ret);
+static int remoteDispatchGetMaxVcpus (struct qemud_client *client, remote_message_header *req, remote_get_max_vcpus_args *args, remote_get_max_vcpus_ret *ret);
+static int remoteDispatchNodeGetInfo (struct qemud_client *client, remote_message_header *req, void *args, remote_node_get_info_ret *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;
+    remote_get_type_ret get_type_ret;
+    remote_get_version_ret get_version_ret;
+    remote_get_max_vcpus_args get_max_vcpus_args;
+    remote_get_max_vcpus_ret get_max_vcpus_ret;
+    remote_node_get_info_ret node_get_info_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_TYPE:
+        fn = (dispatch_fn) remoteDispatchType;
+        ret_filter = (xdrproc_t) xdr_remote_get_type_ret;
+        ret = (char *) &get_type_ret;
+        memset (&get_type_ret, 0, sizeof get_type_ret);
+        break;
+
+    case REMOTE_PROC_VERSION:
+        fn = (dispatch_fn) remoteDispatchVersion;
+        ret_filter = (xdrproc_t) xdr_remote_get_version_ret;
+        ret = (char *) &get_version_ret;
+        memset (&get_version_ret, 0, sizeof get_version_ret);
+        break;
+
+    case REMOTE_PROC_GET_MAX_VCPUS:
+        fn = (dispatch_fn) remoteDispatchGetMaxVcpus;
+        args_filter = (xdrproc_t) xdr_remote_get_max_vcpus_args;
+        args = (char *) &get_max_vcpus_args;
+        memset (&get_max_vcpus_args, 0, sizeof get_max_vcpus_args);
+        ret_filter = (xdrproc_t) xdr_remote_get_max_vcpus_ret;
+        ret = (char *) &get_max_vcpus_ret;
+        memset (&get_max_vcpus_ret, 0, sizeof get_max_vcpus_ret);
+        break;
+
+    case REMOTE_PROC_NODE_GET_INFO:
+        fn = (dispatch_fn) remoteDispatchNodeGetInfo;
+        ret_filter = (xdrproc_t) xdr_remote_node_get_info_ret;
+        ret = (char *) &node_get_info_ret;
+        memset (&node_get_info_ret, 0, sizeof node_get_info_ret);
+        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 function must return -2, -1 or 0.  Anything else is
+     * an internal error.
+     */
+    if (rv < -2 || rv > 0) {
+        remoteDispatchError (client, &req, "internal error - dispatch function returned invalid code %d", rv);
+        return;
+    }
+
+    /* 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;
+    if (client->tls) client->direction = QEMUD_TLS_DIRECTION_WRITE;
+}
+
+/* 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;
+    if (client->tls) client->direction = QEMUD_TLS_DIRECTION_WRITE;
+}
+
+/*----- Functions. -----*/
+
+static int
+remoteDispatchOpen (struct qemud_client *client, remote_message_header *req,
+                    struct remote_open_args *args, void *ret ATTRIBUTE_UNUSED)
+{
+    const char *name;
+    int flags;
+
+    /* 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
+
+    /* If this connection arrived on a readonly socket, force
+     * the connection to be readonly.
+     */
+    flags = args->flags;
+    if (client->readonly) flags |= VIR_CONNECT_RO;
+
+    client->conn =
+        flags & VIR_CONNECT_RO
+        ? virConnectOpenReadOnly (name)
+        : virConnectOpen (name);
+
+    return client->conn ? 0 : -1;
+}
+
+#define CHECK_CONN                              \
+    if (!client->conn) {                        \
+        remoteDispatchError (client, req, "connection not open");   \
+        return -2;                                                  \
+    }
+
+static int
+remoteDispatchClose (struct qemud_client *client, remote_message_header *req,
+                     void *args ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED)
+{
+    int rv;
+    CHECK_CONN;
+
+    rv = virConnectClose (client->conn);
+    if (rv == 0) client->conn = NULL;
+
+    return rv;
+}
+
+static int
+remoteDispatchType (struct qemud_client *client, remote_message_header *req,
+                    void *args ATTRIBUTE_UNUSED, remote_get_type_ret *ret)
+{
+    const char *type;
+    CHECK_CONN;
+
+    type = virConnectGetType (client->conn);
+    if (type == NULL) return -1;
+
+    /* We have to strdup because remoteDispatchClientRequest will
+     * free this string after it's been serialised.
+     */
+    ret->type = strdup (type);
+    if (!ret->type) {
+        remoteDispatchError (client, req, "out of memory in strdup");
+        return -2;
+    }
+
+    return 0;
+}
+
+static int
+remoteDispatchVersion (struct qemud_client *client,
+                       remote_message_header *req,
+                       void *args ATTRIBUTE_UNUSED,
+                       remote_get_version_ret *ret)
+{
+    unsigned long hvVer;
+    CHECK_CONN;
+
+    if (virConnectGetVersion (client->conn, &hvVer) == -1)
+        return -1;
+
+    ret->hv_ver = hvVer;
+    return 0;
+}
+
+static int
+remoteDispatchGetMaxVcpus (struct qemud_client *client,
+                           remote_message_header *req,
+                           remote_get_max_vcpus_args *args,
+                           remote_get_max_vcpus_ret *ret)
+{
+    char *type;
+    CHECK_CONN;
+
+    type = args->type ? *args->type : NULL;
+    ret->max_vcpus = virConnectGetMaxVcpus (client->conn, type);
+    if (ret->max_vcpus == -1) return -1;
+
+    return 0;
+}
+
+static int
+remoteDispatchNodeGetInfo (struct qemud_client *client,
+                           remote_message_header *req,
+                           void *args ATTRIBUTE_UNUSED,
+                           remote_node_get_info_ret *ret)
+{
+    virNodeInfo info;
+    CHECK_CONN;
+
+    if (virNodeGetInfo (client->conn, &info) == -1)
+        return -1;
+
+    memcpy (ret->model, info.model, sizeof ret->model);
+    ret->memory = info.memory;
+    ret->cpus = info.cpus;
+    ret->mhz = info.mhz;
+    ret->nodes = info.nodes;
+    ret->sockets = info.sockets;
+    ret->cores = info.cores;
+    ret->threads = info.threads;
+
+    return 0;
+}
+
+static int
+remoteDispatchGetCapabilities (struct qemud_client *client,
+                               remote_message_header *req,
+                               void *args ATTRIBUTE_UNUSED,
+                               remote_get_capabilities_ret *ret)
+{
+    char *caps;
+    CHECK_CONN;
+
+    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-05-01 12:34:13.000000000 +0100
@@ -0,0 +1,980 @@
+/*
+ * 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_uuid (XDR *xdrs, remote_uuid objp)
+{
+
+	 if (!xdr_opaque (xdrs, objp, VIR_UUID_BUFLEN))
+		 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_remote_uuid (xdrs, objp->uuid))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_nonnull_domain (XDR *xdrs, remote_nonnull_domain *objp)
+{
+
+	 if (!xdr_remote_name (xdrs, objp))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_nonnull_network (XDR *xdrs, remote_nonnull_network *objp)
+{
+
+	 if (!xdr_remote_name (xdrs, objp))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain (XDR *xdrs, remote_domain *objp)
+{
+
+	 if (!xdr_pointer (xdrs, (char **)objp, sizeof (remote_nonnull_domain), (xdrproc_t) xdr_remote_nonnull_domain))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network (XDR *xdrs, remote_network *objp)
+{
+
+	 if (!xdr_pointer (xdrs, (char **)objp, sizeof (remote_nonnull_network), (xdrproc_t) xdr_remote_nonnull_network))
+		 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_vcpu_info (XDR *xdrs, remote_vcpu_info *objp)
+{
+
+	 if (!xdr_u_int (xdrs, &objp->number))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->state))
+		 return FALSE;
+	 if (!xdr_u_quad_t (xdrs, &objp->cpu_time))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->cpu))
+		 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_type_ret (XDR *xdrs, remote_get_type_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->type))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_get_version_ret (XDR *xdrs, remote_get_version_ret *objp)
+{
+
+	 if (!xdr_quad_t (xdrs, &objp->hv_ver))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_get_max_vcpus_args (XDR *xdrs, remote_get_max_vcpus_args *objp)
+{
+
+	 if (!xdr_remote_string (xdrs, &objp->type))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_get_max_vcpus_ret (XDR *xdrs, remote_get_max_vcpus_ret *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->max_vcpus))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_node_get_info_ret (XDR *xdrs, remote_node_get_info_ret *objp)
+{
+	register int32_t *buf;
+
+
+	if (xdrs->x_op == XDR_ENCODE) {
+		 if (!xdr_vector (xdrs, (char *)objp->model, 32,
+			sizeof (char), (xdrproc_t) xdr_char))
+			 return FALSE;
+		 if (!xdr_quad_t (xdrs, &objp->memory))
+			 return FALSE;
+		buf = XDR_INLINE (xdrs, 6 * BYTES_PER_XDR_UNIT);
+		if (buf == NULL) {
+			 if (!xdr_int (xdrs, &objp->cpus))
+				 return FALSE;
+			 if (!xdr_int (xdrs, &objp->mhz))
+				 return FALSE;
+			 if (!xdr_int (xdrs, &objp->nodes))
+				 return FALSE;
+			 if (!xdr_int (xdrs, &objp->sockets))
+				 return FALSE;
+			 if (!xdr_int (xdrs, &objp->cores))
+				 return FALSE;
+			 if (!xdr_int (xdrs, &objp->threads))
+				 return FALSE;
+		} else {
+			(void)IXDR_PUT_INT32(buf, objp->cpus);
+			(void)IXDR_PUT_INT32(buf, objp->mhz);
+			(void)IXDR_PUT_INT32(buf, objp->nodes);
+			(void)IXDR_PUT_INT32(buf, objp->sockets);
+			(void)IXDR_PUT_INT32(buf, objp->cores);
+			(void)IXDR_PUT_INT32(buf, objp->threads);
+		}
+		return TRUE;
+	} else if (xdrs->x_op == XDR_DECODE) {
+		 if (!xdr_vector (xdrs, (char *)objp->model, 32,
+			sizeof (char), (xdrproc_t) xdr_char))
+			 return FALSE;
+		 if (!xdr_quad_t (xdrs, &objp->memory))
+			 return FALSE;
+		buf = XDR_INLINE (xdrs, 6 * BYTES_PER_XDR_UNIT);
+		if (buf == NULL) {
+			 if (!xdr_int (xdrs, &objp->cpus))
+				 return FALSE;
+			 if (!xdr_int (xdrs, &objp->mhz))
+				 return FALSE;
+			 if (!xdr_int (xdrs, &objp->nodes))
+				 return FALSE;
+			 if (!xdr_int (xdrs, &objp->sockets))
+				 return FALSE;
+			 if (!xdr_int (xdrs, &objp->cores))
+				 return FALSE;
+			 if (!xdr_int (xdrs, &objp->threads))
+				 return FALSE;
+		} else {
+			objp->cpus = IXDR_GET_LONG(buf);
+			objp->mhz = IXDR_GET_LONG(buf);
+			objp->nodes = IXDR_GET_LONG(buf);
+			objp->sockets = IXDR_GET_LONG(buf);
+			objp->cores = IXDR_GET_LONG(buf);
+			objp->threads = IXDR_GET_LONG(buf);
+		}
+	 return TRUE;
+	}
+
+	 if (!xdr_vector (xdrs, (char *)objp->model, 32,
+		sizeof (char), (xdrproc_t) xdr_char))
+		 return FALSE;
+	 if (!xdr_quad_t (xdrs, &objp->memory))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->cpus))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->mhz))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->nodes))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->sockets))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->cores))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->threads))
+		 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_list_domains_args (XDR *xdrs, remote_list_domains_args *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->maxids))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_list_domains_ret (XDR *xdrs, remote_list_domains_ret *objp)
+{
+	char *objp_cp0 = (char *) objp->ids.ids_val;
+	char **objp_cpp0 = &objp_cp0;
+
+	 if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->ids.ids_len, REMOTE_DOMAIN_ID_LIST_MAX,
+		sizeof (int), (xdrproc_t) xdr_int))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_num_of_domains_ret (XDR *xdrs, remote_num_of_domains_ret *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->num))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_create_linux_args (XDR *xdrs, remote_domain_create_linux_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->xml_desc))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->flags))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_create_linux_ret (XDR *xdrs, remote_domain_create_linux_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_lookup_by_id_args (XDR *xdrs, remote_domain_lookup_by_id_args *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->id))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_lookup_by_id_ret (XDR *xdrs, remote_domain_lookup_by_id_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_lookup_by_uuid_args (XDR *xdrs, remote_domain_lookup_by_uuid_args *objp)
+{
+
+	 if (!xdr_remote_uuid (xdrs, objp->uuid))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_lookup_by_uuid_ret (XDR *xdrs, remote_domain_lookup_by_uuid_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_lookup_by_name_args (XDR *xdrs, remote_domain_lookup_by_name_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->name))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_lookup_by_name_ret (XDR *xdrs, remote_domain_lookup_by_name_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_suspend_args (XDR *xdrs, remote_domain_suspend_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_resume_args (XDR *xdrs, remote_domain_resume_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_shutdown_args (XDR *xdrs, remote_domain_shutdown_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_reboot_args (XDR *xdrs, remote_domain_reboot_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->flags))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_destroy_args (XDR *xdrs, remote_domain_destroy_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_os_type_args (XDR *xdrs, remote_domain_get_os_type_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_os_type_ret (XDR *xdrs, remote_domain_get_os_type_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->type))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_max_memory_args (XDR *xdrs, remote_domain_get_max_memory_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_max_memory_ret (XDR *xdrs, remote_domain_get_max_memory_ret *objp)
+{
+
+	 if (!xdr_u_quad_t (xdrs, &objp->memory))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_set_max_memory_args (XDR *xdrs, remote_domain_set_max_memory_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	 if (!xdr_u_quad_t (xdrs, &objp->memory))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_set_memory_args (XDR *xdrs, remote_domain_set_memory_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	 if (!xdr_u_quad_t (xdrs, &objp->memory))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_info_args (XDR *xdrs, remote_domain_get_info_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_info_ret (XDR *xdrs, remote_domain_get_info_ret *objp)
+{
+
+	 if (!xdr_u_char (xdrs, &objp->state))
+		 return FALSE;
+	 if (!xdr_u_quad_t (xdrs, &objp->max_mem))
+		 return FALSE;
+	 if (!xdr_u_quad_t (xdrs, &objp->memory))
+		 return FALSE;
+	 if (!xdr_u_short (xdrs, &objp->nr_virt_cpu))
+		 return FALSE;
+	 if (!xdr_u_quad_t (xdrs, &objp->cpu_time))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_dump_xml_args (XDR *xdrs, remote_domain_dump_xml_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->flags))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_dump_xml_ret (XDR *xdrs, remote_domain_dump_xml_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_list_defined_domains_args (XDR *xdrs, remote_domain_list_defined_domains_args *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->maxnames))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_list_defined_domains_ret (XDR *xdrs, remote_domain_list_defined_domains_ret *objp)
+{
+	char *objp_cp0 = (char *) objp->names.names_val;
+	char **objp_cpp0 = &objp_cp0;
+
+	 if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->names.names_len, REMOTE_DOMAIN_NAME_LIST_MAX,
+		sizeof (remote_nonnull_string), (xdrproc_t) xdr_remote_nonnull_string))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_num_of_defined_domains_ret (XDR *xdrs, remote_domain_num_of_defined_domains_ret *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->num))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_create_args (XDR *xdrs, remote_domain_create_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_define_xml_args (XDR *xdrs, remote_domain_define_xml_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_define_xml_ret (XDR *xdrs, remote_domain_define_xml_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_undefine_args (XDR *xdrs, remote_domain_undefine_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_set_vcpus_args (XDR *xdrs, remote_domain_set_vcpus_args *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->nvcpus))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_pin_vcpu_args (XDR *xdrs, remote_domain_pin_vcpu_args *objp)
+{
+	char *objp_cp0 = (char *) objp->cpumap.cpumap_val;
+	char **objp_cpp0 = &objp_cp0;
+
+	 if (!xdr_int (xdrs, &objp->vcpu))
+		 return FALSE;
+	 if (!xdr_bytes (xdrs, objp_cpp0, (u_int *) &objp->cpumap.cpumap_len, REMOTE_CPUMAP_MAX))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_vcpus_args (XDR *xdrs, remote_domain_get_vcpus_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->maxinfo))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->maplen))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_vcpus_ret (XDR *xdrs, remote_domain_get_vcpus_ret *objp)
+{
+	char *objp_cp0 = (char *) objp->info.info_val;
+	char **objp_cpp0 = &objp_cp0;
+	char *objp_cp1 = (char *) objp->cpumaps.cpumaps_val;
+	char **objp_cpp1 = &objp_cp1;
+
+	 if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->info.info_len, REMOTE_VCPUINFO_MAX,
+		sizeof (remote_vcpu_info), (xdrproc_t) xdr_remote_vcpu_info))
+		 return FALSE;
+	 if (!xdr_bytes (xdrs, objp_cpp1, (u_int *) &objp->cpumaps.cpumaps_len, REMOTE_CPUMAPS_MAX))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_max_vcpus_args (XDR *xdrs, remote_domain_get_max_vcpus_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_max_vcpus_ret (XDR *xdrs, remote_domain_get_max_vcpus_ret *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->num))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_attach_device_args (XDR *xdrs, remote_domain_attach_device_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_detach_device_args (XDR *xdrs, remote_domain_detach_device_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_autostart_args (XDR *xdrs, remote_domain_get_autostart_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_get_autostart_ret (XDR *xdrs, remote_domain_get_autostart_ret *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->autostart))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_domain_set_autostart_args (XDR *xdrs, remote_domain_set_autostart_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->autostart))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_num_of_networks_ret (XDR *xdrs, remote_num_of_networks_ret *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->num))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_list_networks_args (XDR *xdrs, remote_list_networks_args *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->maxnames))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_list_networks_ret (XDR *xdrs, remote_list_networks_ret *objp)
+{
+	char *objp_cp0 = (char *) objp->names.names_val;
+	char **objp_cpp0 = &objp_cp0;
+
+	 if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->names.names_len, REMOTE_NETWORK_NAME_LIST_MAX,
+		sizeof (remote_nonnull_string), (xdrproc_t) xdr_remote_nonnull_string))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_num_of_defined_networks_ret (XDR *xdrs, remote_num_of_defined_networks_ret *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->num))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_list_defined_networks_args (XDR *xdrs, remote_list_defined_networks_args *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->maxnames))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_list_defined_networks_ret (XDR *xdrs, remote_list_defined_networks_ret *objp)
+{
+	char *objp_cp0 = (char *) objp->names.names_val;
+	char **objp_cpp0 = &objp_cp0;
+
+	 if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->names.names_len, REMOTE_NETWORK_NAME_LIST_MAX,
+		sizeof (remote_nonnull_string), (xdrproc_t) xdr_remote_nonnull_string))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_lookup_by_uuid_args (XDR *xdrs, remote_network_lookup_by_uuid_args *objp)
+{
+
+	 if (!xdr_remote_uuid (xdrs, objp->uuid))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_lookup_by_uuid_ret (XDR *xdrs, remote_network_lookup_by_uuid_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_network (xdrs, &objp->net))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_lookup_by_name_args (XDR *xdrs, remote_network_lookup_by_name_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->name))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_lookup_by_name_ret (XDR *xdrs, remote_network_lookup_by_name_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_network (xdrs, &objp->net))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_create_xml_args (XDR *xdrs, remote_network_create_xml_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_create_xml_ret (XDR *xdrs, remote_network_create_xml_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_network (xdrs, &objp->net))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_define_xml_args (XDR *xdrs, remote_network_define_xml_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_define_xml_ret (XDR *xdrs, remote_network_define_xml_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_network (xdrs, &objp->net))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_undefine_args (XDR *xdrs, remote_network_undefine_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_network (xdrs, &objp->net))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_create_args (XDR *xdrs, remote_network_create_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_network (xdrs, &objp->net))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_destroy_args (XDR *xdrs, remote_network_destroy_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_network (xdrs, &objp->net))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_dump_xml_args (XDR *xdrs, remote_network_dump_xml_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_network (xdrs, &objp->net))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->flags))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_dump_xml_ret (XDR *xdrs, remote_network_dump_xml_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->xml))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_get_bridge_name_args (XDR *xdrs, remote_network_get_bridge_name_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_network (xdrs, &objp->net))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_get_bridge_name_ret (XDR *xdrs, remote_network_get_bridge_name_ret *objp)
+{
+
+	 if (!xdr_remote_nonnull_string (xdrs, &objp->name))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_get_autostart_args (XDR *xdrs, remote_network_get_autostart_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_network (xdrs, &objp->net))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_get_autostart_ret (XDR *xdrs, remote_network_get_autostart_ret *objp)
+{
+
+	 if (!xdr_int (xdrs, &objp->autostart))
+		 return FALSE;
+	return TRUE;
+}
+
+bool_t
+xdr_remote_network_set_autostart_args (XDR *xdrs, remote_network_set_autostart_args *objp)
+{
+
+	 if (!xdr_remote_nonnull_network (xdrs, &objp->net))
+		 return FALSE;
+	 if (!xdr_int (xdrs, &objp->autostart))
+		 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-05-01 12:34:13.000000000 +0100
@@ -0,0 +1,717 @@
+/*
+ * 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;
+#define REMOTE_DOMAIN_ID_LIST_MAX 16384
+#define REMOTE_DOMAIN_NAME_LIST_MAX 1024
+#define REMOTE_CPUMAP_MAX 256
+#define REMOTE_VCPUINFO_MAX 2048
+#define REMOTE_CPUMAPS_MAX 16384
+#define REMOTE_NETWORK_NAME_LIST_MAX 256
+
+typedef char remote_uuid[VIR_UUID_BUFLEN];
+
+struct remote_name {
+	remote_nonnull_string name;
+	remote_uuid uuid;
+};
+typedef struct remote_name remote_name;
+
+typedef remote_name remote_nonnull_domain;
+
+typedef remote_name remote_nonnull_network;
+
+typedef remote_nonnull_domain *remote_domain;
+
+typedef remote_nonnull_network *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_vcpu_info {
+	u_int number;
+	int state;
+	u_quad_t cpu_time;
+	int cpu;
+};
+typedef struct remote_vcpu_info remote_vcpu_info;
+
+struct remote_open_args {
+	remote_string name;
+	int flags;
+};
+typedef struct remote_open_args remote_open_args;
+
+struct remote_get_type_ret {
+	remote_nonnull_string type;
+};
+typedef struct remote_get_type_ret remote_get_type_ret;
+
+struct remote_get_version_ret {
+	quad_t hv_ver;
+};
+typedef struct remote_get_version_ret remote_get_version_ret;
+
+struct remote_get_max_vcpus_args {
+	remote_string type;
+};
+typedef struct remote_get_max_vcpus_args remote_get_max_vcpus_args;
+
+struct remote_get_max_vcpus_ret {
+	int max_vcpus;
+};
+typedef struct remote_get_max_vcpus_ret remote_get_max_vcpus_ret;
+
+struct remote_node_get_info_ret {
+	char model[32];
+	quad_t memory;
+	int cpus;
+	int mhz;
+	int nodes;
+	int sockets;
+	int cores;
+	int threads;
+};
+typedef struct remote_node_get_info_ret remote_node_get_info_ret;
+
+struct remote_get_capabilities_ret {
+	remote_nonnull_string capabilities;
+};
+typedef struct remote_get_capabilities_ret remote_get_capabilities_ret;
+
+struct remote_list_domains_args {
+	int maxids;
+};
+typedef struct remote_list_domains_args remote_list_domains_args;
+
+struct remote_list_domains_ret {
+	struct {
+		u_int ids_len;
+		int *ids_val;
+	} ids;
+};
+typedef struct remote_list_domains_ret remote_list_domains_ret;
+
+struct remote_num_of_domains_ret {
+	int num;
+};
+typedef struct remote_num_of_domains_ret remote_num_of_domains_ret;
+
+struct remote_domain_create_linux_args {
+	remote_nonnull_string xml_desc;
+	int flags;
+};
+typedef struct remote_domain_create_linux_args remote_domain_create_linux_args;
+
+struct remote_domain_create_linux_ret {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_create_linux_ret remote_domain_create_linux_ret;
+
+struct remote_domain_lookup_by_id_args {
+	int id;
+};
+typedef struct remote_domain_lookup_by_id_args remote_domain_lookup_by_id_args;
+
+struct remote_domain_lookup_by_id_ret {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_lookup_by_id_ret remote_domain_lookup_by_id_ret;
+
+struct remote_domain_lookup_by_uuid_args {
+	remote_uuid uuid;
+};
+typedef struct remote_domain_lookup_by_uuid_args remote_domain_lookup_by_uuid_args;
+
+struct remote_domain_lookup_by_uuid_ret {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_lookup_by_uuid_ret remote_domain_lookup_by_uuid_ret;
+
+struct remote_domain_lookup_by_name_args {
+	remote_nonnull_string name;
+};
+typedef struct remote_domain_lookup_by_name_args remote_domain_lookup_by_name_args;
+
+struct remote_domain_lookup_by_name_ret {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_lookup_by_name_ret remote_domain_lookup_by_name_ret;
+
+struct remote_domain_suspend_args {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_suspend_args remote_domain_suspend_args;
+
+struct remote_domain_resume_args {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_resume_args remote_domain_resume_args;
+
+struct remote_domain_shutdown_args {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_shutdown_args remote_domain_shutdown_args;
+
+struct remote_domain_reboot_args {
+	remote_nonnull_domain dom;
+	int flags;
+};
+typedef struct remote_domain_reboot_args remote_domain_reboot_args;
+
+struct remote_domain_destroy_args {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_destroy_args remote_domain_destroy_args;
+
+struct remote_domain_get_os_type_args {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_get_os_type_args remote_domain_get_os_type_args;
+
+struct remote_domain_get_os_type_ret {
+	remote_nonnull_string type;
+};
+typedef struct remote_domain_get_os_type_ret remote_domain_get_os_type_ret;
+
+struct remote_domain_get_max_memory_args {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_get_max_memory_args remote_domain_get_max_memory_args;
+
+struct remote_domain_get_max_memory_ret {
+	u_quad_t memory;
+};
+typedef struct remote_domain_get_max_memory_ret remote_domain_get_max_memory_ret;
+
+struct remote_domain_set_max_memory_args {
+	remote_nonnull_domain dom;
+	u_quad_t memory;
+};
+typedef struct remote_domain_set_max_memory_args remote_domain_set_max_memory_args;
+
+struct remote_domain_set_memory_args {
+	remote_nonnull_domain dom;
+	u_quad_t memory;
+};
+typedef struct remote_domain_set_memory_args remote_domain_set_memory_args;
+
+struct remote_domain_get_info_args {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_get_info_args remote_domain_get_info_args;
+
+struct remote_domain_get_info_ret {
+	u_char state;
+	u_quad_t max_mem;
+	u_quad_t memory;
+	u_short nr_virt_cpu;
+	u_quad_t cpu_time;
+};
+typedef struct remote_domain_get_info_ret remote_domain_get_info_ret;
+
+struct remote_domain_dump_xml_args {
+	remote_nonnull_domain dom;
+	int flags;
+};
+typedef struct remote_domain_dump_xml_args remote_domain_dump_xml_args;
+
+struct remote_domain_dump_xml_ret {
+	remote_nonnull_string xml;
+};
+typedef struct remote_domain_dump_xml_ret remote_domain_dump_xml_ret;
+
+struct remote_domain_list_defined_domains_args {
+	int maxnames;
+};
+typedef struct remote_domain_list_defined_domains_args remote_domain_list_defined_domains_args;
+
+struct remote_domain_list_defined_domains_ret {
+	struct {
+		u_int names_len;
+		remote_nonnull_string *names_val;
+	} names;
+};
+typedef struct remote_domain_list_defined_domains_ret remote_domain_list_defined_domains_ret;
+
+struct remote_domain_num_of_defined_domains_ret {
+	int num;
+};
+typedef struct remote_domain_num_of_defined_domains_ret remote_domain_num_of_defined_domains_ret;
+
+struct remote_domain_create_args {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_create_args remote_domain_create_args;
+
+struct remote_domain_define_xml_args {
+	remote_nonnull_string xml;
+};
+typedef struct remote_domain_define_xml_args remote_domain_define_xml_args;
+
+struct remote_domain_define_xml_ret {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_define_xml_ret remote_domain_define_xml_ret;
+
+struct remote_domain_undefine_args {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_undefine_args remote_domain_undefine_args;
+
+struct remote_domain_set_vcpus_args {
+	int nvcpus;
+};
+typedef struct remote_domain_set_vcpus_args remote_domain_set_vcpus_args;
+
+struct remote_domain_pin_vcpu_args {
+	int vcpu;
+	struct {
+		u_int cpumap_len;
+		char *cpumap_val;
+	} cpumap;
+};
+typedef struct remote_domain_pin_vcpu_args remote_domain_pin_vcpu_args;
+
+struct remote_domain_get_vcpus_args {
+	remote_nonnull_domain dom;
+	int maxinfo;
+	int maplen;
+};
+typedef struct remote_domain_get_vcpus_args remote_domain_get_vcpus_args;
+
+struct remote_domain_get_vcpus_ret {
+	struct {
+		u_int info_len;
+		remote_vcpu_info *info_val;
+	} info;
+	struct {
+		u_int cpumaps_len;
+		char *cpumaps_val;
+	} cpumaps;
+};
+typedef struct remote_domain_get_vcpus_ret remote_domain_get_vcpus_ret;
+
+struct remote_domain_get_max_vcpus_args {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_get_max_vcpus_args remote_domain_get_max_vcpus_args;
+
+struct remote_domain_get_max_vcpus_ret {
+	int num;
+};
+typedef struct remote_domain_get_max_vcpus_ret remote_domain_get_max_vcpus_ret;
+
+struct remote_domain_attach_device_args {
+	remote_nonnull_domain dom;
+	remote_nonnull_string xml;
+};
+typedef struct remote_domain_attach_device_args remote_domain_attach_device_args;
+
+struct remote_domain_detach_device_args {
+	remote_nonnull_domain dom;
+	remote_nonnull_string xml;
+};
+typedef struct remote_domain_detach_device_args remote_domain_detach_device_args;
+
+struct remote_domain_get_autostart_args {
+	remote_nonnull_domain dom;
+};
+typedef struct remote_domain_get_autostart_args remote_domain_get_autostart_args;
+
+struct remote_domain_get_autostart_ret {
+	int autostart;
+};
+typedef struct remote_domain_get_autostart_ret remote_domain_get_autostart_ret;
+
+struct remote_domain_set_autostart_args {
+	remote_nonnull_domain dom;
+	int autostart;
+};
+typedef struct remote_domain_set_autostart_args remote_domain_set_autostart_args;
+
+struct remote_num_of_networks_ret {
+	int num;
+};
+typedef struct remote_num_of_networks_ret remote_num_of_networks_ret;
+
+struct remote_list_networks_args {
+	int maxnames;
+};
+typedef struct remote_list_networks_args remote_list_networks_args;
+
+struct remote_list_networks_ret {
+	struct {
+		u_int names_len;
+		remote_nonnull_string *names_val;
+	} names;
+};
+typedef struct remote_list_networks_ret remote_list_networks_ret;
+
+struct remote_num_of_defined_networks_ret {
+	int num;
+};
+typedef struct remote_num_of_defined_networks_ret remote_num_of_defined_networks_ret;
+
+struct remote_list_defined_networks_args {
+	int maxnames;
+};
+typedef struct remote_list_defined_networks_args remote_list_defined_networks_args;
+
+struct remote_list_defined_networks_ret {
+	struct {
+		u_int names_len;
+		remote_nonnull_string *names_val;
+	} names;
+};
+typedef struct remote_list_defined_networks_ret remote_list_defined_networks_ret;
+
+struct remote_network_lookup_by_uuid_args {
+	remote_uuid uuid;
+};
+typedef struct remote_network_lookup_by_uuid_args remote_network_lookup_by_uuid_args;
+
+struct remote_network_lookup_by_uuid_ret {
+	remote_nonnull_network net;
+};
+typedef struct remote_network_lookup_by_uuid_ret remote_network_lookup_by_uuid_ret;
+
+struct remote_network_lookup_by_name_args {
+	remote_nonnull_string name;
+};
+typedef struct remote_network_lookup_by_name_args remote_network_lookup_by_name_args;
+
+struct remote_network_lookup_by_name_ret {
+	remote_nonnull_network net;
+};
+typedef struct remote_network_lookup_by_name_ret remote_network_lookup_by_name_ret;
+
+struct remote_network_create_xml_args {
+	remote_nonnull_string xml;
+};
+typedef struct remote_network_create_xml_args remote_network_create_xml_args;
+
+struct remote_network_create_xml_ret {
+	remote_nonnull_network net;
+};
+typedef struct remote_network_create_xml_ret remote_network_create_xml_ret;
+
+struct remote_network_define_xml_args {
+	remote_nonnull_string xml;
+};
+typedef struct remote_network_define_xml_args remote_network_define_xml_args;
+
+struct remote_network_define_xml_ret {
+	remote_nonnull_network net;
+};
+typedef struct remote_network_define_xml_ret remote_network_define_xml_ret;
+
+struct remote_network_undefine_args {
+	remote_nonnull_network net;
+};
+typedef struct remote_network_undefine_args remote_network_undefine_args;
+
+struct remote_network_create_args {
+	remote_nonnull_network net;
+};
+typedef struct remote_network_create_args remote_network_create_args;
+
+struct remote_network_destroy_args {
+	remote_nonnull_network net;
+};
+typedef struct remote_network_destroy_args remote_network_destroy_args;
+
+struct remote_network_dump_xml_args {
+	remote_nonnull_network net;
+	int flags;
+};
+typedef struct remote_network_dump_xml_args remote_network_dump_xml_args;
+
+struct remote_network_dump_xml_ret {
+	remote_nonnull_string xml;
+};
+typedef struct remote_network_dump_xml_ret remote_network_dump_xml_ret;
+
+struct remote_network_get_bridge_name_args {
+	remote_nonnull_network net;
+};
+typedef struct remote_network_get_bridge_name_args remote_network_get_bridge_name_args;
+
+struct remote_network_get_bridge_name_ret {
+	remote_nonnull_string name;
+};
+typedef struct remote_network_get_bridge_name_ret remote_network_get_bridge_name_ret;
+
+struct remote_network_get_autostart_args {
+	remote_nonnull_network net;
+};
+typedef struct remote_network_get_autostart_args remote_network_get_autostart_args;
+
+struct remote_network_get_autostart_ret {
+	int autostart;
+};
+typedef struct remote_network_get_autostart_ret remote_network_get_autostart_ret;
+
+struct remote_network_set_autostart_args {
+	remote_nonnull_network net;
+	int autostart;
+};
+typedef struct remote_network_set_autostart_args remote_network_set_autostart_args;
+#define REMOTE_PROGRAM 0x20008086
+#define REMOTE_PROTOCOL_VERSION 1
+
+enum remote_procedure {
+	REMOTE_PROC_OPEN = 1,
+	REMOTE_PROC_CLOSE = 2,
+	REMOTE_PROC_TYPE = 3,
+	REMOTE_PROC_VERSION = 4,
+	REMOTE_PROC_GET_MAX_VCPUS = 5,
+	REMOTE_PROC_NODE_GET_INFO = 6,
+	REMOTE_PROC_GET_CAPABILITIES = 7,
+};
+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_uuid (XDR *, remote_uuid);
+extern  bool_t xdr_remote_name (XDR *, remote_name*);
+extern  bool_t xdr_remote_nonnull_domain (XDR *, remote_nonnull_domain*);
+extern  bool_t xdr_remote_nonnull_network (XDR *, remote_nonnull_network*);
+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_vcpu_info (XDR *, remote_vcpu_info*);
+extern  bool_t xdr_remote_open_args (XDR *, remote_open_args*);
+extern  bool_t xdr_remote_get_type_ret (XDR *, remote_get_type_ret*);
+extern  bool_t xdr_remote_get_version_ret (XDR *, remote_get_version_ret*);
+extern  bool_t xdr_remote_get_max_vcpus_args (XDR *, remote_get_max_vcpus_args*);
+extern  bool_t xdr_remote_get_max_vcpus_ret (XDR *, remote_get_max_vcpus_ret*);
+extern  bool_t xdr_remote_node_get_info_ret (XDR *, remote_node_get_info_ret*);
+extern  bool_t xdr_remote_get_capabilities_ret (XDR *, remote_get_capabilities_ret*);
+extern  bool_t xdr_remote_list_domains_args (XDR *, remote_list_domains_args*);
+extern  bool_t xdr_remote_list_domains_ret (XDR *, remote_list_domains_ret*);
+extern  bool_t xdr_remote_num_of_domains_ret (XDR *, remote_num_of_domains_ret*);
+extern  bool_t xdr_remote_domain_create_linux_args (XDR *, remote_domain_create_linux_args*);
+extern  bool_t xdr_remote_domain_create_linux_ret (XDR *, remote_domain_create_linux_ret*);
+extern  bool_t xdr_remote_domain_lookup_by_id_args (XDR *, remote_domain_lookup_by_id_args*);
+extern  bool_t xdr_remote_domain_lookup_by_id_ret (XDR *, remote_domain_lookup_by_id_ret*);
+extern  bool_t xdr_remote_domain_lookup_by_uuid_args (XDR *, remote_domain_lookup_by_uuid_args*);
+extern  bool_t xdr_remote_domain_lookup_by_uuid_ret (XDR *, remote_domain_lookup_by_uuid_ret*);
+extern  bool_t xdr_remote_domain_lookup_by_name_args (XDR *, remote_domain_lookup_by_name_args*);
+extern  bool_t xdr_remote_domain_lookup_by_name_ret (XDR *, remote_domain_lookup_by_name_ret*);
+extern  bool_t xdr_remote_domain_suspend_args (XDR *, remote_domain_suspend_args*);
+extern  bool_t xdr_remote_domain_resume_args (XDR *, remote_domain_resume_args*);
+extern  bool_t xdr_remote_domain_shutdown_args (XDR *, remote_domain_shutdown_args*);
+extern  bool_t xdr_remote_domain_reboot_args (XDR *, remote_domain_reboot_args*);
+extern  bool_t xdr_remote_domain_destroy_args (XDR *, remote_domain_destroy_args*);
+extern  bool_t xdr_remote_domain_get_os_type_args (XDR *, remote_domain_get_os_type_args*);
+extern  bool_t xdr_remote_domain_get_os_type_ret (XDR *, remote_domain_get_os_type_ret*);
+extern  bool_t xdr_remote_domain_get_max_memory_args (XDR *, remote_domain_get_max_memory_args*);
+extern  bool_t xdr_remote_domain_get_max_memory_ret (XDR *, remote_domain_get_max_memory_ret*);
+extern  bool_t xdr_remote_domain_set_max_memory_args (XDR *, remote_domain_set_max_memory_args*);
+extern  bool_t xdr_remote_domain_set_memory_args (XDR *, remote_domain_set_memory_args*);
+extern  bool_t xdr_remote_domain_get_info_args (XDR *, remote_domain_get_info_args*);
+extern  bool_t xdr_remote_domain_get_info_ret (XDR *, remote_domain_get_info_ret*);
+extern  bool_t xdr_remote_domain_dump_xml_args (XDR *, remote_domain_dump_xml_args*);
+extern  bool_t xdr_remote_domain_dump_xml_ret (XDR *, remote_domain_dump_xml_ret*);
+extern  bool_t xdr_remote_domain_list_defined_domains_args (XDR *, remote_domain_list_defined_domains_args*);
+extern  bool_t xdr_remote_domain_list_defined_domains_ret (XDR *, remote_domain_list_defined_domains_ret*);
+extern  bool_t xdr_remote_domain_num_of_defined_domains_ret (XDR *, remote_domain_num_of_defined_domains_ret*);
+extern  bool_t xdr_remote_domain_create_args (XDR *, remote_domain_create_args*);
+extern  bool_t xdr_remote_domain_define_xml_args (XDR *, remote_domain_define_xml_args*);
+extern  bool_t xdr_remote_domain_define_xml_ret (XDR *, remote_domain_define_xml_ret*);
+extern  bool_t xdr_remote_domain_undefine_args (XDR *, remote_domain_undefine_args*);
+extern  bool_t xdr_remote_domain_set_vcpus_args (XDR *, remote_domain_set_vcpus_args*);
+extern  bool_t xdr_remote_domain_pin_vcpu_args (XDR *, remote_domain_pin_vcpu_args*);
+extern  bool_t xdr_remote_domain_get_vcpus_args (XDR *, remote_domain_get_vcpus_args*);
+extern  bool_t xdr_remote_domain_get_vcpus_ret (XDR *, remote_domain_get_vcpus_ret*);
+extern  bool_t xdr_remote_domain_get_max_vcpus_args (XDR *, remote_domain_get_max_vcpus_args*);
+extern  bool_t xdr_remote_domain_get_max_vcpus_ret (XDR *, remote_domain_get_max_vcpus_ret*);
+extern  bool_t xdr_remote_domain_attach_device_args (XDR *, remote_domain_attach_device_args*);
+extern  bool_t xdr_remote_domain_detach_device_args (XDR *, remote_domain_detach_device_args*);
+extern  bool_t xdr_remote_domain_get_autostart_args (XDR *, remote_domain_get_autostart_args*);
+extern  bool_t xdr_remote_domain_get_autostart_ret (XDR *, remote_domain_get_autostart_ret*);
+extern  bool_t xdr_remote_domain_set_autostart_args (XDR *, remote_domain_set_autostart_args*);
+extern  bool_t xdr_remote_num_of_networks_ret (XDR *, remote_num_of_networks_ret*);
+extern  bool_t xdr_remote_list_networks_args (XDR *, remote_list_networks_args*);
+extern  bool_t xdr_remote_list_networks_ret (XDR *, remote_list_networks_ret*);
+extern  bool_t xdr_remote_num_of_defined_networks_ret (XDR *, remote_num_of_defined_networks_ret*);
+extern  bool_t xdr_remote_list_defined_networks_args (XDR *, remote_list_defined_networks_args*);
+extern  bool_t xdr_remote_list_defined_networks_ret (XDR *, remote_list_defined_networks_ret*);
+extern  bool_t xdr_remote_network_lookup_by_uuid_args (XDR *, remote_network_lookup_by_uuid_args*);
+extern  bool_t xdr_remote_network_lookup_by_uuid_ret (XDR *, remote_network_lookup_by_uuid_ret*);
+extern  bool_t xdr_remote_network_lookup_by_name_args (XDR *, remote_network_lookup_by_name_args*);
+extern  bool_t xdr_remote_network_lookup_by_name_ret (XDR *, remote_network_lookup_by_name_ret*);
+extern  bool_t xdr_remote_network_create_xml_args (XDR *, remote_network_create_xml_args*);
+extern  bool_t xdr_remote_network_create_xml_ret (XDR *, remote_network_create_xml_ret*);
+extern  bool_t xdr_remote_network_define_xml_args (XDR *, remote_network_define_xml_args*);
+extern  bool_t xdr_remote_network_define_xml_ret (XDR *, remote_network_define_xml_ret*);
+extern  bool_t xdr_remote_network_undefine_args (XDR *, remote_network_undefine_args*);
+extern  bool_t xdr_remote_network_create_args (XDR *, remote_network_create_args*);
+extern  bool_t xdr_remote_network_destroy_args (XDR *, remote_network_destroy_args*);
+extern  bool_t xdr_remote_network_dump_xml_args (XDR *, remote_network_dump_xml_args*);
+extern  bool_t xdr_remote_network_dump_xml_ret (XDR *, remote_network_dump_xml_ret*);
+extern  bool_t xdr_remote_network_get_bridge_name_args (XDR *, remote_network_get_bridge_name_args*);
+extern  bool_t xdr_remote_network_get_bridge_name_ret (XDR *, remote_network_get_bridge_name_ret*);
+extern  bool_t xdr_remote_network_get_autostart_args (XDR *, remote_network_get_autostart_args*);
+extern  bool_t xdr_remote_network_get_autostart_ret (XDR *, remote_network_get_autostart_ret*);
+extern  bool_t xdr_remote_network_set_autostart_args (XDR *, remote_network_set_autostart_args*);
+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_uuid ();
+extern bool_t xdr_remote_name ();
+extern bool_t xdr_remote_nonnull_domain ();
+extern bool_t xdr_remote_nonnull_network ();
+extern bool_t xdr_remote_domain ();
+extern bool_t xdr_remote_network ();
+extern bool_t xdr_remote_error ();
+extern bool_t xdr_remote_vcpu_info ();
+extern bool_t xdr_remote_open_args ();
+extern bool_t xdr_remote_get_type_ret ();
+extern bool_t xdr_remote_get_version_ret ();
+extern bool_t xdr_remote_get_max_vcpus_args ();
+extern bool_t xdr_remote_get_max_vcpus_ret ();
+extern bool_t xdr_remote_node_get_info_ret ();
+extern bool_t xdr_remote_get_capabilities_ret ();
+extern bool_t xdr_remote_list_domains_args ();
+extern bool_t xdr_remote_list_domains_ret ();
+extern bool_t xdr_remote_num_of_domains_ret ();
+extern bool_t xdr_remote_domain_create_linux_args ();
+extern bool_t xdr_remote_domain_create_linux_ret ();
+extern bool_t xdr_remote_domain_lookup_by_id_args ();
+extern bool_t xdr_remote_domain_lookup_by_id_ret ();
+extern bool_t xdr_remote_domain_lookup_by_uuid_args ();
+extern bool_t xdr_remote_domain_lookup_by_uuid_ret ();
+extern bool_t xdr_remote_domain_lookup_by_name_args ();
+extern bool_t xdr_remote_domain_lookup_by_name_ret ();
+extern bool_t xdr_remote_domain_suspend_args ();
+extern bool_t xdr_remote_domain_resume_args ();
+extern bool_t xdr_remote_domain_shutdown_args ();
+extern bool_t xdr_remote_domain_reboot_args ();
+extern bool_t xdr_remote_domain_destroy_args ();
+extern bool_t xdr_remote_domain_get_os_type_args ();
+extern bool_t xdr_remote_domain_get_os_type_ret ();
+extern bool_t xdr_remote_domain_get_max_memory_args ();
+extern bool_t xdr_remote_domain_get_max_memory_ret ();
+extern bool_t xdr_remote_domain_set_max_memory_args ();
+extern bool_t xdr_remote_domain_set_memory_args ();
+extern bool_t xdr_remote_domain_get_info_args ();
+extern bool_t xdr_remote_domain_get_info_ret ();
+extern bool_t xdr_remote_domain_dump_xml_args ();
+extern bool_t xdr_remote_domain_dump_xml_ret ();
+extern bool_t xdr_remote_domain_list_defined_domains_args ();
+extern bool_t xdr_remote_domain_list_defined_domains_ret ();
+extern bool_t xdr_remote_domain_num_of_defined_domains_ret ();
+extern bool_t xdr_remote_domain_create_args ();
+extern bool_t xdr_remote_domain_define_xml_args ();
+extern bool_t xdr_remote_domain_define_xml_ret ();
+extern bool_t xdr_remote_domain_undefine_args ();
+extern bool_t xdr_remote_domain_set_vcpus_args ();
+extern bool_t xdr_remote_domain_pin_vcpu_args ();
+extern bool_t xdr_remote_domain_get_vcpus_args ();
+extern bool_t xdr_remote_domain_get_vcpus_ret ();
+extern bool_t xdr_remote_domain_get_max_vcpus_args ();
+extern bool_t xdr_remote_domain_get_max_vcpus_ret ();
+extern bool_t xdr_remote_domain_attach_device_args ();
+extern bool_t xdr_remote_domain_detach_device_args ();
+extern bool_t xdr_remote_domain_get_autostart_args ();
+extern bool_t xdr_remote_domain_get_autostart_ret ();
+extern bool_t xdr_remote_domain_set_autostart_args ();
+extern bool_t xdr_remote_num_of_networks_ret ();
+extern bool_t xdr_remote_list_networks_args ();
+extern bool_t xdr_remote_list_networks_ret ();
+extern bool_t xdr_remote_num_of_defined_networks_ret ();
+extern bool_t xdr_remote_list_defined_networks_args ();
+extern bool_t xdr_remote_list_defined_networks_ret ();
+extern bool_t xdr_remote_network_lookup_by_uuid_args ();
+extern bool_t xdr_remote_network_lookup_by_uuid_ret ();
+extern bool_t xdr_remote_network_lookup_by_name_args ();
+extern bool_t xdr_remote_network_lookup_by_name_ret ();
+extern bool_t xdr_remote_network_create_xml_args ();
+extern bool_t xdr_remote_network_create_xml_ret ();
+extern bool_t xdr_remote_network_define_xml_args ();
+extern bool_t xdr_remote_network_define_xml_ret ();
+extern bool_t xdr_remote_network_undefine_args ();
+extern bool_t xdr_remote_network_create_args ();
+extern bool_t xdr_remote_network_destroy_args ();
+extern bool_t xdr_remote_network_dump_xml_args ();
+extern bool_t xdr_remote_network_dump_xml_ret ();
+extern bool_t xdr_remote_network_get_bridge_name_args ();
+extern bool_t xdr_remote_network_get_bridge_name_ret ();
+extern bool_t xdr_remote_network_get_autostart_args ();
+extern bool_t xdr_remote_network_get_autostart_ret ();
+extern bool_t xdr_remote_network_set_autostart_args ();
+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-05-01 12:33:57.000000000 +0100
@@ -0,0 +1,545 @@
+/* -*- 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 redhat com>
+ */
+
+/* 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;
+
+/* This just places an upper limit on the length of lists of
+ * domain IDs which may be sent via the protocol.
+ */
+const REMOTE_DOMAIN_ID_LIST_MAX = 16384;
+
+/* Upper limit on lists of domain names. */
+const REMOTE_DOMAIN_NAME_LIST_MAX = 1024;
+
+/* Upper limit on cpumap (bytes) passed to virDomainPinVcpu. */
+const REMOTE_CPUMAP_MAX = 256;
+
+/* Upper limit on number of info fields returned by virDomainGetVcpus. */
+const REMOTE_VCPUINFO_MAX = 2048;
+
+/* Upper limit on cpumaps (bytes) passed to virDomainGetVcpus. */
+const REMOTE_CPUMAPS_MAX = 16384;
+
+/* Upper limit on lists of network names. */
+const REMOTE_NETWORK_NAME_LIST_MAX = 256;
+
+/* Domains and networks are represented on the wire by (name, UUID). */
+typedef opaque remote_uuid[VIR_UUID_BUFLEN];
+
+struct remote_name {
+    remote_nonnull_string name;
+    remote_uuid uuid;
+};
+
+/* A domain or network which may not be NULL. */
+typedef struct remote_name remote_nonnull_domain;
+typedef struct remote_name remote_nonnull_network;
+
+/* A domain or network which may be NULL. */
+typedef remote_nonnull_domain *remote_domain;
+typedef remote_nonnull_network *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;
+};
+
+/* Wire encoding of virVcpuInfo. */
+struct remote_vcpu_info {
+    unsigned int number;
+    int state;
+    unsigned hyper cpu_time;
+    int cpu;
+};
+
+/*----- Calls. -----*/
+
+/* For each call we may have a 'remote_CALL_args' and 'remote_CALL_ret'
+ * type.  These are omitted when they are void.  The virConnectPtr
+ * is not passed at all (it is inferred on the remote server from the
+ * connection).  Errors are returned implicitly in the RPC protocol.
+ */
+
+struct remote_open_args {
+    /* NB. "name" might be NULL although in practice you can't
+     * yet do that using the remote_internal driver.
+     */
+    remote_string name;
+    int flags;
+};
+
+struct remote_get_type_ret {
+    remote_nonnull_string type;
+};
+
+struct remote_get_version_ret {
+    hyper hv_ver;
+};
+
+struct remote_get_max_vcpus_args {
+    /* The only backend which supports this call is Xen HV, and
+     * there the type is ignored so it could be NULL.
+     */
+    remote_string type;
+};
+
+struct remote_get_max_vcpus_ret {
+    int max_vcpus;
+};
+
+struct remote_node_get_info_ret {
+    char model[32];
+    hyper memory;
+    int cpus;
+    int mhz;
+    int nodes;
+    int sockets;
+    int cores;
+    int threads;
+};
+
+struct remote_get_capabilities_ret {
+    remote_nonnull_string capabilities;
+};
+
+struct remote_list_domains_args {
+    int maxids;
+};
+
+struct remote_list_domains_ret {
+    int ids<REMOTE_DOMAIN_ID_LIST_MAX>;
+};
+
+struct remote_num_of_domains_ret {
+    int num;
+};
+
+struct remote_domain_create_linux_args {
+    remote_nonnull_string xml_desc;
+    int flags;
+};
+
+struct remote_domain_create_linux_ret {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_lookup_by_id_args {
+    int id;
+};
+
+struct remote_domain_lookup_by_id_ret {
+    /* XXX "Not found" semantic is ill-defined. */
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_lookup_by_uuid_args {
+    remote_uuid uuid;
+};
+
+struct remote_domain_lookup_by_uuid_ret {
+    /* XXX "Not found" semantic is ill-defined. */
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_lookup_by_name_args {
+    remote_nonnull_string name;
+};
+
+struct remote_domain_lookup_by_name_ret {
+    /* XXX "Not found" semantic is ill-defined. */
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_suspend_args {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_resume_args {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_shutdown_args {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_reboot_args {
+    remote_nonnull_domain dom;
+    int flags;
+};
+
+struct remote_domain_destroy_args {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_get_os_type_args {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_get_os_type_ret {
+    remote_nonnull_string type;
+};
+
+struct remote_domain_get_max_memory_args {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_get_max_memory_ret {
+    unsigned hyper memory;
+};
+
+struct remote_domain_set_max_memory_args {
+    remote_nonnull_domain dom;
+    unsigned hyper memory;
+};
+
+struct remote_domain_set_memory_args {
+    remote_nonnull_domain dom;
+    unsigned hyper memory;
+};
+
+struct remote_domain_get_info_args {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_get_info_ret {
+    unsigned char state;
+    unsigned hyper max_mem;
+    unsigned hyper memory;
+    unsigned short nr_virt_cpu;
+    /* XXX cpu_time is declared as unsigned long long */
+    unsigned hyper cpu_time;
+};
+
+/* XXX Save, Restore, CoreDump not yet implemented because we
+ * don't know where we will write the images.
+ */
+
+struct remote_domain_dump_xml_args {
+    remote_nonnull_domain dom;
+    int flags;
+};
+
+struct remote_domain_dump_xml_ret {
+    remote_nonnull_string xml;
+};
+
+struct remote_domain_list_defined_domains_args {
+    int maxnames;
+};
+
+struct remote_domain_list_defined_domains_ret {
+    remote_nonnull_string names<REMOTE_DOMAIN_NAME_LIST_MAX>;
+};
+
+struct remote_domain_num_of_defined_domains_ret {
+    int num;
+};
+
+struct remote_domain_create_args {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_define_xml_args {
+    remote_nonnull_string xml;
+};
+
+struct remote_domain_define_xml_ret {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_undefine_args {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_set_vcpus_args {
+    int nvcpus;
+};
+
+struct remote_domain_pin_vcpu_args {
+    int vcpu;
+    opaque cpumap<REMOTE_CPUMAP_MAX>;
+};
+
+struct remote_domain_get_vcpus_args {
+    remote_nonnull_domain dom;
+    int maxinfo;
+    int maplen;
+};
+
+struct remote_domain_get_vcpus_ret {
+    remote_vcpu_info info<REMOTE_VCPUINFO_MAX>;
+    opaque cpumaps<REMOTE_CPUMAPS_MAX>;
+};
+
+struct remote_domain_get_max_vcpus_args {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_get_max_vcpus_ret {
+    int num;
+};
+
+struct remote_domain_attach_device_args {
+    remote_nonnull_domain dom;
+    remote_nonnull_string xml;
+};
+
+struct remote_domain_detach_device_args {
+    remote_nonnull_domain dom;
+    remote_nonnull_string xml;
+};
+
+struct remote_domain_get_autostart_args {
+    remote_nonnull_domain dom;
+};
+
+struct remote_domain_get_autostart_ret {
+    int autostart;
+};
+
+struct remote_domain_set_autostart_args {
+    remote_nonnull_domain dom;
+    int autostart;
+};
+
+/* Network calls: */
+
+struct remote_num_of_networks_ret {
+    int num;
+};
+
+struct remote_list_networks_args {
+    int maxnames;
+};
+
+struct remote_list_networks_ret {
+    remote_nonnull_string names<REMOTE_NETWORK_NAME_LIST_MAX>;
+};
+
+struct remote_num_of_defined_networks_ret {
+    int num;
+};
+
+struct remote_list_defined_networks_args {
+    int maxnames;
+};
+
+struct remote_list_defined_networks_ret {
+    remote_nonnull_string names<REMOTE_NETWORK_NAME_LIST_MAX>;
+};
+
+struct remote_network_lookup_by_uuid_args {
+    remote_uuid uuid;
+};
+
+struct remote_network_lookup_by_uuid_ret {
+    /* XXX "Not found" semantic is ill-defined. */
+    remote_nonnull_network net;
+};
+
+struct remote_network_lookup_by_name_args {
+    remote_nonnull_string name;
+};
+
+struct remote_network_lookup_by_name_ret {
+    /* XXX "Not found" semantic is ill-defined. */
+    remote_nonnull_network net;
+};
+
+struct remote_network_create_xml_args {
+    remote_nonnull_string xml;
+};
+
+struct remote_network_create_xml_ret {
+    remote_nonnull_network net;
+};
+
+struct remote_network_define_xml_args {
+    remote_nonnull_string xml;
+};
+
+struct remote_network_define_xml_ret {
+    remote_nonnull_network net;
+};
+
+struct remote_network_undefine_args {
+    remote_nonnull_network net;
+};
+
+struct remote_network_create_args {
+    remote_nonnull_network net;
+};
+
+struct remote_network_destroy_args {
+    remote_nonnull_network net;
+};
+
+struct remote_network_dump_xml_args {
+    remote_nonnull_network net;
+    int flags;
+};
+
+struct remote_network_dump_xml_ret {
+    remote_nonnull_string xml;
+};
+
+struct remote_network_get_bridge_name_args {
+    remote_nonnull_network net;
+};
+
+struct remote_network_get_bridge_name_ret {
+    remote_nonnull_string name;
+};
+
+struct remote_network_get_autostart_args {
+    remote_nonnull_network net;
+};
+
+struct remote_network_get_autostart_ret {
+    int autostart;
+};
+
+struct remote_network_set_autostart_args {
+    remote_nonnull_network net;
+    int autostart;
+};
+
+/*----- 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_TYPE = 3,
+    REMOTE_PROC_VERSION = 4,
+    REMOTE_PROC_GET_MAX_VCPUS = 5,
+    REMOTE_PROC_NODE_GET_INFO = 6,
+    REMOTE_PROC_GET_CAPABILITIES = 7
+};
+
+/* 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-30 17:50:10.000000000 +0100
@@ -0,0 +1,81 @@
+# 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.  Update: The IXDR_PUT_LONG replacements are
+# actually fixes for 64 bit, so this file is necessary.  Arguably
+# so is the type-punning fix.
+#
+# Copyright (C) 2007 Red Hat, Inc.
+#
+# See COPYING for the license of this software.
+#
+# Richard Jones <rjones redhat com>
+
+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.
+	my %uses = ();
+	my $i = 0;
+	foreach (@function) {
+	    $uses{$1} = $i++ if m/\(char \*\*\)\&(objp->[a-z_.]+_val)/;
+	}
+	if (keys %uses >= 1) {
+	    my $i = 1;
+
+	    foreach (keys %uses) {
+		$i = $uses{$_};
+		unshift @function,
+		("\tchar *objp_cp$i = (char *) $_;\n",
+		 "\tchar **objp_cpp$i = &objp_cp$i;\n");
+		$i++;
+	    }
+	    @function =
+		map { s{\(char \*\*\)\&(objp->[a-z_.]+_val)}
+		       {objp_cpp$uses{$1}}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-26 17:47:52.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-26 17:47:59.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-05-01 13:55:02.000000000 +0100
+++ libvirt-remote/src/driver.h	2007-04-30 18:35:49.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-05-01 13:55:02.000000000 +0100
+++ libvirt-remote/src/libvirt.c	2007-05-01 17:44:33.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
@@ -295,8 +299,8 @@
 
     for (i = 0; i < virNetworkDriverTabCount; i++) {
         res = virNetworkDriverTab[i]->open (ret, name, flags);
-        if (res == -1) goto failed;
-        else if (res == 0) {
+        if (res == VIR_DRV_OPEN_ERROR) goto failed;
+        else if (res == VIR_DRV_OPEN_SUCCESS) {
             ret->networkDriver = virNetworkDriverTab[i];
             break;
         }
@@ -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-26 17:45:57.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/proxy_internal.c libvirt-remote/src/proxy_internal.c
--- libvirt-cvs/src/proxy_internal.c	2007-05-01 13:55:02.000000000 +0100
+++ libvirt-remote/src/proxy_internal.c	2007-05-01 16:29:09.000000000 +0100
@@ -544,7 +544,7 @@
 
     fd = virProxyOpenClientSocket(PROXY_SOCKET_PATH);
     if (fd < 0) {
-	    virProxyError(conn, VIR_ERR_NO_XEN, PROXY_SOCKET_PATH);
+	    virProxyError(NULL, VIR_ERR_NO_XEN, PROXY_SOCKET_PATH);
         return(-1);
     }
     priv->proxy = fd;
@@ -554,7 +554,7 @@
     req.len = sizeof(req);
     ret = xenProxyCommand(conn, &req, NULL, 1);
     if ((ret < 0) || (req.command != VIR_PROXY_NONE)) {
-	    virProxyError(conn, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
+	    virProxyError(NULL, VIR_ERR_OPERATION_FAILED, __FUNCTION__);
         xenProxyClose(conn);
 	return(-1);
     }
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-05-01 13:55:02.000000000 +0100
+++ libvirt-remote/src/qemu_internal.c	2007-05-01 17:45:40.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:
@@ -146,7 +127,7 @@
     int ret, pid, status;
 
     if (!proxyPath) {
-        fprintf(stderr, "failed to find qemu\n");
+        qemuError (NULL, NULL, VIR_ERR_INVALID_ARG, "no proxyPath");
         return(-1);
     }
 
@@ -231,6 +212,7 @@
  retry:
     fd = socket(PF_UNIX, SOCK_STREAM, 0);
     if (fd < 0) {
+        qemuError (NULL, NULL, VIR_ERR_SYSTEM_ERROR, "socket");
         return VIR_DRV_OPEN_ERROR;
     }
 
@@ -256,12 +238,43 @@
             usleep(5000 * trials * trials);
             goto retry;
         }
+        __virRaiseError (NULL, NULL, NULL,
+                         VIR_FROM_QEMU, VIR_ERR_SYSTEM_ERROR, VIR_ERR_ERROR,
+                         "connect", NULL, NULL, errno, 0,
+                         "connect: %s: %s", path, strerror (errno));
         return VIR_DRV_OPEN_ERROR;
     }
 
     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 +283,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;
     }
 
-    if (reply->header.type != req->header.type) {
-        qemuPacketError(conn, dom, reply);
+    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;
+    }
+
+    /* 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;
 }
 
@@ -346,34 +408,43 @@
     int autostart = 0;
 
     if (uri->server != NULL) {
+        qemuError (NULL, NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__);
         return VIR_DRV_OPEN_ERROR;
     }
 
-    if (!strcmp(uri->path, "/system")) {
+    if (strcmp(uri->path, "/system") == 0) {
         if (readonly) {
             if (snprintf(path, sizeof(path), "%s/run/libvirt/qemud-sock-ro", LOCAL_STATE_DIR) >= (int)sizeof(path)) {
+                qemuError (NULL, NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
                 return VIR_DRV_OPEN_ERROR;
             }
         } else {
             if (snprintf(path, sizeof(path), "%s/run/libvirt/qemud-sock", LOCAL_STATE_DIR) >= (int)sizeof(path)) {
+                qemuError (NULL, NULL, VIR_ERR_INVALID_ARG, __FUNCTION__);
                 return VIR_DRV_OPEN_ERROR;
             }
         }
-    } else if (!strcmp(uri->path, "/session")) {
+    } else if (strcmp(uri->path, "/session") == 0) {
         struct passwd *pw;
         int uid;
 
         if ((uid = geteuid()) < 0) {
+            qemuError (NULL, NULL, VIR_ERR_SYSTEM_ERROR, "geteuid");
             return VIR_DRV_OPEN_ERROR;
         }
 
-        if (!(pw = getpwuid(uid)))
+        if (!(pw = getpwuid(uid))) {
+            qemuError (NULL, NULL, VIR_ERR_SYSTEM_ERROR, "getpwuid");
             return VIR_DRV_OPEN_ERROR;
+        }
 
         if (snprintf(path, sizeof(path), "@%s/.libvirt/qemud-sock", pw->pw_dir) == sizeof(path)) {
             return VIR_DRV_OPEN_ERROR;
         }
         autostart = 1;
+    } else {
+        qemuError (NULL, NULL, VIR_ERR_INVALID_ARG, "path should be /system or /session - for example, qemu:///session");
+        return VIR_DRV_OPEN_ERROR;
     }
     return qemuOpenClientUNIX(conn, path, autostart);
 }
@@ -395,7 +466,7 @@
 
     uri = xmlParseURI(name);
     if (uri == NULL) {
-        qemuError(conn, NULL, VIR_ERR_NO_SUPPORT, name);
+        qemuError(NULL, NULL, VIR_ERR_NO_SUPPORT, name);
         return VIR_DRV_OPEN_DECLINED;
     }
 
@@ -407,9 +478,9 @@
     }
 
     /* 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__);
+        qemuError (NULL, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__);
         return VIR_DRV_OPEN_ERROR;
     }
 
@@ -447,41 +518,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;
 }
 
@@ -489,23 +560,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;
@@ -515,40 +586,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;
@@ -558,7 +629,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;
@@ -567,46 +639,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;
@@ -616,42 +687,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;
@@ -659,20 +730,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;
@@ -697,12 +768,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;
@@ -712,12 +783,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;
@@ -728,19 +799,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;
@@ -756,29 +827,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) {
@@ -791,64 +862,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;
@@ -857,20 +929,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;
@@ -878,13 +949,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;
@@ -900,31 +971,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;
@@ -949,10 +1022,10 @@
         netpriv->qemud_fd = priv->qemud_fd;
         netpriv->shared = 1;
         conn->networkPrivateData = netpriv;
-        return 0;
+        return VIR_DRV_OPEN_SUCCESS;
     } else {
         /* Non-QEMU driver is active - open a new connection */
-        const char *drvname = geteuid() == 0 ? "qemu:///system" : "qemu://session";
+        const char *drvname = geteuid() == 0 ? "qemu:///system" : "qemu:///session";
         xmlURIPtr uri = xmlParseURI(drvname);
         int ret = qemuOpenConnection(conn, uri, flags & VIR_DRV_OPEN_RO ? 1 : 0);
         xmlFreeURI(uri);
@@ -964,7 +1037,7 @@
             netpriv->qemud_fd = ret;
             netpriv->shared = 0;
             conn->networkPrivateData = netpriv;
-            return 0;
+            return VIR_DRV_OPEN_SUCCESS;
         }
     }
 }
@@ -983,80 +1056,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;
@@ -1064,22 +1137,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;
 
@@ -1088,16 +1161,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;
@@ -1105,7 +1178,7 @@
 
     if (!(network = virGetNetwork(conn,
                                   name,
-                                  reply.data.networkLookupByNameReply.uuid)))
+                                  reply.data.qemud_packet_server_data_u.networkLookupByNameReply.uuid)))
         return NULL;
 
     return network;
@@ -1113,7 +1186,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;
@@ -1122,20 +1196,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;
@@ -1144,7 +1217,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;
@@ -1153,33 +1227,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;
@@ -1194,12 +1267,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;
@@ -1209,12 +1282,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;
@@ -1224,66 +1297,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-05-01 17:58:54.000000000 +0100
@@ -0,0 +1,1463 @@
+/*
+ * 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 redhat com>
+ */
+
+#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). */
+    char *type;                 /* Cached return from remoteType. */
+};
+
+#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 in_open, 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 (virConnectPtr conn, remote_domain domain);
+static virNetworkPtr get_network (virConnectPtr conn, remote_network network);
+#if 0
+static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain);
+static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network network);
+#endif
+
+/*----------------------------------------------------------------------*/
+
+/* 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 (NULL, 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 (NULL, 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 (NULL, 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 (NULL, 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 (NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+                continue;
+            }
+            if (connect (priv.sock, r->ai_addr, r->ai_addrlen) == -1) {
+                error (NULL, 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 (NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+            goto failed;
+        }
+        if (connect (priv.sock, (struct sockaddr *) &addr, sizeof addr) == -1){
+            error (NULL, 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 (NULL, VIR_ERR_SYSTEM_ERROR, strerror (errno));
+            goto failed;
+        }
+
+        pid = fork ();
+        if (pid == -1) {
+            error (NULL, 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, 1, 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 (NULL, 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) {
+        if (priv.uses_tls) gnutls_bye (priv.session, GNUTLS_SHUT_RDWR);
+        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 ATTRIBUTE_UNUSED)
+{
+    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 (NULL, 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 (NULL, 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 (NULL, 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 (NULL, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err));
+        return NULL;
+    }
+
+    /* Use default priorities */
+    err = gnutls_set_default_priority (session);
+    if (err) {
+        error (NULL, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err));
+        return NULL;
+    }
+    err =
+        gnutls_certificate_type_set_priority (session,
+                                              cert_type_priority);
+    if (err) {
+        error (NULL, 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 (NULL, 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 (NULL, 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 (NULL, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (len));
+        return NULL;
+    }
+    if (len != 1 || buf[0] != '\1') {
+        error (NULL, 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 ATTRIBUTE_UNUSED,
+                    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 (NULL, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (ret));
+        return -1;
+    }
+  
+    if ((now = time(NULL)) == ((time_t)-1)) {
+        error (NULL, 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 (NULL, VIR_ERR_RPC, reason);
+        return -1;
+    }
+
+    if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) {
+        error (NULL, VIR_ERR_RPC, "Certificate type is not X.509");
+        return -1;
+    }
+  
+    if (!(certs = gnutls_certificate_get_peers(session, &nCerts))) {
+        error (NULL, 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 (NULL, 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 (NULL, VIR_ERR_GNUTLS_ERROR, gnutls_strerror (ret));
+            gnutls_x509_crt_deinit (cert);
+            return -1;
+        }
+    
+        if (gnutls_x509_crt_get_expiration_time (cert) < now) {
+            error (NULL, VIR_ERR_RPC, "The certificate has expired");
+            gnutls_x509_crt_deinit (cert);
+            return -1;
+        }
+    
+        if (gnutls_x509_crt_get_activation_time (cert) > now) {
+            error (NULL, 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
+                    (NULL, 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, 0, REMOTE_PROC_CLOSE,
+              (xdrproc_t) xdr_void, (char *) NULL,
+              (xdrproc_t) xdr_void, (char *) NULL) == -1)
+        return -1;
+
+    /* Close socket. */
+    if (priv->uses_tls) gnutls_bye (priv->session, GNUTLS_SHUT_RDWR);
+    close (priv->sock);
+
+    /* See comment for remoteType. */
+    if (priv->type) free (priv->type);
+
+    return 0;
+}
+
+/* Unfortunately this function is defined to return a static string.
+ * Since the remote end always answers with the same type (for a
+ * single connection anyway) we cache the type in the connection's
+ * private data, and free it when we close the connection.
+ *
+ * See also:
+ * http://www.redhat.com/archives/libvir-list/2007-February/msg00096.html
+ */
+static const char *
+remoteType (virConnectPtr conn)
+{
+    remote_get_type_ret ret;
+    GET_PRIVATE (conn, NULL);
+
+    /* Cached? */
+    if (priv->type) return priv->type;
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_TYPE,
+              (xdrproc_t) xdr_void, (char *) NULL,
+              (xdrproc_t) xdr_remote_get_type_ret, (char *) &ret) == -1)
+        return NULL;
+
+    /* Stash. */
+    return priv->type = ret.type;
+}
+
+static int
+remoteVersion (virConnectPtr conn, unsigned long *hvVer)
+{
+    remote_get_version_ret ret;
+    GET_PRIVATE (conn, -1);
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_VERSION,
+              (xdrproc_t) xdr_void, (char *) NULL,
+              (xdrproc_t) xdr_remote_get_version_ret, (char *) &ret) == -1)
+        return -1;
+
+    if (hvVer) *hvVer = ret.hv_ver;
+    return 0;
+}
+
+static int
+remoteGetMaxVcpus (virConnectPtr conn, const char *type)
+{
+    remote_get_max_vcpus_args args;
+    remote_get_max_vcpus_ret ret;
+    GET_PRIVATE (conn, -1);
+
+    memset (&ret, 0, sizeof ret);
+    args.type = (char **) &type;
+    if (call (conn, priv, 0, REMOTE_PROC_GET_MAX_VCPUS,
+              (xdrproc_t) xdr_remote_get_max_vcpus_args, (char *) &args,
+              (xdrproc_t) xdr_remote_get_max_vcpus_ret, (char *) &ret) == -1)
+        return -1;
+
+    return ret.max_vcpus;
+}
+
+static int
+remoteNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info)
+{
+    remote_node_get_info_ret ret;
+    GET_PRIVATE (conn, -1);
+
+    memset (&ret, 0, sizeof ret);
+    if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_INFO,
+              (xdrproc_t) xdr_void, (char *) NULL,
+              (xdrproc_t) xdr_remote_node_get_info_ret, (char *) &ret) == -1)
+        return -1;
+
+    strncpy (info->model, ret.model, 32);
+    info->model[31] = '\0';
+    info->memory = ret.memory;
+    info->cpus = ret.cpus;
+    info->mhz = ret.mhz;
+    info->nodes = ret.nodes;
+    info->sockets = ret.sockets;
+    info->cores = ret.cores;
+    info->threads = ret.threads;
+    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, 0, 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
+remoteNetworkOpen (virConnectPtr conn,
+                   const char *uri_str ATTRIBUTE_UNUSED,
+                   int flags ATTRIBUTE_UNUSED)
+{
+    /* If the main connection is a remote, then just catch the
+     * network open too.  Nothing is forwarded because the
+     * main remoteOpen call above will have already opened
+     * network on the remote side.
+     */
+    if (conn && conn->driver &&
+        strcmp (conn->driver->name, "remote") == 0)
+        return VIR_DRV_OPEN_SUCCESS;
+    else
+        return VIR_DRV_OPEN_DECLINED;
+}
+
+static int
+remoteNetworkClose (virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    /* No need to pass this to the remote side, because
+     * libvirt.c will soon call remoteClose.
+     */
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+
+static int really_write (virConnectPtr conn, struct private_data *priv,
+                         int in_open, char *bytes, int len);
+static int really_read (virConnectPtr conn, struct private_data *priv,
+                        int in_open, char *bytes, int len);
+
+/* This function performs a remote procedure call to procedure PROC_NR.
+ *
+ * NB. This does not free the args structure (not desirable, since you
+ * often want this allocated on the stack or else it contains strings
+ * which come from the user).  It does however free any intermediate
+ * results, eg. the error structure if there is one.
+ *
+ * NB(2). Make sure to memset (&ret, 0, sizeof ret) before calling,
+ * else Bad Things will happen in the XDR code.
+ */
+static int
+call (virConnectPtr conn, struct private_data *priv,
+      int in_open /* if we are in virConnectOpen */,
+      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 (in_open ? NULL : conn,
+               VIR_ERR_RPC, "xdr_remote_message_header");
+        return -1;
+    }
+
+    if (!(*args_filter) (&xdr, args)) {
+        error (in_open ? NULL : 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 (in_open ? NULL : 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, in_open, buffer2, sizeof buffer2) == -1 ||
+        really_write (conn, priv, in_open, buffer, len-4) == -1)
+        return -1;
+
+    /* Read and deserialise length word. */
+    if (really_read (conn, priv, in_open, buffer2, sizeof buffer2) == -1)
+        return -1;
+
+    xdrmem_create (&xdr, buffer2, sizeof buffer2, XDR_DECODE);
+    if (!xdr_int (&xdr, &len)) {
+        error (in_open ? NULL : 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 (in_open ? NULL : 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, in_open, buffer, len) == -1)
+        return -1;
+
+    /* Deserialise reply header. */
+    xdrmem_create (&xdr, buffer, len, XDR_DECODE);
+    if (!xdr_remote_message_header (&xdr, &hdr)) {
+        error (in_open ? NULL : 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 (in_open ? NULL : 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 (in_open ? NULL : 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 (in_open ? NULL : 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 (in_open ? NULL : 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 (in_open ? NULL : 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 (in_open ? NULL : 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 (in_open ? NULL : conn,
+                   VIR_ERR_RPC, "unmarshalling remote_error");
+            return -1;
+        }
+        xdr_destroy (&xdr);
+        server_error (in_open ? NULL : conn, &rerror);
+        xdr_free ((xdrproc_t) xdr_remote_error, (char *) &rerror);
+        return -1;
+
+    default:
+        __virRaiseError (in_open ? NULL : 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,
+              int in_open /* if we are in virConnectOpen */,
+              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 (in_open ? NULL : 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 (in_open ? NULL : 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,
+             int in_open /* if we are in virConnectOpen */,
+             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 (in_open ? NULL : conn,
+                       VIR_ERR_GNUTLS_ERROR, gnutls_strerror (err));
+                return -1;
+            }
+            if (err == 0) {
+                error (in_open ? NULL : 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 (in_open ? NULL : conn,
+                       VIR_ERR_SYSTEM_ERROR, strerror (errno));
+                return -1;
+            }
+            if (err == 0) {
+                error (in_open ? NULL : 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 (conn, err->dom);
+    virNetworkPtr net = get_network (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;
+
+    __virRaiseError (conn, dom, net,
+                     err->domain, err->code, err->level,
+                     str1, str2, str3,
+                     err->int1, err->int2,
+                     message);
+}
+
+/* get_domain and get_network turn an on-wire (name, uuid) pair into
+ * virDomainPtr or virNetworkPtr object.  The *nonnull* versions do
+ * the same when the virDomainPtr or virNetworkPtr cannot be NULL.
+ *
+ * NB. If the *nonnull* versions return NULL then the caller must
+ * return an error.
+ */
+static virDomainPtr
+get_domain (virConnectPtr conn, remote_domain domain)
+{
+    if (!conn || !domain) return NULL;
+    return virGetDomain (conn, domain->name, BAD_CAST domain->uuid);
+}
+
+static virNetworkPtr
+get_network (virConnectPtr conn, remote_network network)
+{
+    if (!conn || !network) return NULL;
+    return virGetNetwork (conn, network->name, BAD_CAST network->uuid);
+}
+
+#if 0
+static virDomainPtr
+get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain)
+{
+    return virGetDomain (conn, domain.name, BAD_CAST domain.uuid);
+}
+
+static virNetworkPtr
+get_nonnull_network (virConnectPtr conn, remote_nonnull_network network)
+{
+    return virGetNetwork (conn, network.name, BAD_CAST network.uuid);
+}
+#endif
+
+/*----------------------------------------------------------------------*/
+
+static virDriver driver = {
+    .no = VIR_DRV_REMOTE,
+    .name = "remote",
+    .ver = REMOTE_PROTOCOL_VERSION,
+    .open = remoteOpen,
+    .close = remoteClose,
+	.type = remoteType,
+	.version = remoteVersion,
+	.getMaxVcpus = remoteGetMaxVcpus,
+	.nodeGetInfo = remoteNodeGetInfo,
+    .getCapabilities = remoteGetCapabilities,
+    /* XXX */
+};
+
+static virNetworkDriver network_driver = {
+    .open = remoteNetworkOpen,
+    .close = remoteNetworkClose,
+    /* XXX */
+};
+
+/* remoteRegister:
+ *
+ * Register driver with libvirt driver system.
+ */
+int
+remoteRegister (void)
+{
+    if (virRegisterDriver (&driver) == -1) return -1;
+    if (virRegisterNetworkDriver (&network_driver) == -1) return -1;
+
+    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 17:47:20.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 redhat com>
+ */
+
+#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/test.c libvirt-remote/src/test.c
--- libvirt-cvs/src/test.c	2007-05-01 13:55:02.000000000 +0100
+++ libvirt-remote/src/test.c	2007-05-01 16:29:09.000000000 +0100
@@ -562,7 +562,7 @@
     if (ret == 0) {
         nodeInfo->nodes = l;
     } else if (ret == -2) {
-	testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu numa nodes"));
+	testError(NULL, NULL, VIR_ERR_XML_ERROR, _("node cpu numa nodes"));
 	goto error;
     }
 
@@ -570,7 +570,7 @@
     if (ret == 0) {
         nodeInfo->sockets = l;
     } else if (ret == -2) {
-	testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu sockets"));
+	testError(NULL, NULL, VIR_ERR_XML_ERROR, _("node cpu sockets"));
 	goto error;
     }
 
@@ -578,7 +578,7 @@
     if (ret == 0) {
         nodeInfo->cores = l;
     } else if (ret == -2) {
-	testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu cores"));
+	testError(NULL, NULL, VIR_ERR_XML_ERROR, _("node cpu cores"));
 	goto error;
     }
 
@@ -586,7 +586,7 @@
     if (ret == 0) {
         nodeInfo->threads = l;
     } else if (ret == -2) {
-	testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu threads"));
+	testError(NULL, NULL, VIR_ERR_XML_ERROR, _("node cpu threads"));
 	goto error;
     }
 
@@ -597,14 +597,14 @@
 	    nodeInfo->cpus = l;
 	}
     } else if (ret == -2) {
-	testError(conn, NULL, VIR_ERR_XML_ERROR, _("node active cpu"));
+	testError(NULL, NULL, VIR_ERR_XML_ERROR, _("node active cpu"));
 	goto error;
     }
     ret = virXPathLong("string(/node/cpu/mhz[1])", ctxt, &l);
     if (ret == 0) {
         nodeInfo->mhz = l;
     } else if (ret == -2) {
-        testError(conn, NULL, VIR_ERR_XML_ERROR, _("node cpu mhz"));
+        testError(NULL, NULL, VIR_ERR_XML_ERROR, _("node cpu mhz"));
 	goto error;
     }
 
@@ -619,7 +619,7 @@
     if (ret == 0) {
         nodeInfo->memory = l;
     } else if (ret == -2) {
-        testError(conn, NULL, VIR_ERR_XML_ERROR, _("node memory"));
+        testError(NULL, NULL, VIR_ERR_XML_ERROR, _("node memory"));
 	goto error;
     }
 
@@ -717,7 +717,7 @@
 
     uri = xmlParseURI(name);
     if (uri == NULL) {
-        testError(conn, NULL, VIR_ERR_NO_SUPPORT, name);
+        testError(NULL, NULL, VIR_ERR_NO_SUPPORT, name);
         return VIR_DRV_OPEN_DECLINED;
     }
 
@@ -730,7 +730,7 @@
     if (!uri->path
         || uri->path[0] == '\0'
         || (uri->path[0] == '/' && uri->path[1] == '\0')) {
-        testError (conn, NULL, VIR_ERR_INVALID_ARG,
+        testError (NULL, NULL, VIR_ERR_INVALID_ARG,
                    _("testOpen: supply a path or use test:///default"));
         return VIR_DRV_OPEN_ERROR;
     }
@@ -743,7 +743,7 @@
     /* Allocate per-connection private data. */
     priv = conn->privateData = malloc (sizeof (struct _testPrivate));
     if (!priv) {
-        testError(conn, NULL, VIR_ERR_NO_MEMORY, _("allocating private data"));
+        testError(NULL, NULL, VIR_ERR_NO_MEMORY, _("allocating private data"));
         return VIR_DRV_OPEN_ERROR;
     }
     priv->handle = -1;
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-26 17:47:19.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);
 }
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/src/xend_internal.c libvirt-remote/src/xend_internal.c
--- libvirt-cvs/src/xend_internal.c	2007-05-01 13:55:03.000000000 +0100
+++ libvirt-remote/src/xend_internal.c	2007-05-01 16:29:09.000000000 +0100
@@ -894,7 +894,7 @@
     pent = gethostbyname(host);
     if (pent == NULL) {
         if (inet_aton(host, &ip) == 0) {
-            virXendError(conn, VIR_ERR_UNKNOWN_HOST, host);
+            virXendError(NULL, VIR_ERR_UNKNOWN_HOST, host);
             errno = ESRCH;
             return (-1);
         }
@@ -1960,14 +1960,14 @@
          */
         uri = xmlParseURI(name);
         if (uri == NULL) {
-            virXendError(conn, VIR_ERR_NO_SUPPORT, name);
+            virXendError(NULL, VIR_ERR_NO_SUPPORT, name);
             goto failed;
         }
 
         if (uri->scheme == NULL) {
             /* It should be a file access */
             if (uri->path == NULL) {
-                virXendError(conn, VIR_ERR_NO_SUPPORT, name);
+                virXendError(NULL, VIR_ERR_NO_SUPPORT, name);
                 goto failed;
             }
             ret = xenDaemonOpen_unix(conn, uri->path);
@@ -1985,7 +1985,7 @@
             if (ret == -1)
                 goto failed;
         } else {
-            virXendError(conn, VIR_ERR_NO_SUPPORT, name);
+            virXendError(NULL, VIR_ERR_NO_SUPPORT, name);
             goto failed;
         }
     }
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/src/xen_internal.c libvirt-remote/src/xen_internal.c
--- libvirt-cvs/src/xen_internal.c	2007-05-01 13:55:02.000000000 +0100
+++ libvirt-remote/src/xen_internal.c	2007-04-30 18:36:39.000000000 +0100
@@ -1524,8 +1524,10 @@
     xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;
 
     if (initialized == 0)
-        if (xenHypervisorInit() == -1)
+        if (xenHypervisorInit() == -1) {
+            virXenError (VIR_ERR_NO_XEN, "xenHypervisorInit failed", 0);
             return -1;
+        }
 
     priv->handle = -1;
 
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/src/xen_unified.c libvirt-remote/src/xen_unified.c
--- libvirt-cvs/src/xen_unified.c	2007-05-01 13:55:02.000000000 +0100
+++ libvirt-remote/src/xen_unified.c	2007-05-01 16:29:09.000000000 +0100
@@ -95,7 +95,7 @@
     /* Allocate per-connection private data. */
     priv = malloc (sizeof *priv);
     if (!priv) {
-        xenUnifiedError (conn, VIR_ERR_NO_MEMORY, "allocating private data");
+        xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, "allocating private data");
         return VIR_DRV_OPEN_ERROR;
     }
     conn->privateData = priv;
diff -urN --exclude=CVS --exclude=.git --exclude='*.pem' --exclude=demoCA --exclude=.gitignore --exclude='*.orig' --exclude='*.bak' libvirt-cvs/src/xs_internal.c libvirt-remote/src/xs_internal.c
--- libvirt-cvs/src/xs_internal.c	2007-05-01 13:55:03.000000000 +0100
+++ libvirt-remote/src/xs_internal.c	2007-05-01 16:29:09.000000000 +0100
@@ -340,7 +340,7 @@
 #endif /* ! PROXY */
 
     if (priv->xshandle == NULL) {
-        virXenStoreError(conn, VIR_ERR_NO_XEN, 
+        virXenStoreError(NULL, VIR_ERR_NO_XEN, 
 	                     _("failed to connect to Xen Store"));
         return (-1);
     }

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


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