dispatch.c 33.3 KB
Newer Older
D
Daniel P. Berrange 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * dispatch.c: (De-)marshall wire messages to driver functions.
 *
 * Copyright (C) 2006, 2007 Red Hat, Inc.
 * Copyright (C) 2006 Daniel P. Berrange
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

24 25
#include <config.h>

26
#include <unistd.h>
D
Daniel P. Berrange 已提交
27 28 29 30 31 32 33 34 35
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <libvirt/virterror.h>

#include "internal.h"
#include "driver.h"
#include "dispatch.h"
36
#include "conf.h"
D
Daniel P. Berrange 已提交
37 38 39 40


static int qemudDispatchFailure(struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client ATTRIBUTE_UNUSED,
41
                                struct qemud_packet_server_data *out) {
42 43
    virErrorPtr err = virGetLastError();

44
    out->type = QEMUD_SERVER_PKT_FAILURE;
45 46 47 48 49

    out->qemud_packet_server_data_u.failureReply.code = err->code;
    strncpy(out->qemud_packet_server_data_u.failureReply.message,
            err->message, QEMUD_MAX_ERROR_LEN-1);
    out->qemud_packet_server_data_u.failureReply.message[QEMUD_MAX_ERROR_LEN-1] = '\0';
D
Daniel P. Berrange 已提交
50 51 52 53 54
    return 0;
}


static int qemudDispatchGetVersion(struct qemud_server *server, struct qemud_client *client,
55
                                   struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
56 57 58 59 60
    int version = qemudGetVersion(server);
    if (version < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
61 62
        out->type = QEMUD_SERVER_PKT_GET_VERSION;
        out->qemud_packet_server_data_u.getVersionReply.versionNum = version;
D
Daniel P. Berrange 已提交
63 64 65 66 67
    }
    return 0;
}

static int qemudDispatchGetNodeInfo(struct qemud_server *server, struct qemud_client *client,
68
                                    struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
69 70 71 72 73 74 75 76 77
    if (qemudGetNodeInfo(&out->qemud_packet_server_data_u.getNodeInfoReply.memory,
                         out->qemud_packet_server_data_u.getNodeInfoReply.model,
                         sizeof(out->qemud_packet_server_data_u.getNodeInfoReply.model),
                         &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) {
D
Daniel P. Berrange 已提交
78 79 80 81 82
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
        return 0;
    }

83 84
    out->type = QEMUD_SERVER_PKT_GET_NODEINFO;
    out->qemud_packet_server_data_u.getNodeInfoReply.model[sizeof(out->qemud_packet_server_data_u.getNodeInfoReply.model)-1] = '\0';
D
Daniel P. Berrange 已提交
85 86 87 88

    return 0;
}

89 90 91
static int
qemudDispatchGetCapabilities (struct qemud_server *server,
                              struct qemud_client *client,
92 93
                              struct qemud_packet_client_data *in ATTRIBUTE_UNUSED,
                              struct qemud_packet_server_data *out)
94
{
95
    char *xml = qemudGetCapabilities(server);
96

97
    if (strlen(xml) > QEMUD_MAX_XML_LEN) {
98
        qemudReportError(NULL, NULL, NULL, VIR_ERR_XML_ERROR, NULL);
99
        qemudDispatchFailure (server, client, out);
100
        free(xml);
101 102
        return 0;
    }
103

104
    out->type = QEMUD_SERVER_PKT_GET_CAPABILITIES;
105 106
    strcpy (out->qemud_packet_server_data_u.getCapabilitiesReply.xml, xml);
    free(xml);
107 108 109
    return 0;
}

D
Daniel P. Berrange 已提交
110
static int qemudDispatchListDomains(struct qemud_server *server, struct qemud_client *client,
111
                                    struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
112 113 114 115 116 117 118 119 120
    int i, ndomains, domains[QEMUD_MAX_NUM_DOMAINS];

    ndomains = qemudListDomains(server,
                                domains,
                                QEMUD_MAX_NUM_DOMAINS);
    if (ndomains < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
121
        out->type = QEMUD_SERVER_PKT_LIST_DOMAINS;
D
Daniel P. Berrange 已提交
122
        for (i = 0 ; i < ndomains ; i++) {
123
            out->qemud_packet_server_data_u.listDomainsReply.domains[i] = domains[i];
D
Daniel P. Berrange 已提交
124
        }
125
        out->qemud_packet_server_data_u.listDomainsReply.numDomains = ndomains;
D
Daniel P. Berrange 已提交
126 127 128 129 130
    }
    return 0;
}

static int qemudDispatchNumDomains(struct qemud_server *server, struct qemud_client *client,
131
                                   struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
132 133 134 135 136
    int ndomains = qemudNumDomains(server);
    if (ndomains < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
137 138
        out->type = QEMUD_SERVER_PKT_NUM_DOMAINS;
        out->qemud_packet_server_data_u.numDomainsReply.numDomains = ndomains;
D
Daniel P. Berrange 已提交
139 140 141 142 143
    }
    return 0;
}

static int qemudDispatchDomainCreate(struct qemud_server *server, struct qemud_client *client,
144 145
                                     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';
D
Daniel P. Berrange 已提交
146

147
    struct qemud_vm *vm = qemudDomainCreate(server, in->qemud_packet_client_data_u.domainCreateRequest.xml);
D
Daniel P. Berrange 已提交
148 149 150 151
    if (!vm) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
152 153 154 155 156
        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';
D
Daniel P. Berrange 已提交
157 158 159 160 161
    }
    return 0;
}

