dispatch.c 31.9 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"
37
extern struct qemud_driver *qemu_driver;
D
Daniel P. Berrange 已提交
38 39


40 41
static virConnect conn;

42
static int qemudDispatchFailure(struct qemud_packet_server_data *out) {
43
    virErrorPtr err = virGetLastError();
44 45
    if (!err)
        err = virConnGetLastError(&conn);
46

47
    out->type = QEMUD_SERVER_PKT_FAILURE;
48

49 50 51 52 53 54 55 56 57 58
    if (err) {
        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';
    } else {
        out->qemud_packet_server_data_u.failureReply.code = VIR_ERR_INTERNAL_ERROR;
        strcpy(out->qemud_packet_server_data_u.failureReply.message,
               "Unknown error");
    }
D
Daniel P. Berrange 已提交
59 60 61 62
    return 0;
}


63
static int qemudDispatchGetVersion(struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
64 65 66 67
    int ret;
    unsigned long version;
    ret = qemudGetVersion(&conn, &version);
    if (ret < 0) {
68
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
69 70
            return -1;
    } else {
71 72
        out->type = QEMUD_SERVER_PKT_GET_VERSION;
        out->qemud_packet_server_data_u.getVersionReply.versionNum = version;
D
Daniel P. Berrange 已提交
73 74 75 76
    }
    return 0;
}

77
static int qemudDispatchGetNodeInfo(struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
78 79 80
    virNodeInfo info;
    if (qemudGetNodeInfo(&conn,
                         &info) < 0) {
81
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
82 83 84 85
            return -1;
        return 0;
    }

86 87 88 89 90 91 92 93
    out->qemud_packet_server_data_u.getNodeInfoReply.memory = info.memory;
    out->qemud_packet_server_data_u.getNodeInfoReply.cpus = info.cpus;
    out->qemud_packet_server_data_u.getNodeInfoReply.mhz = info.mhz;
    out->qemud_packet_server_data_u.getNodeInfoReply.nodes = info.nodes;
    out->qemud_packet_server_data_u.getNodeInfoReply.sockets = info.sockets;
    out->qemud_packet_server_data_u.getNodeInfoReply.cores = info.cores;
    out->qemud_packet_server_data_u.getNodeInfoReply.threads = info.threads;

94
    out->type = QEMUD_SERVER_PKT_GET_NODEINFO;
95 96
    strncpy(out->qemud_packet_server_data_u.getNodeInfoReply.model, info.model,
            sizeof(out->qemud_packet_server_data_u.getNodeInfoReply.model)-1);
97
    out->qemud_packet_server_data_u.getNodeInfoReply.model[sizeof(out->qemud_packet_server_data_u.getNodeInfoReply.model)-1] = '\0';
D
Daniel P. Berrange 已提交
98 99 100 101

    return 0;
}

102
static int
103
qemudDispatchGetCapabilities (struct qemud_packet_client_data *in ATTRIBUTE_UNUSED,
104
                              struct qemud_packet_server_data *out)
105
{
106
    char *xml = qemudGetCapabilities(&conn);
107

108
    if (strlen(xml) > QEMUD_MAX_XML_LEN) {
109
        qemudReportError(&conn, NULL, NULL, VIR_ERR_XML_ERROR, NULL);
110
        qemudDispatchFailure(out);
111
        free(xml);
112 113
        return 0;
    }
114

115
    out->type = QEMUD_SERVER_PKT_GET_CAPABILITIES;
116 117
    strcpy (out->qemud_packet_server_data_u.getCapabilitiesReply.xml, xml);
    free(xml);
118 119 120
    return 0;
}

121
static int qemudDispatchListDomains(struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
122 123
    int i, ndomains, domains[QEMUD_MAX_NUM_DOMAINS];

124
    ndomains = qemudListDomains(&conn,
D
Daniel P. Berrange 已提交
125 126 127
                                domains,
                                QEMUD_MAX_NUM_DOMAINS);
    if (ndomains < 0) {
128
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
129 130
            return -1;
    } else {
131
        out->type = QEMUD_SERVER_PKT_LIST_DOMAINS;
D
Daniel P. Berrange 已提交
132
        for (i = 0 ; i < ndomains ; i++) {
133
            out->qemud_packet_server_data_u.listDomainsReply.domains[i] = domains[i];
D
Daniel P. Berrange 已提交
134
        }
135
        out->qemud_packet_server_data_u.listDomainsReply.numDomains = ndomains;
D
Daniel P. Berrange 已提交
136 137 138 139
    }
    return 0;
}

