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