static int qemudDispatchDomainLookupByID(struct qemud_server *server, struct qemud_client *client,
162 163
                                         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);
D
Daniel P. Berrange 已提交
164 165 166 167
    if (!vm) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
168 169 170 171
        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';
D
Daniel P. Berrange 已提交
172 173 174 175 176
    }
    return 0;
}

static int qemudDispatchDomainLookupByUUID(struct qemud_server *server, struct qemud_client *client,
177 178
                                           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);
D
Daniel P. Berrange 已提交
179 180 181 182
    if (!vm) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
183 184 185 186
        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';
D
Daniel P. Berrange 已提交
187 188 189 190 191
    }
    return 0;
}

static int qemudDispatchDomainLookupByName(struct qemud_server *server, struct qemud_client *client,
192
                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
193
    /* Paranoia NULL termination */
194 195
    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);
D
Daniel P. Berrange 已提交
196 197 198 199
    if (!vm) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
200 201 202
        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);
D
Daniel P. Berrange 已提交
203 204 205 206 207
    }
    return 0;
}

static int qemudDispatchDomainSuspend(struct qemud_server *server, struct qemud_client *client,
208 209
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    int ret = qemudDomainSuspend(server, in->qemud_packet_client_data_u.domainSuspendRequest.id);
D
Daniel P. Berrange 已提交
210 211 212 213
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
214
        out->type = QEMUD_SERVER_PKT_DOMAIN_SUSPEND;
D
Daniel P. Berrange 已提交
215 216 217 218 219
    }
    return 0;
}

static int qemudDispatchDomainResume(struct qemud_server *server, struct qemud_client *client,
220 221
                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    int ret = qemudDomainResume(server, in->qemud_packet_client_data_u.domainResumeRequest.id);
D
Daniel P. Berrange 已提交
222 223 224 225
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
226
        out->type = QEMUD_SERVER_PKT_DOMAIN_RESUME;
D
Daniel P. Berrange 已提交
227 228 229 230 231
    }
    return 0;
}

static int qemudDispatchDomainDestroy(struct qemud_server *server, struct qemud_client *client,
232 233
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    if (qemudDomainDestroy(server, in->qemud_packet_client_data_u.domainDestroyRequest.id) < 0) {
D
Daniel P. Berrange 已提交
234 235 236
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
237
        out->type = QEMUD_SERVER_PKT_DOMAIN_DESTROY;
D
Daniel P. Berrange 已提交
238 239 240 241 242
    }
    return 0;
}