140
static int qemudDispatchNumDomains(struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
141
    int ndomains = qemudNumDomains(&conn);
D
Daniel P. Berrange 已提交
142
    if (ndomains < 0) {
143
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
144 145
            return -1;
    } else {
146 147
        out->type = QEMUD_SERVER_PKT_NUM_DOMAINS;
        out->qemud_packet_server_data_u.numDomainsReply.numDomains = ndomains;
D
Daniel P. Berrange 已提交
148 149 150 151
    }
    return 0;
}

152
static int qemudDispatchDomainCreate(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
153
    in->qemud_packet_client_data_u.domainCreateRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
D
Daniel P. Berrange 已提交
154

155 156
    virDomainPtr dom = qemudDomainCreate(&conn, in->qemud_packet_client_data_u.domainCreateRequest.xml, 0);
    if (!dom) {
157
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
158 159
            return -1;
    } else {
160
        out->type = QEMUD_SERVER_PKT_DOMAIN_CREATE;
161 162 163
        out->qemud_packet_server_data_u.domainCreateReply.id = dom->id;
        memcpy(out->qemud_packet_server_data_u.domainCreateReply.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
        strncpy(out->qemud_packet_server_data_u.domainCreateReply.name, dom->name, QEMUD_MAX_NAME_LEN-1);
164
        out->qemud_packet_server_data_u.domainCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
165
        free(dom);
D
Daniel P. Berrange 已提交
166 167 168 169
    }
    return 0;
}

170
static int qemudDispatchDomainLookupByID(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
171 172
    virDomainPtr dom = qemudDomainLookupByID(&conn, in->qemud_packet_client_data_u.domainLookupByIDRequest.id);
    if (!dom) {
173
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
174 175
            return -1;
    } else {
176
        out->type = QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_ID;
177 178
        memcpy(out->qemud_packet_server_data_u.domainLookupByIDReply.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
        strncpy(out->qemud_packet_server_data_u.domainLookupByIDReply.name, dom->name, QEMUD_MAX_NAME_LEN-1);
179
        out->qemud_packet_server_data_u.domainLookupByIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
180
        free(dom);
D
Daniel P. Berrange 已提交
181 182 183 184
    }
    return 0;
}

185
static int qemudDispatchDomainLookupByUUID(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
186 187
    virDomainPtr dom = qemudDomainLookupByUUID(&conn, in->qemud_packet_client_data_u.domainLookupByUUIDRequest.uuid);
    if (!dom) {
188
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
189 190
            return -1;
    } else {
191
        out->type = QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_UUID;
192 193
        out->qemud_packet_server_data_u.domainLookupByUUIDReply.id = dom->id;
        strncpy(out->qemud_packet_server_data_u.domainLookupByUUIDReply.name, dom->name, QEMUD_MAX_NAME_LEN-1);
194
        out->qemud_packet_server_data_u.domainLookupByUUIDReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
195
        free(dom);
D
Daniel P. Berrange 已提交
196 197 198 199
    }
    return 0;
}

200
static int qemudDispatchDomainLookupByName(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
201
    /* Paranoia NULL termination */
202
    in->qemud_packet_client_data_u.domainLookupByNameRequest.name[QEMUD_MAX_NAME_LEN-1] = '\0';
203 204
    virDomainPtr dom = qemudDomainLookupByName(&conn, in->qemud_packet_client_data_u.domainLookupByNameRequest.name);
    if (!dom) {
205
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
206 207
            return -1;
    } else {
208
        out->type = QEMUD_SERVER_PKT_DOMAIN_LOOKUP_BY_NAME;
209 210 211
        out->qemud_packet_server_data_u.domainLookupByNameReply.id = dom->id;
        memcpy(out->qemud_packet_server_data_u.domainLookupByNameReply.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
        free(dom);
D
Daniel P. Berrange 已提交
212 213 214 215
    }
    return 0;
}

216
static int qemudDispatchDomainSuspend(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
217 218 219 220 221 222 223 224 225 226
    virDomainPtr dom = qemudDomainLookupByID(&conn, in->qemud_packet_client_data_u.domainSuspendRequest.id);
    int ret;
    if (!dom) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
        return 0;
    }

    ret = qemudDomainSuspend(dom);
    free(dom);
D
Daniel P. Berrange 已提交
227
    if (ret < 0) {
228
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
229 230
            return -1;
    } else {
231
        out->type = QEMUD_SERVER_PKT_DOMAIN_SUSPEND;
D
Daniel P. Berrange 已提交
232 233 234 235
    }
    return 0;
}

236
static int qemudDispatchDomainResume(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
237 238 239 240 241 242 243 244 245 246
    virDomainPtr dom = qemudDomainLookupByID(&conn, in->qemud_packet_client_data_u.domainResumeRequest.id);
    int ret;
    if (!dom) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
        return 0;
    }

    ret = qemudDomainResume(dom);
    free(dom);
D
Daniel P. Berrange 已提交
247
    if (ret < 0) {
248
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
249 250
            return -1;
    } else {
251
        out->type = QEMUD_SERVER_PKT_DOMAIN_RESUME;
D
Daniel P. Berrange 已提交
252 253 254 255
    }
    return 0;
}

256
static int qemudDispatchDomainDestroy(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
257 258 259 260 261 262 263 264 265 266 267
    virDomainPtr dom = qemudDomainLookupByID(&conn, in->qemud_packet_client_data_u.domainDestroyRequest.id);
    int ret;
    if (!dom) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
        return 0;
    }

    ret = qemudDomainDestroy(dom);
    free(dom);
    if (ret < 0) {
268
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
269 270
            return -1;
    } else {
271
        out->type = QEMUD_SERVER_PKT_DOMAIN_DESTROY;
D
Daniel P. Berrange 已提交
272 273 274 275
    }
    return 0;
}

