dispatch.c 33.2 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 42 43 44
                                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);
D
Daniel P. Berrange 已提交
45 46 47 48 49
    return 0;
}


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

static int qemudDispatchGetNodeInfo(struct qemud_server *server, struct qemud_client *client,
63
                                    struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
64 65 66 67 68 69 70 71 72
    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 已提交
73 74 75 76 77
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
        return 0;
    }

78 79
    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 已提交
80 81 82 83

    return 0;
}

84 85 86
static int
qemudDispatchGetCapabilities (struct qemud_server *server,
                              struct qemud_client *client,
87 88
                              struct qemud_packet_client_data *in ATTRIBUTE_UNUSED,
                              struct qemud_packet_server_data *out)
89
{
90
    char *xml = qemudGetCapabilities(server);
91

92
    if (strlen(xml) > QEMUD_MAX_XML_LEN) {
93 94
        qemudReportError (server, VIR_ERR_XML_ERROR, NULL);
        qemudDispatchFailure (server, client, out);
95
        free(xml);
96 97
        return 0;
    }
98

99
    out->type = QEMUD_SERVER_PKT_GET_CAPABILITIES;
100 101
    strcpy (out->qemud_packet_server_data_u.getCapabilitiesReply.xml, xml);
    free(xml);
102 103 104
    return 0;
}

D
Daniel P. Berrange 已提交
105
static int qemudDispatchListDomains(struct qemud_server *server, struct qemud_client *client,
106
                                    struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
107 108 109 110 111 112 113 114 115
    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 {
116
        out->type = QEMUD_SERVER_PKT_LIST_DOMAINS;
D
Daniel P. Berrange 已提交
117
        for (i = 0 ; i < ndomains ; i++) {
118
            out->qemud_packet_server_data_u.listDomainsReply.domains[i] = domains[i];
D
Daniel P. Berrange 已提交
119
        }
120
        out->qemud_packet_server_data_u.listDomainsReply.numDomains = ndomains;
D
Daniel P. Berrange 已提交
121 122 123 124 125
    }
    return 0;
}

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

static int qemudDispatchDomainCreate(struct qemud_server *server, struct qemud_client *client,
139 140
                                     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 已提交
141

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

static int qemudDispatchDomainLookupByID(struct qemud_server *server, struct qemud_client *client,
157 158
                                         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 已提交
159 160 161 162
    if (!vm) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
163 164 165 166
        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 已提交
167 168 169 170 171
    }
    return 0;
}

static int qemudDispatchDomainLookupByUUID(struct qemud_server *server, struct qemud_client *client,
172 173
                                           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 已提交
174 175 176 177
    if (!vm) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
178 179 180 181
        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 已提交
182 183 184 185 186
    }
    return 0;
}

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

static int qemudDispatchDomainSuspend(struct qemud_server *server, struct qemud_client *client,
203 204
                                      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 已提交
205 206 207 208
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
209
        out->type = QEMUD_SERVER_PKT_DOMAIN_SUSPEND;
D
Daniel P. Berrange 已提交
210 211 212 213 214
    }
    return 0;
}

static int qemudDispatchDomainResume(struct qemud_server *server, struct qemud_client *client,
215 216
                                     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 已提交
217 218 219 220
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
221
        out->type = QEMUD_SERVER_PKT_DOMAIN_RESUME;
D
Daniel P. Berrange 已提交
222 223 224 225 226
    }
    return 0;
}

static int qemudDispatchDomainDestroy(struct qemud_server *server, struct qemud_client *client,
227 228
                                      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 已提交
229 230 231
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
232
        out->type = QEMUD_SERVER_PKT_DOMAIN_DESTROY;
D
Daniel P. Berrange 已提交
233 234 235 236 237
    }
    return 0;
}