static int qemudDispatchDomainGetInfo(struct qemud_server *server, struct qemud_client *client,
243
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
244 245 246 247 248 249
    int runstate;
    unsigned long long cpuTime;
    unsigned long memory;
    unsigned long maxmem;
    unsigned int nrVirtCpu;

250
    int ret = qemudDomainGetInfo(server, in->qemud_packet_client_data_u.domainGetInfoRequest.uuid,
D
Daniel P. Berrange 已提交
251 252 253 254 255 256 257 258 259
                                 &runstate,
                                 &cpuTime,
                                 &maxmem,
                                 &memory,
                                 &nrVirtCpu);
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
260 261 262 263 264 265
        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;
D
Daniel P. Berrange 已提交
266 267 268 269 270
    }
    return 0;
}

static int qemudDispatchDomainSave(struct qemud_server *server, struct qemud_client *client,
271
                                   struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
272
    /* Paranoia NULL termination */
273
    in->qemud_packet_client_data_u.domainSaveRequest.file[PATH_MAX-1] ='\0';
D
Daniel P. Berrange 已提交
274 275

    int ret = qemudDomainSave(server,
276 277
                              in->qemud_packet_client_data_u.domainSaveRequest.id,
                              in->qemud_packet_client_data_u.domainSaveRequest.file);
D
Daniel P. Berrange 已提交
278 279 280 281
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
282
        out->type = QEMUD_SERVER_PKT_DOMAIN_SAVE;
D
Daniel P. Berrange 已提交
283 284 285 286 287
    }
    return 0;
}

static int qemudDispatchDomainRestore(struct qemud_server *server, struct qemud_client *client,
288
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
289 290 291
    int id;

    /* Paranoia null termination */
292
    in->qemud_packet_client_data_u.domainRestoreRequest.file[PATH_MAX-1] ='\0';
D
Daniel P. Berrange 已提交
293

294
    id = qemudDomainRestore(server, in->qemud_packet_client_data_u.domainRestoreRequest.file);
D
Daniel P. Berrange 已提交
295 296 297 298
    if (id < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
299 300
        out->type = QEMUD_SERVER_PKT_DOMAIN_RESTORE;
        out->qemud_packet_server_data_u.domainRestoreReply.id = id;
D
Daniel P. Berrange 已提交
301 302 303 304 305
    }
    return 0;
}

static int qemudDispatchDumpXML(struct qemud_server *server, struct qemud_client *client,
306
                                struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
307 308
    int ret;
    ret = qemudDomainDumpXML(server,
309 310
                             in->qemud_packet_client_data_u.domainDumpXMLRequest.uuid,
                             out->qemud_packet_server_data_u.domainDumpXMLReply.xml,
D
Daniel P. Berrange 已提交
311 312 313 314 315
                             QEMUD_MAX_XML_LEN);
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
316
        out->type = QEMUD_SERVER_PKT_DUMP_XML;
D
Daniel P. Berrange 已提交
317 318 319 320 321
    }
    return 0;
}

static int qemudDispatchListDefinedDomains(struct qemud_server *server, struct qemud_client *client,
322
                                           struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
323 324 325 326 327 328 329
    char **names;
    int i, ndomains;

    if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_DOMAINS)))
        return -1;

    for (i = 0 ; i < QEMUD_MAX_NUM_DOMAINS ; i++) {
330
        names[i] = &out->qemud_packet_server_data_u.listDefinedDomainsReply.domains[i*QEMUD_MAX_NAME_LEN];
D
Daniel P. Berrange 已提交
331 332 333 334 335 336 337 338 339 340
    }

    ndomains = qemudListDefinedDomains(server,
                                       names,
                                       QEMUD_MAX_NUM_DOMAINS);
    free(names);
    if (ndomains < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
341 342 343 344 345 346
        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]);
D
Daniel P. Berrange 已提交
347 348 349 350 351
    }
    return 0;
}

static int qemudDispatchNumDefinedDomains(struct qemud_server *server, struct qemud_client *client,
352
                                          struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
353 354 355 356 357
    int ndomains = qemudNumDefinedDomains(server);
    if (ndomains < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
358 359
        out->type = QEMUD_SERVER_PKT_NUM_DEFINED_DOMAINS;
        out->qemud_packet_server_data_u.numDefinedDomainsReply.numDomains = ndomains;
D
Daniel P. Berrange 已提交
360 361 362 363 364
    }
    return 0;
}