276
static int qemudDispatchDomainGetInfo(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
277 278 279 280 281 282 283 284 285 286
    virDomainInfo info;
    virDomainPtr dom = qemudDomainLookupByUUID(&conn, in->qemud_packet_client_data_u.domainGetInfoRequest.uuid);

    if (!dom) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
        return 0;
    }

    if (qemudDomainGetInfo(dom, &info) < 0) {
287
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
288 289
            return -1;
    } else {
290
        out->type = QEMUD_SERVER_PKT_DOMAIN_GET_INFO;
291 292 293 294 295
        out->qemud_packet_server_data_u.domainGetInfoReply.runstate = info.state;
        out->qemud_packet_server_data_u.domainGetInfoReply.cpuTime = info.cpuTime;
        out->qemud_packet_server_data_u.domainGetInfoReply.maxmem = info.maxMem;
        out->qemud_packet_server_data_u.domainGetInfoReply.memory = info.memory;
        out->qemud_packet_server_data_u.domainGetInfoReply.nrVirtCpu = info.nrVirtCpu;
D
Daniel P. Berrange 已提交
296 297 298 299
    }
    return 0;
}

300
static int qemudDispatchDomainSave(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
301 302 303 304 305 306 307 308
    virDomainPtr dom = qemudDomainLookupByID(&conn, in->qemud_packet_client_data_u.domainSaveRequest.id);
    int ret;
    if (!dom) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
        return 0;
    }

D
Daniel P. Berrange 已提交
309
    /* Paranoia NULL termination */
310
    in->qemud_packet_client_data_u.domainSaveRequest.file[PATH_MAX-1] ='\0';
D
Daniel P. Berrange 已提交
311

312 313 314
    ret = qemudDomainSave(dom,
                          in->qemud_packet_client_data_u.domainSaveRequest.file);
    free(dom);
D
Daniel P. Berrange 已提交
315
    if (ret < 0) {
316
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
317 318
            return -1;
    } else {
319
        out->type = QEMUD_SERVER_PKT_DOMAIN_SAVE;
D
Daniel P. Berrange 已提交
320 321 322 323
    }
    return 0;
}

324
static int qemudDispatchDomainRestore(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
325
    int ret;
D
Daniel P. Berrange 已提交
326 327

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

330 331
    ret = qemudDomainRestore(&conn, in->qemud_packet_client_data_u.domainRestoreRequest.file);
    if (ret < 0) {
332
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
333 334
            return -1;
    } else {
335
        out->type = QEMUD_SERVER_PKT_DOMAIN_RESTORE;
336
        out->qemud_packet_server_data_u.domainRestoreReply.id = ret;
D
Daniel P. Berrange 已提交
337 338 339 340
    }
    return 0;
}

341
static int qemudDispatchDumpXML(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
342 343 344 345 346 347 348 349 350 351 352
    virDomainPtr dom = qemudDomainLookupByUUID(&conn, in->qemud_packet_client_data_u.domainDumpXMLRequest.uuid);
    char *ret;
    if (!dom) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
        return 0;
    }

    ret = qemudDomainDumpXML(dom, 0);
    free(dom);
    if (!ret) {
353
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
354 355
            return -1;
    } else {
356
        out->type = QEMUD_SERVER_PKT_DUMP_XML;
357 358 359 360
        strncpy(out->qemud_packet_server_data_u.domainDumpXMLReply.xml,
                ret, QEMUD_MAX_XML_LEN-1);
        out->qemud_packet_server_data_u.domainDumpXMLReply.xml[QEMUD_MAX_XML_LEN-1] = '\0';
        free(ret);
D
Daniel P. Berrange 已提交
361 362 363 364
    }
    return 0;
}