static int qemudDispatchDomainGetInfo(struct qemud_server *server, struct qemud_client *client,
238
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
239 240 241 242 243 244
    int runstate;
    unsigned long long cpuTime;
    unsigned long memory;
    unsigned long maxmem;
    unsigned int nrVirtCpu;

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

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

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

static int qemudDispatchDomainRestore(struct qemud_server *server, struct qemud_client *client,
283
                                      struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
284 285 286
    int id;

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

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

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

static int qemudDispatchListDefinedDomains(struct qemud_server *server, struct qemud_client *client,
317
                                           struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
318 319 320 321 322 323 324
    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++) {
325
        names[i] = &out->qemud_packet_server_data_u.listDefinedDomainsReply.domains[i*QEMUD_MAX_NAME_LEN];
D
Daniel P. Berrange 已提交
326 327 328 329 330 331 332 333 334 335
    }

    ndomains = qemudListDefinedDomains(server,
                                       names,
                                       QEMUD_MAX_NUM_DOMAINS);
    free(names);
    if (ndomains < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
336 337 338 339 340 341
        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 已提交
342 343 344 345 346
    }
    return 0;
}

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

static int qemudDispatchDomainStart(struct qemud_server *server, struct qemud_client *client,
360
                                    struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
361 362
    struct qemud_vm *vm;

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

static int qemudDispatchDomainDefine(struct qemud_server *server, struct qemud_client *client,
374 375
                                     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 已提交
376

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

static int qemudDispatchDomainUndefine(struct qemud_server *server, struct qemud_client *client,
391 392
                                       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 已提交
393 394 395 396
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
397
        out->type = QEMUD_SERVER_PKT_DOMAIN_UNDEFINE;
D
Daniel P. Berrange 已提交
398 399 400 401
    }
    return 0;
}

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

static int qemudDispatchListNetworks(struct qemud_server *server, struct qemud_client *client,
416
                                     struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
417 418 419 420 421 422 423
    char **names;
    int i;

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

    for (i = 0 ; i < QEMUD_MAX_NUM_NETWORKS ; i++) {
424
        names[i] = &out->qemud_packet_server_data_u.listNetworksReply.networks[i*QEMUD_MAX_NAME_LEN];
425 426 427 428 429 430 431 432 433 434
    }

    int nnetworks = qemudListNetworks(server,
                                      names,
                                      QEMUD_MAX_NUM_NETWORKS);
    free(names);
    if (nnetworks < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
435 436
        out->type = QEMUD_SERVER_PKT_LIST_NETWORKS;
        out->qemud_packet_server_data_u.listNetworksReply.numNetworks = nnetworks;
437 438 439 440 441
    }
    return 0;
}

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

static int qemudDispatchListDefinedNetworks(struct qemud_server *server, struct qemud_client *client,
455
                                            struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
456 457 458 459 460 461 462
    char **names;
    int i;

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

    for (i = 0 ; i < QEMUD_MAX_NUM_NETWORKS ; i++) {
463
        names[i] = &out->qemud_packet_server_data_u.listDefinedNetworksReply.networks[i*QEMUD_MAX_NAME_LEN];
464 465 466 467 468 469 470 471 472 473
    }

    int nnetworks = qemudListDefinedNetworks(server,
                                             names,
                                             QEMUD_MAX_NUM_NETWORKS);
    free(names);
    if (nnetworks < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
474 475
        out->type = QEMUD_SERVER_PKT_LIST_DEFINED_NETWORKS;
        out->qemud_packet_server_data_u.listDefinedNetworksReply.numNetworks = nnetworks;
476 477 478 479 480
    }
    return 0;
}

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

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

static int qemudDispatchNetworkCreate(struct qemud_server *server, struct qemud_client *client,
510 511
                                      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';
512

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

static int qemudDispatchNetworkDefine(struct qemud_server *server, struct qemud_client *client,
527 528
                                      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';
529

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

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

static int qemudDispatchNetworkStart(struct qemud_server *server, struct qemud_client *client,
556
                                     struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
557 558
    struct qemud_network *network;

559
    if (!(network = qemudNetworkStart(server, in->qemud_packet_client_data_u.networkStartRequest.uuid))) {
560 561 562
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
563
        out->type = QEMUD_SERVER_PKT_NETWORK_START;
564 565 566 567 568
    }
    return 0;
}

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

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

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

607
static int qemudDispatchDomainGetAutostart(struct qemud_server *server, struct qemud_client *client,
608
                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
609 610 611 612 613 614 615
{
    int ret;
    int autostart;

    autostart = 0;

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

static int qemudDispatchDomainSetAutostart(struct qemud_server *server, struct qemud_client *client,
629
                                           struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
630 631 632 633
{
    int ret;

    ret = qemudDomainSetAutostart(server,
634 635
                                  in->qemud_packet_client_data_u.domainGetAutostartRequest.uuid,
                                  in->qemud_packet_client_data_u.domainSetAutostartRequest.autostart);
636 637 638 639
    if (ret < 0) {
        if (qemudDispatchFailure(server, client, out) < 0)
            return -1;
    } else {
640
        out->type = QEMUD_SERVER_PKT_DOMAIN_SET_AUTOSTART;
641 642 643 644 645
    }
    return 0;
}

static int qemudDispatchNetworkGetAutostart(struct qemud_server *server, struct qemud_client *client,
646
                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
647 648 649 650 651 652 653
{
    int ret;
    int autostart;

    autostart = 0;

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

static int qemudDispatchNetworkSetAutostart(struct qemud_server *server, struct qemud_client *client,
667
                                            struct qemud_packet_client_data *in, struct qemud_packet_server_data *out)
668 669 670 671
{
    int ret;

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

typedef int (*clientFunc)(struct qemud_server *server, struct qemud_client *client,
684
                          struct qemud_packet_client_data *in, struct qemud_packet_server_data *out);
D
Daniel P. Berrange 已提交
685 686 687 688


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

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

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

/*
 * 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,
781
                  qemud_packet_client_data *in, qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
782
    clientFunc *funcs;
783 784 785
    unsigned int type = in->type;
    qemudDebug("> Dispatching request type %d, readonly ? %d",
               in->type, client->readonly);
D
Daniel P. Berrange 已提交
786 787 788 789

    server->errorCode = 0;
    server->errorMessage[0] = '\0';

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

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

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

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

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

    return 0;
}

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