static int qemudDispatchDomainStart(struct qemud_server *server, struct qemud_client *client,
365
                                    struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
366 367
    struct qemud_vm *vm;

368
    if (!(vm = qemudDomainStart(server, in->qemud_packet_client_data_u.domainStartRequest.uuid))) {
D
Daniel P. Berrange 已提交
369 370 371
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
372 373
        out->type = QEMUD_SERVER_PKT_DOMAIN_START;
        out->qemud_packet_server_data_u.domainStartReply.id = vm->id;
D
Daniel P. Berrange 已提交
374 375 376 377 378
    }
    return 0;
}

static int qemudDispatchDomainDefine(struct qemud_server *server, struct qemud_client *client,
379 380
                                     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';
D
Daniel P. Berrange 已提交
381

382
    struct qemud_vm *vm = qemudDomainDefine(server, in->qemud_packet_client_data_u.domainDefineRequest.xml);
D
Daniel P. Berrange 已提交
383 384 385 386
    if (!vm) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
387 388 389 390
        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';
D
Daniel P. Berrange 已提交
391 392 393 394 395
    }
    return 0;
}

static int qemudDispatchDomainUndefine(struct qemud_server *server, struct qemud_client *client,
396 397
                                       struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    int ret = qemudDomainUndefine(server, in->qemud_packet_client_data_u.domainUndefineRequest.uuid);
D
Daniel P. Berrange 已提交
398 399 400 401
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
402
        out->type = QEMUD_SERVER_PKT_DOMAIN_UNDEFINE;
D
Daniel P. Berrange 已提交
403 404 405 406
    }
    return 0;
}

407
static int qemudDispatchNumNetworks(struct qemud_server *server, struct qemud_client *client,
408
                                    struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
409 410 411 412 413
    int nnetworks = qemudNumNetworks(server);
    if (nnetworks < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
414 415
        out->type = QEMUD_SERVER_PKT_NUM_NETWORKS;
        out->qemud_packet_server_data_u.numNetworksReply.numNetworks = nnetworks;
416 417 418 419 420
    }
    return 0;
}

static int qemudDispatchListNetworks(struct qemud_server *server, struct qemud_client *client,
421
                                     struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
422 423 424 425 426 427 428
    char **names;
    int i;

    if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_NETWORKS)))
        return -1;

    for (i = 0 ; i < QEMUD_MAX_NUM_NETWORKS ; i++) {
429
        names[i] = &out->qemud_packet_server_data_u.listNetworksReply.networks[i*QEMUD_MAX_NAME_LEN];
430 431 432 433 434 435 436 437 438 439
    }

    int nnetworks = qemudListNetworks(server,
                                      names,
                                      QEMUD_MAX_NUM_NETWORKS);
    free(names);
    if (nnetworks < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
440 441
        out->type = QEMUD_SERVER_PKT_LIST_NETWORKS;
        out->qemud_packet_server_data_u.listNetworksReply.numNetworks = nnetworks;
442 443 444 445 446
    }
    return 0;
}

static int qemudDispatchNumDefinedNetworks(struct qemud_server *server, struct qemud_client *client,
447
                                           struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
448 449 450 451 452
    int nnetworks = qemudNumDefinedNetworks(server);
    if (nnetworks < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
453 454
        out->type = QEMUD_SERVER_PKT_NUM_DEFINED_NETWORKS;
        out->qemud_packet_server_data_u.numDefinedNetworksReply.numNetworks = nnetworks;
455 456 457 458 459
    }
    return 0;
}

static int qemudDispatchListDefinedNetworks(struct qemud_server *server, struct qemud_client *client,
460
                                            struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
461 462 463 464 465 466 467
    char **names;
    int i;

    if (!(names = malloc(sizeof(char *)*QEMUD_MAX_NUM_NETWORKS)))
        return -1;

    for (i = 0 ; i < QEMUD_MAX_NUM_NETWORKS ; i++) {
468
        names[i] = &out->qemud_packet_server_data_u.listDefinedNetworksReply.networks[i*QEMUD_MAX_NAME_LEN];
469 470 471 472 473 474 475 476 477 478
    }

    int nnetworks = qemudListDefinedNetworks(server,
                                             names,
                                             QEMUD_MAX_NUM_NETWORKS);
    free(names);
    if (nnetworks < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
479 480
        out->type = QEMUD_SERVER_PKT_LIST_DEFINED_NETWORKS;
        out->qemud_packet_server_data_u.listDefinedNetworksReply.numNetworks = nnetworks;
481 482 483 484 485
    }
    return 0;
}