365
static int qemudDispatchListDefinedDomains(struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
366 367 368 369 370 371
    char **names;
    int i, ndomains;

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

372
    ndomains = qemudListDefinedDomains(&conn,
D
Daniel P. Berrange 已提交
373 374
                                       names,
                                       QEMUD_MAX_NUM_DOMAINS);
375 376 377 378 379 380 381
    for (i = 0 ; i < ndomains ; i++) {
        strncpy(&out->qemud_packet_server_data_u.listDefinedDomainsReply.domains[i*QEMUD_MAX_NAME_LEN],
                names[i],
                QEMUD_MAX_NAME_LEN);
        free(names[i]);
    }

D
Daniel P. Berrange 已提交
382 383
    free(names);
    if (ndomains < 0) {
384
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
385 386
            return -1;
    } else {
387 388 389
        out->type = QEMUD_SERVER_PKT_LIST_DEFINED_DOMAINS;
        out->qemud_packet_server_data_u.listDefinedDomainsReply.numDomains = ndomains;
    }
D
Daniel P. Berrange 已提交
390 391 392
    return 0;
}

393
static int qemudDispatchNumDefinedDomains(struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
394
    int ndomains = qemudNumDefinedDomains(&conn);
D
Daniel P. Berrange 已提交
395
    if (ndomains < 0) {
396
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
397 398
            return -1;
    } else {
399 400
        out->type = QEMUD_SERVER_PKT_NUM_DEFINED_DOMAINS;
        out->qemud_packet_server_data_u.numDefinedDomainsReply.numDomains = ndomains;
D
Daniel P. Berrange 已提交
401 402 403 404
    }
    return 0;
}

405
static int qemudDispatchDomainStart(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
406 407 408 409 410 411 412
    virDomainPtr dom = qemudDomainLookupByUUID(&conn, in->qemud_packet_client_data_u.domainStartRequest.uuid);
    int ret;
    if (!dom) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
        return 0;
    }
413

414 415 416
    ret = qemudDomainStart(dom);
    free(dom);
    if (ret < 0) {
417
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
418 419
            return -1;
    } else {
420
        out->type = QEMUD_SERVER_PKT_DOMAIN_START;
421
        out->qemud_packet_server_data_u.domainStartReply.id = dom->id;
D
Daniel P. Berrange 已提交
422 423 424 425
    }
    return 0;
}

426
static int qemudDispatchDomainDefine(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
427
    in->qemud_packet_client_data_u.domainDefineRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
D
Daniel P. Berrange 已提交
428

429 430
    virDomainPtr dom = qemudDomainDefine(&conn, in->qemud_packet_client_data_u.domainDefineRequest.xml);
    if (!dom) {
431
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
432 433
            return -1;
    } else {
434
        out->type = QEMUD_SERVER_PKT_DOMAIN_DEFINE;
435 436
        memcpy(out->qemud_packet_server_data_u.domainDefineReply.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
        strncpy(out->qemud_packet_server_data_u.domainDefineReply.name, dom->name, QEMUD_MAX_NAME_LEN-1);
437
        out->qemud_packet_server_data_u.domainDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
D
Daniel P. Berrange 已提交
438 439 440 441
    }
    return 0;
}

442
static int qemudDispatchDomainUndefine(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
443 444 445 446 447 448 449 450 451
    virDomainPtr dom = qemudDomainLookupByUUID(&conn, in->qemud_packet_client_data_u.domainUndefineRequest.uuid);
    int ret;
    if (!dom) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
        return 0;
    }
    ret = qemudDomainUndefine(dom);
    free(dom);
D
Daniel P. Berrange 已提交
452
    if (ret < 0) {
453
        if (qemudDispatchFailure(out) < 0)
D
Daniel P. Berrange 已提交
454 455
            return -1;
    } else {
456
        out->type = QEMUD_SERVER_PKT_DOMAIN_UNDEFINE;
D
Daniel P. Berrange 已提交
457 458 459 460
    }
    return 0;
}

