]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Mon Jun 11 12:49:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
authorRichard W.M. Jones <rjones@redhat.com>
Mon, 11 Jun 2007 12:04:54 +0000 (12:04 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Mon, 11 Jun 2007 12:04:54 +0000 (12:04 +0000)
* qemud/Makefile.am, qemud/dispatch.c, qemud/dispatch.h,
  qemud/internal.h, qemud/protocol.c,
  qemud/protocol.h, qemud/protocol.x, qemud/qemud.c:
  libvirt_qemud server-side modifications to use
  XDR-based protocol instead of homebrew (Dan Berrange).
  QEMUD server modified to dispatch calls from remote
  clients (Richard Jones).  Added TLS support (Richard Jones).
  Added TCP & IPv6 support (Richard Jones).
  Additional configuration file, command-line handling, and
  usage (Richard Jones).
* qemud/conf.c: Remove unnecessary header file.

ChangeLog
qemud/Makefile.am
qemud/conf.c
qemud/dispatch.c
qemud/dispatch.h
qemud/internal.h
qemud/protocol.c [new file with mode: 0644]
qemud/protocol.h
qemud/protocol.x [new file with mode: 0644]
qemud/qemud.c

index 869c4da1dc203396a70ed46ca273d62bea20214a..32bffa8a5146aba240497daebecbe8d63a2e01cf 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+Mon Jun 11 12:49:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
+
+       * qemud/Makefile.am, qemud/dispatch.c, qemud/dispatch.h,
+         qemud/internal.h, qemud/protocol.c,
+         qemud/protocol.h, qemud/protocol.x, qemud/qemud.c:
+         libvirt_qemud server-side modifications to use
+         XDR-based protocol instead of homebrew (Dan Berrange).
+         QEMUD server modified to dispatch calls from remote
+         clients (Richard Jones).  Added TLS support (Richard Jones).
+         Added TCP & IPv6 support (Richard Jones).
+         Additional configuration file, command-line handling, and
+         usage (Richard Jones).
+       * qemud/conf.c: Remove unnecessary header file.
+
 Mon Jun 11 12:48:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
 
        * src/qemu_internal.c: QEMU client-side modifications to
index d2dbc80caa4daedc6a2448e8efeb11b5102021cd..09c09594d63f7bf45dcbeaf6d553636fb6777a78 100644 (file)
@@ -5,23 +5,28 @@ UUID=$(shell uuidgen)
 
 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 = \
         -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 = $(WARN_CFLAGS) $(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
@@ -41,7 +46,41 @@ uninstall-local:
        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 \
+       remote_dispatch_prototypes.h \
+       remote_dispatch_localvars.h \
+       remote_dispatch_proc_switch.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
+
+remote.c: remote_dispatch_prototypes.h \
+         remote_dispatch_localvars.h \
+         remote_dispatch_proc_switch.h
+
+remote_dispatch_prototypes.h: remote_generate_stubs.pl remote_protocol.x
+       perl -w remote_generate_stubs.pl -i remote_protocol.x > $@
+
+remote_dispatch_localvars.h: remote_generate_stubs.pl remote_protocol.x
+       perl -w remote_generate_stubs.pl -v remote_protocol.x > $@
+
+remote_dispatch_proc_switch.h: remote_generate_stubs.pl remote_protocol.x
+       perl -w remote_generate_stubs.pl -w remote_protocol.x > $@
 
 if LIBVIRT_INIT_SCRIPTS_RED_HAT
 initdir = $(sysconfdir)/rc.d/init.d
index c2fe4f41f127ca73b191aead68ea8b54835e6f08..d70c0c294b9363e17c04b6681d69df622157f317 100644 (file)
@@ -42,7 +42,6 @@
 
 #include <libvirt/virterror.h>
 
-#include "protocol.h"
 #include "internal.h"
 #include "conf.h"
 #include "driver.h"
index bb6d51a42566e2872e3b2d61a5047cdf469cb91c..faeb20f3fb23274afe0e32fc80316d41c4649e66 100644 (file)
 
 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 qemudDispatchGetNodeInfo(struct qemud_server *server, struct qemud_cl
 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 @@ qemudDispatchGetCapabilities (struct qemud_server *server,
     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 @@ qemudDispatchGetCapabilities (struct qemud_server *server,
         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 @@ static int qemudDispatchListDomains(struct qemud_server *server, struct qemud_cl
         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 @@ static int qemudDispatchDomainGetInfo(struct qemud_server *server, struct qemud_
         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 @@ static int qemudDispatchListDefinedDomains(struct qemud_server *server, struct q
         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;
+                                     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';
 
-    in->data.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 @@ static int qemudDispatchListNetworks(struct qemud_server *server, struct qemud_c
         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 @@ static int qemudDispatchListDefinedNetworks(struct qemud_server *server, struct
         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;
-
-    in->data.networkDefineRequest.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.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 @@ clientFunc funcsTransmitRW[QEMUD_PKT_MAX] = {
     qemudDispatchGetCapabilities,
 };
 
-clientFunc funcsTransmitRO[QEMUD_PKT_MAX] = {
-    NULL, /* FAILURE code */
+clientFunc funcsTransmitRO[QEMUD_CLIENT_PKT_MAX] = {
     qemudDispatchGetVersion,
     qemudDispatchGetNodeInfo,
     qemudDispatchListDomains,
@@ -1084,22 +939,18 @@ clientFunc funcsTransmitRO[QEMUD_PKT_MAX] = {
  * 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;
     }
@@ -1120,14 +971,11 @@ int qemudDispatch(struct qemud_server *server, struct qemud_client *client,
         }
     }
 
-    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
index 9e1dbd7d37b9f48e751901c1f72dfc4360a12dd0..8b494f65fbbccc0ac03b0553f7d3fd628f351a78 100644 (file)
@@ -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
 
index 3d7a9266652c325b63f8cd6028ba95e4c7faf89c..276ae4721b88cd02ef080d5a60e5a03c81e767b1 100644 (file)
 
 #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 @@ typedef enum {
 #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,
@@ -277,22 +271,61 @@ struct qemud_network {
     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;
 };
 
@@ -315,7 +348,6 @@ struct qemud_server {
     struct qemud_network *networks;
     brControl *brctl;
     iptablesContext *iptables;
-    char configDirs[QEMUD_N_CONFIG_DIRS][PATH_MAX];
     char *configDir;
     char *autostartDir;
     char *networkConfigDir;
@@ -347,6 +379,9 @@ void qemudLog(int priority, const char *fmt, ...)
 #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 --git a/qemud/protocol.c b/qemud/protocol.c
new file mode 100644 (file)
index 0000000..a9db929
--- /dev/null
@@ -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;
+}
index 8826df750bdff6f0d3105db0aefa3ef8d0ae46ec..0454253028decd125fe9ce1d9b60793030ada0da 100644 (file)
 /*
- * 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 <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
+#include <rpc/rpc.h>
+
+
+#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 ();
 
-/*
- * Local variables:
- *  indent-tabs-mode: nil
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 4
- * End:
- */
+#endif /* K&R C */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_PROTOCOL_H_RPCGEN */
diff --git a/qemud/protocol.x b/qemud/protocol.x
new file mode 100644 (file)
index 0000000..d88519b
--- /dev/null
@@ -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;
+};
index 171da4a0b697c8a1acd9142c88ba57c3c1b81317..5a6180f2a752a8e9fea0c302ac42a1317f7839f4 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <config.h>
 
+#define _GNU_SOURCE /* for asprintf */
+
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
@@ -34,6 +36,7 @@
 #include <sys/un.h>
 #include <sys/poll.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>
 #include <netdb.h>
 #include <stdlib.h>
 #include <pwd.h>
 #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_ip_list = 0;
+static const char **tls_allowed_dn_list = 0;
+
+static const char *key_file = LIBVIRT_SERVERKEY;
+static const char *cert_file = LIBVIRT_SERVERCERT;
+static const char *ca_file = LIBVIRT_CACERT;
+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 +110,80 @@ static void sig_handler(int sig) {
     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 +202,13 @@ static int qemudDispatchSignal(struct qemud_server *server)
     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 +217,47 @@ static int qemudDispatchSignal(struct qemud_server *server)
     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;
-        }
-
-        /* 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;
+        if (!remote) {
+            /* shutdown active VMs */
+            vm = server->vms;
+            while (vm) {
+                struct qemud_vm *next = vm->next;
+                if (qemudIsActiveVM(vm))
+                    qemudShutdownVMDaemon(server, vm);
+                vm = next;
+            }
 
-        /* shutdown active networks */
-        network = server->networks;
-        while (network) {
-            struct qemud_network *next = network->next;
-            if (qemudIsActiveNetwork(network))
-                qemudShutdownNetworkDaemon(server, network);
-            network = 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;
+            /* 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->networks = NULL;
-        server->nactivenetworks = 0;
-        server->ninactivenetworks = 0;
 
         server->shutdown = 1;
         break;
@@ -405,72 +515,206 @@ static int qemudListenUnix(struct qemud_server *server,
     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;
+    }
+
+    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;
+    }
 
-    uid_t uid;
-    struct passwd *pw;
-    char base[PATH_MAX] = SYSCONF_DIR "/";
+    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 (sys) {
-        if (uid != 0) {
-            qemudLog(QEMUD_ERR, "You must run the daemon as root to use system mode");
+        if (qemudSetCloseExec(sock->fd) < 0 ||
+            qemudSetNonBlock(sock->fd) < 0)
+            return -1;
+
+        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;
+
         if (snprintf(server->logDir, PATH_MAX, "%s/log/libvirt/qemu", LOCAL_STATE_DIR) >= PATH_MAX)
             goto snprintf_error;
     } 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;
 
-        if (snprintf(server->logDir, PATH_MAX, "%s/.libvirt/qemu/log", pw->pw_dir) >= 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;
 
-    for (i = 0; i < QEMUD_N_CONFIG_DIRS; i++)
-        if (snprintf(server->configDirs[i], PATH_MAX, "%s%s", base, paths[i]) >= PATH_MAX)
+        if (snprintf(server->logDir, PATH_MAX, "%s/log", base) >= PATH_MAX)
             goto snprintf_error;
+    } /* !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];
@@ -486,22 +730,30 @@ static struct qemud_server *qemudInitialize(int sys, int sigread) {
 
     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;
@@ -514,17 +766,235 @@ static struct qemud_server *qemudInitialize(int sys, int sigread) {
             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;
+}
+
+/* Check DN is on tls_allowed_dn_list. */
+static int
+remoteCheckDN (gnutls_x509_crt_t cert)
+{
+    char name[256];
+    size_t namesize = sizeof name;
+    const char **wildcards;
+    int err;
+
+    err = gnutls_x509_crt_get_dn (cert, name, &namesize);
+    if (err != 0) {
+        qemudLog (QEMUD_ERR,
+                  "remoteCheckDN: gnutls_x509_cert_get_dn: %s",
+                  gnutls_strerror (err));
+        return 0;
+    }
+
+    /* If the list is not set, allow any DN. */
+    wildcards = tls_allowed_dn_list;
+    if (!wildcards)
+        return 1;
+
+    while (*wildcards) {
+        if (fnmatch (*wildcards, name, 0) == 0)
+            return 1;
+        wildcards++;
+    }
+
+    /* Print the client's DN. */
+    qemudLog (QEMUD_DEBUG,
+              "remoteCheckDN: failed: client DN is %s", name);
+
+    return 0; // Not found.
+}
+
+static int
+remoteCheckCertificate (gnutls_session_t session)
+{
+    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 (!remoteCheckDN (cert)) {
+                /* This is the most common error: make it informative. */
+                qemudLog (QEMUD_ERR, "remoteCheckCertificate: client's Distinguished Name is not on the list of allowed clients (tls_allowed_dn_list).  Use 'openssl x509 -in clientcert.pem -text' to view the Distinguished Name field in the client certificate, or run this daemon with --verbose option.");
+                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;
+
+    /* Verify client certificate. */
+    if (remoteCheckCertificate (client->session) == -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");
+    }
+
+    /*----- IP address check, similar to tcp wrappers -----*/
+
+    /* 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 the client is on the list of allowed clients.
+     *
+     * NB: No tls_allowed_ip_list in config file means anyone can access.
+     * If tls_allowed_ip_list 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_ip_list;
+    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's IP address (%s) is not on the list of allowed clients (tls_allowed_ip_list)", addr);
+        if (!tls_no_verify_address) return -1;
+        else qemudLog (QEMUD_INFO, "remoteCheckAccess: tls_no_verify_address is set so the client's IP 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;
+    int no_slow_start = 1;
 
     if ((fd = accept(sock->fd, (struct sockaddr *)&addr, &addrlen)) < 0) {
         if (errno == EAGAIN)
@@ -533,6 +1003,10 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
         return -1;
     }
 
+    /* Disable Nagle.  Unix sockets will ignore this. */
+    setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&no_slow_start,
+                sizeof no_slow_start);
+
     if (qemudSetCloseExec(fd) < 0 ||
         qemudSetNonBlock(fd) < 0) {
         close(fd);
@@ -540,14 +1014,54 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket
     }
 
     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;
 }
 
 
@@ -980,113 +1494,310 @@ static void qemudDispatchClientFailure(struct qemud_server *server, struct qemud
         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)) <= 0) {
+            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;
-
-    /* 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);
+    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 (!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);
+            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);
-        qemudDebug("Dispatch");
+        }
+
+        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,
@@ -1685,6 +2396,9 @@ static int qemudDispatchPoll(struct qemud_server *server, struct pollfd *fds) {
     }
     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)
@@ -1759,12 +2473,19 @@ static void qemudPreparePoll(struct qemud_server *server, struct pollfd *fds) {
     }
     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) {
@@ -1776,7 +2497,7 @@ static void qemudPreparePoll(struct qemud_server *server, struct pollfd *fds) {
 
 
 
-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;
@@ -1825,10 +2546,10 @@ static int qemudOneLoop(struct qemud_server *server, int timeout) {
     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;
@@ -1852,60 +2573,250 @@ static void qemudCleanup(struct qemud_server *server) {
     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_dn_list");
+    if (p) {
+        switch (p->type) {
+        case VIR_CONF_STRING:
+            tls_allowed_dn_list = malloc (2 * sizeof (char *));
+            tls_allowed_dn_list[0] = strdup (p->str);
+            tls_allowed_dn_list[1] = 0;
+            break;
+
+        case VIR_CONF_LIST: {
+            int i, len = 0;
+            virConfValuePtr pp;
+            for (pp = p->list; pp; pp = p->next)
+                len++;
+            tls_allowed_dn_list =
+                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_dn_list: should be a string or list of strings\n", filename);
+                    return -1;
+                }
+                tls_allowed_dn_list[i] = strdup (pp->str);
+            }
+            tls_allowed_dn_list[i] = 0;
+            break;
+        }
+
+        default:
+            qemudLog (QEMUD_ERR, "remoteReadConfigFile: %s: tls_allowed_dn_list: should be a string or list of strings\n", filename);
+            return -1;
+        }
+    }
+
+    p = virConfGetValue (conf, "tls_allowed_ip_list");
+    if (p) {
+        switch (p->type) {
+        case VIR_CONF_STRING:
+            tls_allowed_ip_list = malloc (2 * sizeof (char *));
+            tls_allowed_ip_list[0] = strdup (p->str);
+            tls_allowed_ip_list[1] = 0;
+            break;
+
+        case VIR_CONF_LIST: {
+            int i, len = 0;
+            virConfValuePtr pp;
+            for (pp = p->list; pp; pp = p->next)
+                len++;
+            tls_allowed_ip_list =
+                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_ip_list: should be a string or list of strings\n", filename);
+                    return -1;
+                }
+                tls_allowed_ip_list[i] = strdup (pp->str);
+            }
+            tls_allowed_ip_list[i] = 0;
+            break;
+        }
+
+        default:
+            qemudLog (QEMUD_ERR, "remoteReadConfigFile: %s: tls_allowed_ip_list: 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\
+    TLS:\n\
+      CA certificate:     " LIBVIRT_CACERT "\n\
+      Server certificate: " LIBVIRT_SERVERCERT "\n\
+      Server private key: " LIBVIRT_SERVERKEY "\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'},
@@ -1918,7 +2829,7 @@ int main(int argc, char **argv) {
         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;
@@ -1934,6 +2845,9 @@ int main(int argc, char **argv) {
         case 'd':
             godaemon = 1;
             break;
+        case 'r':
+            remote = 1;
+            break;
         case 's':
             sys = 1;
             break;
@@ -1947,7 +2861,11 @@ int main(int argc, char **argv) {
             break;
 
         case 'p':
-            pid_file = strdup(optarg);
+            pid_file = optarg;
+            break;
+
+        case 'f':
+            remote_config_file = optarg;
             break;
 
         case '?':
@@ -1959,6 +2877,12 @@ int main(int argc, char **argv) {
         }
     }
 
+    /* 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);
 
@@ -1995,16 +2919,27 @@ int main(int argc, char **argv) {
         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);
 
@@ -2017,13 +2952,10 @@ int main(int argc, char **argv) {
     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;
 }