static int qemudDispatchNetworkLookupByName(struct qemud_server *server, struct qemud_client *client,
486
                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
487
    /* Paranoia NULL termination */
488 489
    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);
490 491 492 493
    if (!network) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
494 495
        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);
496 497 498 499 500
    }
    return 0;
}

static int qemudDispatchNetworkLookupByUUID(struct qemud_server *server, struct qemud_client *client,
501 502
                                            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);
503 504 505 506
    if (!network) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
507 508 509
        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';
510 511 512 513 514
    }
    return 0;
}

static int qemudDispatchNetworkCreate(struct qemud_server *server, struct qemud_client *client,
515 516
                                      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';
517

518
    struct qemud_network *network = qemudNetworkCreate(server, in->qemud_packet_client_data_u.networkCreateRequest.xml);
519 520 521 522
    if (!network) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
523 524 525 526
        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';
527 528 529 530 531
    }
    return 0;
}

static int qemudDispatchNetworkDefine(struct qemud_server *server, struct qemud_client *client,
532 533
                                      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';
534

535
    struct qemud_network *network = qemudNetworkDefine(server, in->qemud_packet_client_data_u.networkDefineRequest.xml);
536 537 538 539
    if (!network) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
540 541 542 543
        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';
544 545 546 547 548
    }
    return 0;
}

static int qemudDispatchNetworkUndefine(struct qemud_server *server, struct qemud_client *client,
549 550
                                        struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    int ret = qemudNetworkUndefine(server, in->qemud_packet_client_data_u.networkUndefineRequest.uuid);
551 552 553 554
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
555
        out->type = QEMUD_SERVER_PKT_NETWORK_UNDEFINE;
556 557 558 559 560
    }
    return 0;
}

static int qemudDispatchNetworkStart(struct qemud_server *server, struct qemud_client *client,
561
                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
562 563
    struct qemud_network *network;

564
    if (!(network = qemudNetworkStart(server, in->qemud_packet_client_data_u.networkStartRequest.uuid))) {
565 566 567
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
568
        out->type = QEMUD_SERVER_PKT_NETWORK_START;
569 570 571 572 573
    }
    return 0;
}

static int qemudDispatchNetworkDestroy(struct qemud_server *server, struct qemud_client *client,
574 575
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    if (qemudNetworkDestroy(server, in->qemud_packet_client_data_u.networkDestroyRequest.uuid) < 0) {
576 577 578
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
579
        out->type = QEMUD_SERVER_PKT_NETWORK_DESTROY;
580 581 582 583 584
    }
    return 0;
}

static int qemudDispatchNetworkDumpXML(struct qemud_server *server, struct qemud_client *client,
585
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
586
    int ret = qemudNetworkDumpXML(server,
587 588
                                  in->qemud_packet_client_data_u.networkDumpXMLRequest.uuid,
                                  out->qemud_packet_server_data_u.networkDumpXMLReply.xml, QEMUD_MAX_XML_LEN);
589 590 591 592
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
593
        out->type = QEMUD_SERVER_PKT_NETWORK_DUMP_XML;
594 595 596 597
    }
    return 0;
}

598
static int qemudDispatchNetworkGetBridgeName(struct qemud_server *server, struct qemud_client *client,
599
                                             struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
600
    int ret = qemudNetworkGetBridgeName(server,
601 602
                                        in->qemud_packet_client_data_u.networkDumpXMLRequest.uuid,
                                        out->qemud_packet_server_data_u.networkGetBridgeNameReply.ifname, QEMUD_MAX_IFNAME_LEN);
603 604 605 606
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
607
        out->type = QEMUD_SERVER_PKT_NETWORK_GET_BRIDGE_NAME;
608 609 610 611
    }
    return 0;
}