461
static int qemudDispatchNumNetworks(struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
462
    int nnetworks = qemudNumNetworks(&conn);
463
    if (nnetworks < 0) {
464
        if (qemudDispatchFailure(out) < 0)
465 466
            return -1;
    } else {
467 468
        out->type = QEMUD_SERVER_PKT_NUM_NETWORKS;
        out->qemud_packet_server_data_u.numNetworksReply.numNetworks = nnetworks;
469 470 471 472
    }
    return 0;
}

473
static int qemudDispatchListNetworks(struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
474 475 476 477 478 479
    char **names;
    int i;

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

480
    int nnetworks = qemudListNetworks(&conn,
481 482
                                      names,
                                      QEMUD_MAX_NUM_NETWORKS);
483 484 485 486 487 488
    for (i = 0 ; i < nnetworks ; i++) {
        strncpy(&out->qemud_packet_server_data_u.listNetworksReply.networks[i*QEMUD_MAX_NAME_LEN],
                names[i],
                QEMUD_MAX_NAME_LEN);
        free(names[i]);
    }
489 490
    free(names);
    if (nnetworks < 0) {
491
        if (qemudDispatchFailure(out) < 0)
492 493
            return -1;
    } else {
494 495
        out->type = QEMUD_SERVER_PKT_LIST_NETWORKS;
        out->qemud_packet_server_data_u.listNetworksReply.numNetworks = nnetworks;
496 497 498 499
    }
    return 0;
}

500
static int qemudDispatchNumDefinedNetworks(struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
501
    int nnetworks = qemudNumDefinedNetworks(&conn);
502
    if (nnetworks < 0) {
503
        if (qemudDispatchFailure(out) < 0)
504 505
            return -1;
    } else {
506 507
        out->type = QEMUD_SERVER_PKT_NUM_DEFINED_NETWORKS;
        out->qemud_packet_server_data_u.numDefinedNetworksReply.numNetworks = nnetworks;
508 509 510 511
    }
    return 0;
}

512
static int qemudDispatchListDefinedNetworks(struct qemud_packet_client_data *in ATTRIBUTE_UNUSED, struct qemud_packet_server_data *out) {
513 514 515 516 517 518
    char **names;
    int i;

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

519
    int nnetworks = qemudListDefinedNetworks(&conn,
520 521
                                             names,
                                             QEMUD_MAX_NUM_NETWORKS);
522 523 524 525 526 527 528

    for (i = 0 ; i < nnetworks ; i++) {
        strncpy(&out->qemud_packet_server_data_u.listDefinedNetworksReply.networks[i*QEMUD_MAX_NAME_LEN],
                names[i],
                QEMUD_MAX_NAME_LEN);
        free(names[i]);
    }
529 530
    free(names);
    if (nnetworks < 0) {
531
        if (qemudDispatchFailure(out) < 0)
532 533
            return -1;
    } else {
534 535
        out->type = QEMUD_SERVER_PKT_LIST_DEFINED_NETWORKS;
        out->qemud_packet_server_data_u.listDefinedNetworksReply.numNetworks = nnetworks;
536 537 538 539
    }
    return 0;
}

540
static int qemudDispatchNetworkLookupByName(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
541
    /* Paranoia NULL termination */
542
    in->qemud_packet_client_data_u.networkLookupByNameRequest.name[QEMUD_MAX_NAME_LEN-1] = '\0';
543
    struct qemud_network *network = qemudFindNetworkByName(qemu_driver, in->qemud_packet_client_data_u.networkLookupByNameRequest.name);
544
    if (!network) {
545
        if (qemudDispatchFailure(out) < 0)
546 547
            return -1;
    } else {
548 549
        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);
550 551 552 553
    }
    return 0;
}

554 555
static int qemudDispatchNetworkLookupByUUID(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    struct qemud_network *network = qemudFindNetworkByUUID(qemu_driver, in->qemud_packet_client_data_u.networkLookupByUUIDRequest.uuid);
556
    if (!network) {
557
        if (qemudDispatchFailure(out) < 0)
558 559
            return -1;
    } else {
560 561 562
        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';
563 564 565 566
    }
    return 0;
}

567
static int qemudDispatchNetworkCreate(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
568
    in->qemud_packet_client_data_u.networkCreateRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
569

570 571
    virNetworkPtr net = qemudNetworkCreate(&conn, in->qemud_packet_client_data_u.networkCreateRequest.xml);
    if (!net) {
572
        if (qemudDispatchFailure(out) < 0)
573 574
            return -1;
    } else {
575
        out->type = QEMUD_SERVER_PKT_NETWORK_CREATE;
576 577
        memcpy(out->qemud_packet_server_data_u.networkCreateReply.uuid, net->uuid, QEMUD_UUID_RAW_LEN);
        strncpy(out->qemud_packet_server_data_u.networkCreateReply.name, net->name, QEMUD_MAX_NAME_LEN-1);
578
        out->qemud_packet_server_data_u.networkCreateReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
579
        free(net);
580 581 582 583
    }
    return 0;
}

584
static int qemudDispatchNetworkDefine(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
585
    in->qemud_packet_client_data_u.networkDefineRequest.xml[QEMUD_MAX_XML_LEN-1] ='\0';
586

587 588
    virNetworkPtr net = qemudNetworkDefine(&conn, in->qemud_packet_client_data_u.networkDefineRequest.xml);
    if (!net) {
589
        if (qemudDispatchFailure(out) < 0)
590 591
            return -1;
    } else {
592
        out->type = QEMUD_SERVER_PKT_NETWORK_DEFINE;
593 594
        memcpy(out->qemud_packet_server_data_u.networkDefineReply.uuid, net->uuid, QEMUD_UUID_RAW_LEN);
        strncpy(out->qemud_packet_server_data_u.networkDefineReply.name, net->name, QEMUD_MAX_NAME_LEN-1);
595
        out->qemud_packet_server_data_u.networkDefineReply.name[QEMUD_MAX_NAME_LEN-1] = '\0';
596
        free(net);
597 598 599 600
    }
    return 0;
}

601
static int qemudDispatchNetworkUndefine(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
602 603 604 605 606 607 608 609 610
    virNetworkPtr net = qemudNetworkLookupByUUID(&conn, in->qemud_packet_client_data_u.networkUndefineRequest.uuid);
    int ret;
    if (!net) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
    }

    ret = qemudNetworkUndefine(net);
    free(net);
611
    if (ret < 0) {
612
        if (qemudDispatchFailure(out) < 0)
613 614
            return -1;
    } else {
615
        out->type = QEMUD_SERVER_PKT_NETWORK_UNDEFINE;
616 617 618 619
    }
    return 0;
}

620
static int qemudDispatchNetworkStart(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
621 622 623 624 625 626
    virNetworkPtr net = qemudNetworkLookupByUUID(&conn, in->qemud_packet_client_data_u.networkStartRequest.uuid);
    int ret;
    if (!net) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
    }
627

628 629 630
    ret = qemudNetworkStart(net);
    free(net);
    if (ret < 0) {
631
        if (qemudDispatchFailure(out) < 0)
632 633
            return -1;
    } else {
634
        out->type = QEMUD_SERVER_PKT_NETWORK_START;
635 636 637 638
    }
    return 0;
}

639
static int qemudDispatchNetworkDestroy(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
640 641 642 643 644 645 646 647 648 649
    virNetworkPtr net = qemudNetworkLookupByUUID(&conn, in->qemud_packet_client_data_u.networkDestroyRequest.uuid);
    int ret;
    if (!net) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
    }

    ret = qemudNetworkDestroy(net);
    free(net);
    if (ret < 0) {
650
        if (qemudDispatchFailure(out) < 0)
651 652
            return -1;
    } else {
653
        out->type = QEMUD_SERVER_PKT_NETWORK_DESTROY;
654 655 656 657
    }
    return 0;
}

658
static int qemudDispatchNetworkDumpXML(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
659 660 661 662 663 664 665 666 667 668
    virNetworkPtr net = qemudNetworkLookupByUUID(&conn, in->qemud_packet_client_data_u.networkDumpXMLRequest.uuid);
    char *ret;
    if (!net) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
    }

    ret = qemudNetworkDumpXML(net, 0);
    free(net);
    if (!ret) {
669
        if (qemudDispatchFailure(out) < 0)
670 671
            return -1;
    } else {
672
        out->type = QEMUD_SERVER_PKT_NETWORK_DUMP_XML;
673 674 675
        strncpy(out->qemud_packet_server_data_u.networkDumpXMLReply.xml, ret, QEMUD_MAX_XML_LEN-1);
        out->qemud_packet_server_data_u.networkDumpXMLReply.xml[QEMUD_MAX_XML_LEN-1] = '\0';
        free(ret);
676 677 678 679
    }
    return 0;
}