612
static int qemudDispatchDomainGetAutostart(struct qemud_server *server, struct qemud_client *client,
613
                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
614 615 616 617 618 619 620
{
    int ret;
    int autostart;

    autostart = 0;

    ret = qemudDomainGetAutostart(server,
621
                                  in->qemud_packet_client_data_u.domainGetAutostartRequest.uuid,
622 623 624 625 626
                                  &autostart);
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
627 628
        out->type = QEMUD_SERVER_PKT_DOMAIN_GET_AUTOSTART;
        out->qemud_packet_server_data_u.networkGetAutostartReply.autostart = (autostart != 0);
629 630 631 632 633
    }
    return 0;
}

static int qemudDispatchDomainSetAutostart(struct qemud_server *server, struct qemud_client *client,
634
                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
635 636 637 638
{
    int ret;

    ret = qemudDomainSetAutostart(server,
639 640
                                  in->qemud_packet_client_data_u.domainGetAutostartRequest.uuid,
                                  in->qemud_packet_client_data_u.domainSetAutostartRequest.autostart);
641 642 643 644
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
645
        out->type = QEMUD_SERVER_PKT_DOMAIN_SET_AUTOSTART;
646 647 648 649 650
    }
    return 0;
}

static int qemudDispatchNetworkGetAutostart(struct qemud_server *server, struct qemud_client *client,
651
                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
652 653 654 655 656 657 658
{
    int ret;
    int autostart;

    autostart = 0;

    ret = qemudNetworkGetAutostart(server,
659
                                   in->qemud_packet_client_data_u.networkGetAutostartRequest.uuid,
660 661 662 663 664
                                   &autostart);
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
665 666
        out->type = QEMUD_SERVER_PKT_NETWORK_GET_AUTOSTART;
        out->qemud_packet_server_data_u.networkGetAutostartReply.autostart = (autostart != 0);
667 668 669 670 671
    }
    return 0;
}

static int qemudDispatchNetworkSetAutostart(struct qemud_server *server, struct qemud_client *client,
672
                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
673 674 675 676
{
    int ret;

    ret = qemudNetworkSetAutostart(server,
677 678
                                   in->qemud_packet_client_data_u.networkGetAutostartRequest.uuid,
                                   in->qemud_packet_client_data_u.networkSetAutostartRequest.autostart);
679 680 681 682
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
683
        out->type = QEMUD_SERVER_PKT_NETWORK_SET_AUTOSTART;
684 685 686
    }
    return 0;
}
D
Daniel P. Berrange 已提交
687 688

typedef int (*clientFunc)(struct qemud_server *server, struct qemud_client *client,
689
                          struct qemud_packet_client_data *in, struct qemud_packet_server_data *out);
D
Daniel P. Berrange 已提交
690 691 692 693


/* One per message type recorded in qemud_packet_type enum */

694
clientFunc funcsTransmitRW[QEMUD_CLIENT_PKT_MAX] = {
D
Daniel P. Berrange 已提交
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
    qemudDispatchGetVersion,
    qemudDispatchGetNodeInfo,
    qemudDispatchListDomains,
    qemudDispatchNumDomains,
    qemudDispatchDomainCreate,
    qemudDispatchDomainLookupByID,
    qemudDispatchDomainLookupByUUID,
    qemudDispatchDomainLookupByName,
    qemudDispatchDomainSuspend,
    qemudDispatchDomainResume,
    qemudDispatchDomainDestroy,
    qemudDispatchDomainGetInfo,
    qemudDispatchDomainSave,
    qemudDispatchDomainRestore,
    qemudDispatchDumpXML,
    qemudDispatchListDefinedDomains,
    qemudDispatchNumDefinedDomains,
    qemudDispatchDomainStart,
    qemudDispatchDomainDefine,
714 715 716 717 718 719 720 721 722 723 724 725 726
    qemudDispatchDomainUndefine,
    qemudDispatchNumNetworks,
    qemudDispatchListNetworks,
    qemudDispatchNumDefinedNetworks,
    qemudDispatchListDefinedNetworks,
    qemudDispatchNetworkLookupByUUID,
    qemudDispatchNetworkLookupByName,
    qemudDispatchNetworkCreate,
    qemudDispatchNetworkDefine,
    qemudDispatchNetworkUndefine,
    qemudDispatchNetworkStart,
    qemudDispatchNetworkDestroy,
    qemudDispatchNetworkDumpXML,
727
    qemudDispatchNetworkGetBridgeName,
728 729 730 731
    qemudDispatchDomainGetAutostart,
    qemudDispatchDomainSetAutostart,
    qemudDispatchNetworkGetAutostart,
    qemudDispatchNetworkSetAutostart,
732
    qemudDispatchGetCapabilities,
D
Daniel P. Berrange 已提交
733 734
};