680
static int qemudDispatchNetworkGetBridgeName(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
681 682 683 684 685 686 687 688 689 690
    virNetworkPtr net = qemudNetworkLookupByUUID(&conn, in->qemud_packet_client_data_u.networkDumpXMLRequest.uuid);
    char *ret;
    if (!net) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
    }

    ret = qemudNetworkGetBridgeName(net);
    free(net);
    if (!ret) {
691
        if (qemudDispatchFailure(out) < 0)
692 693
            return -1;
    } else {
694
        out->type = QEMUD_SERVER_PKT_NETWORK_GET_BRIDGE_NAME;
695 696 697
        strncpy(out->qemud_packet_server_data_u.networkGetBridgeNameReply.ifname, ret, QEMUD_MAX_IFNAME_LEN-1);
        out->qemud_packet_server_data_u.networkGetBridgeNameReply.ifname[QEMUD_MAX_IFNAME_LEN-1] = '\0';
        free(ret);
698 699 700 701
    }
    return 0;
}

702 703
static int qemudDispatchDomainGetAutostart(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    virDomainPtr dom = qemudDomainLookupByUUID(&conn, in->qemud_packet_client_data_u.domainGetAutostartRequest.uuid);
704 705
    int ret;
    int autostart;
706 707 708 709 710
    if (!dom) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
        return 0;
    }
711 712 713

    autostart = 0;

714
    ret = qemudDomainGetAutostart(dom,
715
                                  &autostart);
716
    free(dom);
717
    if (ret < 0) {
718
        if (qemudDispatchFailure(out) < 0)
719 720
            return -1;
    } else {
721 722
        out->type = QEMUD_SERVER_PKT_DOMAIN_GET_AUTOSTART;
        out->qemud_packet_server_data_u.networkGetAutostartReply.autostart = (autostart != 0);
723 724 725 726
    }
    return 0;
}

727 728
static int qemudDispatchDomainSetAutostart(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    virDomainPtr dom = qemudDomainLookupByUUID(&conn, in->qemud_packet_client_data_u.domainSetAutostartRequest.uuid);
729
    int ret;
730 731 732 733 734
    if (!dom) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
        return 0;
    }
735

736
    ret = qemudDomainSetAutostart(dom,
737
                                  in->qemud_packet_client_data_u.domainSetAutostartRequest.autostart);
738
    free(dom);
739
    if (ret < 0) {
740
        if (qemudDispatchFailure(out) < 0)
741 742
            return -1;
    } else {
743
        out->type = QEMUD_SERVER_PKT_DOMAIN_SET_AUTOSTART;
744 745 746 747
    }
    return 0;
}

748 749
static int qemudDispatchNetworkGetAutostart(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    virNetworkPtr net = qemudNetworkLookupByUUID(&conn, in->qemud_packet_client_data_u.networkGetAutostartRequest.uuid);
750 751
    int ret;
    int autostart;
752 753 754 755
    if (!net) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
    }
756 757 758

    autostart = 0;

759
    ret = qemudNetworkGetAutostart(net,
760
                                   &autostart);
761
    free(net);
762
    if (ret < 0) {
763
        if (qemudDispatchFailure(out) < 0)
764 765
            return -1;
    } else {
766 767
        out->type = QEMUD_SERVER_PKT_NETWORK_GET_AUTOSTART;
        out->qemud_packet_server_data_u.networkGetAutostartReply.autostart = (autostart != 0);
768 769 770 771
    }
    return 0;
}

772 773
static int qemudDispatchNetworkSetAutostart(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out) {
    virNetworkPtr net = qemudNetworkLookupByUUID(&conn, in->qemud_packet_client_data_u.networkGetAutostartRequest.uuid);
774
    int ret;
775 776 777 778
    if (!net) {
        if (qemudDispatchFailure(out) < 0)
            return -1;
    }
779

780
    ret = qemudNetworkSetAutostart(net,
781
                                   in->qemud_packet_client_data_u.networkSetAutostartRequest.autostart);
782
    free(net);
783
    if (ret < 0) {
784
        if (qemudDispatchFailure(out) < 0)
785 786
            return -1;
    } else {
787
        out->type = QEMUD_SERVER_PKT_NETWORK_SET_AUTOSTART;
788 789 790
    }
    return 0;
}
D
Daniel P. Berrange 已提交
791

792
typedef int (*clientFunc)(struct qemud_packet_client_data *in, struct qemud_packet_server_data *out);
D
Daniel P. Berrange 已提交
793 794 795 796


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