735
clientFunc funcsTransmitRO[QEMUD_CLIENT_PKT_MAX] = {
D
Daniel P. Berrange 已提交
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755
    qemudDispatchGetVersion,
    qemudDispatchGetNodeInfo,
    qemudDispatchListDomains,
    qemudDispatchNumDomains,
    NULL,
    qemudDispatchDomainLookupByID,
    qemudDispatchDomainLookupByUUID,
    qemudDispatchDomainLookupByName,
    NULL,
    NULL,
    NULL,
    qemudDispatchDomainGetInfo,
    NULL,
    NULL,
    qemudDispatchDumpXML,
    qemudDispatchListDefinedDomains,
    qemudDispatchNumDefinedDomains,
    NULL,
    NULL,
    NULL,
756 757 758 759 760 761 762 763 764 765 766 767
    qemudDispatchNumNetworks,
    qemudDispatchListNetworks,
    qemudDispatchNumDefinedNetworks,
    qemudDispatchListDefinedNetworks,
    qemudDispatchNetworkLookupByUUID,
    qemudDispatchNetworkLookupByName,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    qemudDispatchNetworkDumpXML,
768
    qemudDispatchNetworkGetBridgeName,
769 770 771 772
    qemudDispatchDomainGetAutostart,
    NULL,
    qemudDispatchNetworkGetAutostart,
    NULL,
D
Daniel P. Berrange 已提交
773 774 775 776 777 778 779 780 781 782 783 784 785
};

/*
 * Returns -1 if message processing failed - eg, illegal header sizes,
 * a memory error dealing with stuff, or any other bad stuff which
 * should trigger immediate client disconnect
 *
 * Return 0 if message processing succeeded. NB, this does not mean
 * the operation itself succeeded - success/failure of the operation
 * is recorded by the return message type - either it matches the
 * incoming type, or is QEMUD_PKT_FAILURE
 */
int qemudDispatch(struct qemud_server *server, struct qemud_client *client,
786
                  qemud_packet_client_data *in, qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
787
    clientFunc *funcs;
788 789 790
    unsigned int type = in->type;
    qemudDebug("> Dispatching request type %d, readonly ? %d",
               in->type, client->readonly);
D
Daniel P. Berrange 已提交
791

792
    virResetLastError();
D
Daniel P. Berrange 已提交
793

794
    memset(out, 0, sizeof(*out));
D
Daniel P. Berrange 已提交
795

796
    if (type >= QEMUD_CLIENT_PKT_MAX) {
797
        qemudDebug("Illegal request type");
D
Daniel P. Berrange 已提交
798 799 800 801 802 803 804 805 806
        return -1;
    }

    if (client->readonly)
        funcs = funcsTransmitRO;
    else
        funcs = funcsTransmitRW;

    if (!funcs[type]) {
807
        qemudDebug("Illegal operation requested");
808
        qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_DENIED, NULL);
D
Daniel P. Berrange 已提交
809 810 811
        qemudDispatchFailure(server, client, out);
    } else {
        if ((funcs[type])(server, client, in, out) < 0) {
812
            qemudDebug("Dispatch failed");
D
Daniel P. Berrange 已提交
813 814 815 816
            return -1;
        }
    }

817
    qemudDebug("< Returning reply %d", out->type);
D
Daniel P. Berrange 已提交
818 819 820 821 822 823 824 825 826 827 828 829

    return 0;
}

/*
 * Local variables:
 *  indent-tabs-mode: nil
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  tab-width: 4
 * End:
 */