797
clientFunc funcsTransmitRW[QEMUD_CLIENT_PKT_MAX] = {
D
Daniel P. Berrange 已提交
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
    qemudDispatchGetVersion,
    qemudDispatchGetNodeInfo,
    qemudDispatchListDomains,
    qemudDispatchNumDomains,
    qemudDispatchDomainCreate,
    qemudDispatchDomainLookupByID,
    qemudDispatchDomainLookupByUUID,
    qemudDispatchDomainLookupByName,
    qemudDispatchDomainSuspend,
    qemudDispatchDomainResume,
    qemudDispatchDomainDestroy,
    qemudDispatchDomainGetInfo,
    qemudDispatchDomainSave,
    qemudDispatchDomainRestore,
    qemudDispatchDumpXML,
    qemudDispatchListDefinedDomains,
    qemudDispatchNumDefinedDomains,
    qemudDispatchDomainStart,
    qemudDispatchDomainDefine,
817 818 819 820 821 822 823 824 825 826 827 828 829
    qemudDispatchDomainUndefine,
    qemudDispatchNumNetworks,
    qemudDispatchListNetworks,
    qemudDispatchNumDefinedNetworks,
    qemudDispatchListDefinedNetworks,
    qemudDispatchNetworkLookupByUUID,
    qemudDispatchNetworkLookupByName,
    qemudDispatchNetworkCreate,
    qemudDispatchNetworkDefine,
    qemudDispatchNetworkUndefine,
    qemudDispatchNetworkStart,
    qemudDispatchNetworkDestroy,
    qemudDispatchNetworkDumpXML,
830
    qemudDispatchNetworkGetBridgeName,
831 832 833 834
    qemudDispatchDomainGetAutostart,
    qemudDispatchDomainSetAutostart,
    qemudDispatchNetworkGetAutostart,
    qemudDispatchNetworkSetAutostart,
835
    qemudDispatchGetCapabilities,
D
Daniel P. Berrange 已提交
836 837
};

838
clientFunc funcsTransmitRO[QEMUD_CLIENT_PKT_MAX] = {
D
Daniel P. Berrange 已提交
839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
    qemudDispatchGetVersion,
    qemudDispatchGetNodeInfo,
    qemudDispatchListDomains,
    qemudDispatchNumDomains,
    NULL,
    qemudDispatchDomainLookupByID,
    qemudDispatchDomainLookupByUUID,
    qemudDispatchDomainLookupByName,
    NULL,
    NULL,
    NULL,
    qemudDispatchDomainGetInfo,
    NULL,
    NULL,
    qemudDispatchDumpXML,
    qemudDispatchListDefinedDomains,
    qemudDispatchNumDefinedDomains,
    NULL,
    NULL,
    NULL,
859 860 861 862 863 864 865 866 867 868 869 870
    qemudDispatchNumNetworks,
    qemudDispatchListNetworks,
    qemudDispatchNumDefinedNetworks,
    qemudDispatchListDefinedNetworks,
    qemudDispatchNetworkLookupByUUID,
    qemudDispatchNetworkLookupByName,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    qemudDispatchNetworkDumpXML,
871
    qemudDispatchNetworkGetBridgeName,
872 873 874 875
    qemudDispatchDomainGetAutostart,
    NULL,
    qemudDispatchNetworkGetAutostart,
    NULL,
D
Daniel P. Berrange 已提交
876 877 878 879 880 881 882 883 884 885 886 887
};

/*
 * 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
 */
888 889 890

int qemudDispatch(struct qemud_server *server ATTRIBUTE_UNUSED,
                  struct qemud_client *client,
891
                  qemud_packet_client_data *in, qemud_packet_server_data *out) {
D
Daniel P. Berrange 已提交
892
    clientFunc *funcs;
893 894 895
    unsigned int type = in->type;
    qemudDebug("> Dispatching request type %d, readonly ? %d",
               in->type, client->readonly);
D
Daniel P. Berrange 已提交
896

897 898 899 900
    if (!conn.magic) {
        qemudOpen(&conn, "qemu:///session", 0);
        conn.magic = 1;
    }
901
    virResetLastError();
902
    virConnResetLastError(&conn);
D
Daniel P. Berrange 已提交
903

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

906
    if (type >= QEMUD_CLIENT_PKT_MAX) {
907
        qemudDebug("Illegal request type");
D
Daniel P. Berrange 已提交
908 909 910 911 912 913 914 915 916
        return -1;
    }

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

    if (!funcs[type]) {
917
        qemudDebug("Illegal operation requested");
918
        qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_DENIED, NULL);
919
        qemudDispatchFailure(out);
D
Daniel P. Berrange 已提交
920
    } else {
921
        if ((funcs[type])(in, out) < 0) {
922
            qemudDebug("Dispatch failed");
D
Daniel P. Berrange 已提交
923 924 925 926
            return -1;
        }
    }

927
    qemudDebug("< Returning reply %d", out->type);
D
Daniel P. Berrange 已提交
928 929 930 931 932 933 934 935 936 937 938 939

    return 0;
}

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