qemu-sockets.c 26.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 *  inet and unix socket functions for qemu
 *
 *  (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; under version 2 of the License.
 *
 *  This program 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 General Public License for more details.
14 15 16
 *
 * Contributions after 2012-01-13 are licensed under the terms of the
 * GNU GPL, version 2 or (at your option) any later version.
17
 */
18 19 20 21 22 23 24
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>

25
#include "monitor/monitor.h"
26
#include "qemu/sockets.h"
27
#include "qemu-common.h" /* for qemu_isdigit */
28
#include "qemu/main-loop.h"
29 30 31 32 33 34 35

#ifndef AI_ADDRCONFIG
# define AI_ADDRCONFIG 0
#endif

static const int on=1, off=0;

36
/* used temporarely until all users are converted to QemuOpts */
Blue Swirl's avatar
Blue Swirl committed
37
static QemuOptsList dummy_opts = {
38
    .name = "dummy",
39
    .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
40 41 42 43
    .desc = {
        {
            .name = "path",
            .type = QEMU_OPT_STRING,
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
        },{
            .name = "host",
            .type = QEMU_OPT_STRING,
        },{
            .name = "port",
            .type = QEMU_OPT_STRING,
        },{
            .name = "to",
            .type = QEMU_OPT_NUMBER,
        },{
            .name = "ipv4",
            .type = QEMU_OPT_BOOL,
        },{
            .name = "ipv6",
            .type = QEMU_OPT_BOOL,
59 60 61 62 63
        },
        { /* end if list */ }
    },
};

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
static int inet_getport(struct addrinfo *e)
{
    struct sockaddr_in *i4;
    struct sockaddr_in6 *i6;

    switch (e->ai_family) {
    case PF_INET6:
        i6 = (void*)e->ai_addr;
        return ntohs(i6->sin6_port);
    case PF_INET:
        i4 = (void*)e->ai_addr;
        return ntohs(i4->sin_port);
    default:
        return 0;
    }
}

static void inet_setport(struct addrinfo *e, int port)
{
    struct sockaddr_in *i4;
    struct sockaddr_in6 *i6;

    switch (e->ai_family) {
    case PF_INET6:
        i6 = (void*)e->ai_addr;
        i6->sin6_port = htons(port);
        break;
    case PF_INET:
        i4 = (void*)e->ai_addr;
        i4->sin_port = htons(port);
        break;
    }
}

98
const char *inet_strfamily(int family)
99 100 101 102 103 104
{
    switch (family) {
    case PF_INET6: return "ipv6";
    case PF_INET:  return "ipv4";
    case PF_UNIX:  return "unix";
    }
105
    return "unknown";
106 107
}

108
int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
109 110
{
    struct addrinfo ai,*res,*e;
111
    const char *addr;
112 113 114
    char port[33];
    char uaddr[INET6_ADDRSTRLEN+1];
    char uport[33];
115
    int slisten, rc, to, port_min, port_max, p;
116 117 118 119

    memset(&ai,0, sizeof(ai));
    ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
    ai.ai_family = PF_UNSPEC;
120
    ai.ai_socktype = SOCK_STREAM;
121

122 123
    if ((qemu_opt_get(opts, "host") == NULL) ||
        (qemu_opt_get(opts, "port") == NULL)) {
124
        error_setg(errp, "host and/or port not specified");
125
        return -1;
126
    }
127 128
    pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
    addr = qemu_opt_get(opts, "host");
129

130 131
    to = qemu_opt_get_number(opts, "to", 0);
    if (qemu_opt_get_bool(opts, "ipv4", 0))
132
        ai.ai_family = PF_INET;
133
    if (qemu_opt_get_bool(opts, "ipv6", 0))
134 135 136 137 138 139 140
        ai.ai_family = PF_INET6;

    /* lookup */
    if (port_offset)
        snprintf(port, sizeof(port), "%d", atoi(port) + port_offset);
    rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res);
    if (rc != 0) {
141 142
        error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
                   gai_strerror(rc));
143 144 145 146 147
        return -1;
    }

    /* create socket + bind */
    for (e = res; e != NULL; e = e->ai_next) {
vibi's avatar
vibi committed
148 149 150
        getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
		        uaddr,INET6_ADDRSTRLEN,uport,32,
		        NI_NUMERICHOST | NI_NUMERICSERV);
Kevin Wolf's avatar
Kevin Wolf committed
151
        slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
vibi's avatar
vibi committed
152
        if (slisten < 0) {
153
            if (!e->ai_next) {
154
                error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
155
            }
vibi's avatar
vibi committed
156 157
            continue;
        }
158 159 160 161 162

        setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
#ifdef IPV6_V6ONLY
        if (e->ai_family == PF_INET6) {
            /* listen on both ipv4 and ipv6 */
vibi's avatar
vibi committed
163 164
            setsockopt(slisten,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&off,
                sizeof(off));
165 166 167
        }
#endif

168 169 170 171
        port_min = inet_getport(e);
        port_max = to ? to + port_offset : port_min;
        for (p = port_min; p <= port_max; p++) {
            inet_setport(e, p);
172 173 174
            if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
                goto listen;
            }
175
            if (p == port_max) {
176
                if (!e->ai_next) {
177
                    error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED);
178
                }
179 180 181 182 183 184 185 186 187
            }
        }
        closesocket(slisten);
    }
    freeaddrinfo(res);
    return -1;

listen:
    if (listen(slisten,1) != 0) {
188
        error_set_errno(errp, errno, QERR_SOCKET_LISTEN_FAILED);
189
        closesocket(slisten);
vibi's avatar
vibi committed
190
        freeaddrinfo(res);
191 192
        return -1;
    }
193 194 195 196 197
    snprintf(uport, sizeof(uport), "%d", inet_getport(e) - port_offset);
    qemu_opt_set(opts, "host", uaddr);
    qemu_opt_set(opts, "port", uport);
    qemu_opt_set(opts, "ipv6", (e->ai_family == PF_INET6) ? "on" : "off");
    qemu_opt_set(opts, "ipv4", (e->ai_family != PF_INET6) ? "on" : "off");
198 199 200 201
    freeaddrinfo(res);
    return slisten;
}

202 203 204 205 206 207 208 209
#ifdef _WIN32
#define QEMU_SOCKET_RC_INPROGRESS(rc) \
    ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY)
#else
#define QEMU_SOCKET_RC_INPROGRESS(rc) \
    ((rc) == -EINPROGRESS)
#endif

210 211 212 213 214 215 216 217 218 219
/* Struct to store connect state for non blocking connect */
typedef struct ConnectState {
    int fd;
    struct addrinfo *addr_list;
    struct addrinfo *current_addr;
    NonBlockingConnectHandler *callback;
    void *opaque;
} ConnectState;

static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
220
                             ConnectState *connect_state, Error **errp);
221 222

static void wait_for_connect(void *opaque)
223
{
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
    ConnectState *s = opaque;
    int val = 0, rc = 0;
    socklen_t valsize = sizeof(val);
    bool in_progress;

    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);

    do {
        rc = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize);
    } while (rc == -1 && socket_error() == EINTR);

    /* update rc to contain error */
    if (!rc && val) {
        rc = -1;
    }

    /* connect error */
    if (rc < 0) {
        closesocket(s->fd);
        s->fd = rc;
    }

    /* try to connect to the next address on the list */
247 248 249
    if (s->current_addr) {
        while (s->current_addr->ai_next != NULL && s->fd < 0) {
            s->current_addr = s->current_addr->ai_next;
250
            s->fd = inet_connect_addr(s->current_addr, &in_progress, s, NULL);
251 252 253 254
            /* connect in progress */
            if (in_progress) {
                return;
            }
255
        }
256 257

        freeaddrinfo(s->addr_list);
258
    }
259

260 261
    if (s->callback) {
        s->callback(s->fd, s->opaque);
262
    }
263 264 265 266
    g_free(s);
}

static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
267
                             ConnectState *connect_state, Error **errp)
268 269 270 271
{
    int sock, rc;

    *in_progress = false;
272 273 274

    sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
    if (sock < 0) {
275
        error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
276 277
        return -1;
    }
278
    qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
279
    if (connect_state != NULL) {
280 281 282 283 284 285 286 287 288 289
        socket_set_nonblock(sock);
    }
    /* connect to peer */
    do {
        rc = 0;
        if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) {
            rc = -socket_error();
        }
    } while (rc == -EINTR);

290 291 292 293 294
    if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
        connect_state->fd = sock;
        qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect,
                             connect_state);
        *in_progress = true;
295
    } else if (rc < 0) {
296
        error_set_errno(errp, errno, QERR_SOCKET_CONNECT_FAILED);
297 298 299 300 301 302 303 304 305 306
        closesocket(sock);
        return -1;
    }
    return sock;
}

static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp)
{
    struct addrinfo ai, *res;
    int rc;
307 308
    const char *addr;
    const char *port;
309

310
    memset(&ai, 0, sizeof(ai));
311

312 313
    ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
    ai.ai_family = PF_UNSPEC;
314
    ai.ai_socktype = SOCK_STREAM;
315

316 317 318
    addr = qemu_opt_get(opts, "host");
    port = qemu_opt_get(opts, "port");
    if (addr == NULL || port == NULL) {
319
        error_setg(errp, "host and/or port not specified");
320
        return NULL;
321 322
    }

323
    if (qemu_opt_get_bool(opts, "ipv4", 0)) {
324
        ai.ai_family = PF_INET;
325 326
    }
    if (qemu_opt_get_bool(opts, "ipv6", 0)) {
327
        ai.ai_family = PF_INET6;
328
    }
329 330

    /* lookup */
331 332
    rc = getaddrinfo(addr, port, &ai, &res);
    if (rc != 0) {
333 334
        error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
                   gai_strerror(rc));
335 336 337 338 339
        return NULL;
    }
    return res;
}

340 341 342 343 344 345
/**
 * Create a socket and connect it to an address.
 *
 * @opts: QEMU options, recognized parameters strings "host" and "port",
 *        bools "ipv4" and "ipv6".
 * @errp: set on error
346 347
 * @callback: callback function for non-blocking connect
 * @opaque: opaque for callback function
348 349
 *
 * Returns: -1 on error, file descriptor on success.
350 351 352 353
 *
 * If @callback is non-null, the connect is non-blocking.  If this
 * function succeeds, callback will be called when the connection
 * completes, with the file descriptor on success, or -1 on error.
354
 */
355 356
int inet_connect_opts(QemuOpts *opts, Error **errp,
                      NonBlockingConnectHandler *callback, void *opaque)
357 358 359
{
    struct addrinfo *res, *e;
    int sock = -1;
360 361
    bool in_progress;
    ConnectState *connect_state = NULL;
362 363 364 365 366 367

    res = inet_parse_connect_opts(opts, errp);
    if (!res) {
        return -1;
    }

368 369 370 371 372
    if (callback != NULL) {
        connect_state = g_malloc0(sizeof(*connect_state));
        connect_state->addr_list = res;
        connect_state->callback = callback;
        connect_state->opaque = opaque;
373 374 375
    }

    for (e = res; e != NULL; e = e->ai_next) {
376 377 378 379
        if (error_is_set(errp)) {
            error_free(*errp);
            *errp = NULL;
        }
380 381 382
        if (connect_state != NULL) {
            connect_state->current_addr = e;
        }
383
        sock = inet_connect_addr(e, &in_progress, connect_state, errp);
384 385 386 387 388 389 390
        if (in_progress) {
            return sock;
        } else if (sock >= 0) {
            /* non blocking socket immediate success, call callback */
            if (callback != NULL) {
                callback(sock, opaque);
            }
391
            break;
392
        }
393
    }
394
    g_free(connect_state);
395
    freeaddrinfo(res);
396
    return sock;
397 398
}

399
int inet_dgram_opts(QemuOpts *opts, Error **errp)
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
{
    struct addrinfo ai, *peer = NULL, *local = NULL;
    const char *addr;
    const char *port;
    int sock = -1, rc;

    /* lookup peer addr */
    memset(&ai,0, sizeof(ai));
    ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
    ai.ai_family = PF_UNSPEC;
    ai.ai_socktype = SOCK_DGRAM;

    addr = qemu_opt_get(opts, "host");
    port = qemu_opt_get(opts, "port");
    if (addr == NULL || strlen(addr) == 0) {
        addr = "localhost";
    }
    if (port == NULL || strlen(port) == 0) {
418
        error_setg(errp, "remote port not specified");
419 420 421 422 423 424 425 426 427
        return -1;
    }

    if (qemu_opt_get_bool(opts, "ipv4", 0))
        ai.ai_family = PF_INET;
    if (qemu_opt_get_bool(opts, "ipv6", 0))
        ai.ai_family = PF_INET6;

    if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) {
428 429
        error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
                   gai_strerror(rc));
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
	return -1;
    }

    /* lookup local addr */
    memset(&ai,0, sizeof(ai));
    ai.ai_flags = AI_PASSIVE;
    ai.ai_family = peer->ai_family;
    ai.ai_socktype = SOCK_DGRAM;

    addr = qemu_opt_get(opts, "localaddr");
    port = qemu_opt_get(opts, "localport");
    if (addr == NULL || strlen(addr) == 0) {
        addr = NULL;
    }
    if (!port || strlen(port) == 0)
        port = "0";

    if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) {
448 449
        error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,
                   gai_strerror(rc));
450
        goto err;
451 452 453
    }

    /* create socket */
Kevin Wolf's avatar
Kevin Wolf committed
454
    sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol);
455
    if (sock < 0) {
456
        error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
457 458 459 460 461 462
        goto err;
    }
    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));

    /* bind socket */
    if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) {
463
        error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED);
464 465 466 467 468
        goto err;
    }

    /* connect to peer */
    if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) {
469
        error_set_errno(errp, errno, QERR_SOCKET_CONNECT_FAILED);
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
        goto err;
    }

    freeaddrinfo(local);
    freeaddrinfo(peer);
    return sock;

err:
    if (-1 != sock)
        closesocket(sock);
    if (local)
        freeaddrinfo(local);
    if (peer)
        freeaddrinfo(peer);
    return -1;
}

487
/* compatibility wrapper */
488
static InetSocketAddress *inet_parse(const char *str, Error **errp)
489
{
490
    InetSocketAddress *addr;
491
    const char *optstr, *h;
492
    char host[64];
493
    char port[33];
494
    int to;
495 496
    int pos;

497 498
    addr = g_new0(InetSocketAddress, 1);

499 500 501
    /* parse address */
    if (str[0] == ':') {
        /* no host given */
502 503
        host[0] = '\0';
        if (1 != sscanf(str, ":%32[^,]%n", port, &pos)) {
504
            error_setg(errp, "error parsing port in address '%s'", str);
505
            goto fail;
506 507 508
        }
    } else if (str[0] == '[') {
        /* IPv6 addr */
509
        if (2 != sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos)) {
510
            error_setg(errp, "error parsing IPv6 address '%s'", str);
511
            goto fail;
512
        }
513
        addr->ipv6 = addr->has_ipv6 = true;
514 515
    } else if (qemu_isdigit(str[0])) {
        /* IPv4 addr */
516
        if (2 != sscanf(str, "%64[0-9.]:%32[^,]%n", host, port, &pos)) {
517
            error_setg(errp, "error parsing IPv4 address '%s'", str);
518
            goto fail;
519
        }
520
        addr->ipv4 = addr->has_ipv4 = true;
521 522
    } else {
        /* hostname */
523
        if (2 != sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos)) {
524
            error_setg(errp, "error parsing address '%s'", str);
525
            goto fail;
526 527
        }
    }
528 529 530

    addr->host = g_strdup(host);
    addr->port = g_strdup(port);
531 532 533 534

    /* parse options */
    optstr = str + pos;
    h = strstr(optstr, ",to=");
535
    if (h) {
536 537 538
        h += 4;
        if (sscanf(h, "%d%n", &to, &pos) != 1 ||
            (h[pos] != '\0' && h[pos] != ',')) {
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
            error_setg(errp, "error parsing to= argument");
            goto fail;
        }
        addr->has_to = true;
        addr->to = to;
    }
    if (strstr(optstr, ",ipv4")) {
        addr->ipv4 = addr->has_ipv4 = true;
    }
    if (strstr(optstr, ",ipv6")) {
        addr->ipv6 = addr->has_ipv6 = true;
    }
    return addr;

fail:
    qapi_free_InetSocketAddress(addr);
    return NULL;
}

static void inet_addr_to_opts(QemuOpts *opts, InetSocketAddress *addr)
{
    bool ipv4 = addr->ipv4 || !addr->has_ipv4;
    bool ipv6 = addr->ipv6 || !addr->has_ipv6;

    if (!ipv4 || !ipv6) {
        qemu_opt_set_bool(opts, "ipv4", ipv4);
        qemu_opt_set_bool(opts, "ipv6", ipv6);
    }
    if (addr->has_to) {
        char to[20];
        snprintf(to, sizeof(to), "%d", addr->to);
        qemu_opt_set(opts, "to", to);
    }
    qemu_opt_set(opts, "host", addr->host);
    qemu_opt_set(opts, "port", addr->port);
574 575
}

576
int inet_listen(const char *str, char *ostr, int olen,
577
                int socktype, int port_offset, Error **errp)
578 579 580 581
{
    QemuOpts *opts;
    char *optstr;
    int sock = -1;
582
    InetSocketAddress *addr;
583

584 585
    addr = inet_parse(str, errp);
    if (addr != NULL) {
586
        opts = qemu_opts_create_nofail(&dummy_opts);
587 588
        inet_addr_to_opts(opts, addr);
        qapi_free_InetSocketAddress(addr);
589
        sock = inet_listen_opts(opts, port_offset, errp);
590 591 592 593 594 595 596 597 598 599 600 601 602 603
        if (sock != -1 && ostr) {
            optstr = strchr(str, ',');
            if (qemu_opt_get_bool(opts, "ipv6", 0)) {
                snprintf(ostr, olen, "[%s]:%s%s",
                         qemu_opt_get(opts, "host"),
                         qemu_opt_get(opts, "port"),
                         optstr ? optstr : "");
            } else {
                snprintf(ostr, olen, "%s:%s%s",
                         qemu_opt_get(opts, "host"),
                         qemu_opt_get(opts, "port"),
                         optstr ? optstr : "");
            }
        }
604
        qemu_opts_del(opts);
605 606 607 608
    }
    return sock;
}

609 610 611 612 613 614 615 616 617
/**
 * Create a blocking socket and connect it to an address.
 *
 * @str: address string
 * @errp: set in case of an error
 *
 * Returns -1 in case of error, file descriptor on success
 **/
int inet_connect(const char *str, Error **errp)
618 619 620
{
    QemuOpts *opts;
    int sock = -1;
621
    InetSocketAddress *addr;
622

623 624
    addr = inet_parse(str, errp);
    if (addr != NULL) {
625
        opts = qemu_opts_create_nofail(&dummy_opts);
626 627
        inet_addr_to_opts(opts, addr);
        qapi_free_InetSocketAddress(addr);
628
        sock = inet_connect_opts(opts, errp, NULL, NULL);
629
        qemu_opts_del(opts);
630 631 632 633 634 635
    }
    return sock;
}

/**
 * Create a non-blocking socket and connect it to an address.
636 637
 * Calls the callback function with fd in case of success or -1 in case of
 * error.
638 639
 *
 * @str: address string
640 641 642
 * @callback: callback function that is called when connect completes,
 *            cannot be NULL.
 * @opaque: opaque for callback function
643 644
 * @errp: set in case of an error
 *
645
 * Returns: -1 on immediate error, file descriptor on success.
646
 **/
647 648 649
int inet_nonblocking_connect(const char *str,
                             NonBlockingConnectHandler *callback,
                             void *opaque, Error **errp)
650 651 652
{
    QemuOpts *opts;
    int sock = -1;
653
    InetSocketAddress *addr;
654

655 656
    g_assert(callback != NULL);

657 658
    addr = inet_parse(str, errp);
    if (addr != NULL) {
659
        opts = qemu_opts_create_nofail(&dummy_opts);
660 661
        inet_addr_to_opts(opts, addr);
        qapi_free_InetSocketAddress(addr);
662
        sock = inet_connect_opts(opts, errp, callback, opaque);
663
        qemu_opts_del(opts);
664
    }
665 666 667
    return sock;
}

668 669
#ifndef _WIN32

670
int unix_listen_opts(QemuOpts *opts, Error **errp)
671 672
{
    struct sockaddr_un un;
673 674
    const char *path = qemu_opt_get(opts, "path");
    int sock, fd;
675

Kevin Wolf's avatar
Kevin Wolf committed
676
    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
677
    if (sock < 0) {
678
        error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
vibi's avatar
vibi committed
679
        return -1;
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697
    }

    memset(&un, 0, sizeof(un));
    un.sun_family = AF_UNIX;
    if (path && strlen(path)) {
        snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
    } else {
        char *tmpdir = getenv("TMPDIR");
        snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX",
                 tmpdir ? tmpdir : "/tmp");
        /*
         * This dummy fd usage silences the mktemp() unsecure warning.
         * Using mkstemp() doesn't make things more secure here
         * though.  bind() complains about existing files, so we have
         * to unlink first and thus re-open the race window.  The
         * worst case possible is bind() failing, i.e. a DoS attack.
         */
        fd = mkstemp(un.sun_path); close(fd);
698
        qemu_opt_set(opts, "path", un.sun_path);
699 700 701 702
    }

    unlink(un.sun_path);
    if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
703
        error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED);
704 705 706
        goto err;
    }
    if (listen(sock, 1) < 0) {
707
        error_set_errno(errp, errno, QERR_SOCKET_LISTEN_FAILED);
708 709 710 711 712 713 714 715 716 717
        goto err;
    }

    return sock;

err:
    closesocket(sock);
    return -1;
}

718 719
int unix_connect_opts(QemuOpts *opts, Error **errp,
                      NonBlockingConnectHandler *callback, void *opaque)
720 721
{
    struct sockaddr_un un;
722
    const char *path = qemu_opt_get(opts, "path");
723 724
    ConnectState *connect_state = NULL;
    int sock, rc;
725

726
    if (NULL == path) {
727
        error_setg(errp, "unix connect: no path specified");
728 729 730
        return -1;
    }

Kevin Wolf's avatar
Kevin Wolf committed
731
    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
732
    if (sock < 0) {
733
        error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED);
vibi's avatar
vibi committed
734
        return -1;
735
    }
736 737 738 739 740 741
    if (callback != NULL) {
        connect_state = g_malloc0(sizeof(*connect_state));
        connect_state->callback = callback;
        connect_state->opaque = opaque;
        socket_set_nonblock(sock);
    }
742 743 744 745

    memset(&un, 0, sizeof(un));
    un.sun_family = AF_UNIX;
    snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767

    /* connect to peer */
    do {
        rc = 0;
        if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) {
            rc = -socket_error();
        }
    } while (rc == -EINTR);

    if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) {
        connect_state->fd = sock;
        qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect,
                             connect_state);
        return sock;
    } else if (rc >= 0) {
        /* non blocking socket immediate success, call callback */
        if (callback != NULL) {
            callback(sock, opaque);
        }
    }

    if (rc < 0) {
768
        error_set_errno(errp, -rc, QERR_SOCKET_CONNECT_FAILED);
769
        close(sock);
770
        sock = -1;
771 772
    }

773
    g_free(connect_state);
774 775 776
    return sock;
}

777 778 779 780
#else

int unix_listen_opts(QemuOpts *opts, Error **errp)
{
781
    error_setg(errp, "unix sockets are not available on windows");
782 783 784 785
    errno = ENOTSUP;
    return -1;
}

786 787
int unix_connect_opts(QemuOpts *opts, Error **errp,
                      NonBlockingConnectHandler *callback, void *opaque)
788
{
789
    error_setg(errp, "unix sockets are not available on windows");
790 791 792 793 794
    errno = ENOTSUP;
    return -1;
}
#endif

795
/* compatibility wrapper */
796
int unix_listen(const char *str, char *ostr, int olen, Error **errp)
797 798 799 800 801
{
    QemuOpts *opts;
    char *path, *optstr;
    int sock, len;

802
    opts = qemu_opts_create_nofail(&dummy_opts);
803 804 805 806 807

    optstr = strchr(str, ',');
    if (optstr) {
        len = optstr - str;
        if (len) {
808
            path = g_malloc(len+1);
809 810
            snprintf(path, len+1, "%.*s", len, str);
            qemu_opt_set(opts, "path", path);
811
            g_free(path);
812 813 814 815 816
        }
    } else {
        qemu_opt_set(opts, "path", str);
    }

817
    sock = unix_listen_opts(opts, errp);
818 819 820 821 822 823 824

    if (sock != -1 && ostr)
        snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : "");
    qemu_opts_del(opts);
    return sock;
}

825
int unix_connect(const char *path, Error **errp)
826 827 828 829
{
    QemuOpts *opts;
    int sock;

830
    opts = qemu_opts_create_nofail(&dummy_opts);
831
    qemu_opt_set(opts, "path", path);
832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
    sock = unix_connect_opts(opts, errp, NULL, NULL);
    qemu_opts_del(opts);
    return sock;
}


int unix_nonblocking_connect(const char *path,
                             NonBlockingConnectHandler *callback,
                             void *opaque, Error **errp)
{
    QemuOpts *opts;
    int sock = -1;

    g_assert(callback != NULL);

847
    opts = qemu_opts_create_nofail(&dummy_opts);
848 849
    qemu_opt_set(opts, "path", path);
    sock = unix_connect_opts(opts, errp, callback, opaque);
850 851 852 853
    qemu_opts_del(opts);
    return sock;
}

854 855 856 857 858 859 860
SocketAddress *socket_parse(const char *str, Error **errp)
{
    SocketAddress *addr = NULL;

    addr = g_new(SocketAddress, 1);
    if (strstart(str, "unix:", NULL)) {
        if (str[5] == '\0') {
861
            error_setg(errp, "invalid Unix socket address");
862 863 864 865 866 867 868 869
            goto fail;
        } else {
            addr->kind = SOCKET_ADDRESS_KIND_UNIX;
            addr->q_unix = g_new(UnixSocketAddress, 1);
            addr->q_unix->path = g_strdup(str + 5);
        }
    } else if (strstart(str, "fd:", NULL)) {
        if (str[3] == '\0') {
870
            error_setg(errp, "invalid file descriptor address");
871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897
            goto fail;
        } else {
            addr->kind = SOCKET_ADDRESS_KIND_FD;
            addr->fd = g_new(String, 1);
            addr->fd->str = g_strdup(str + 3);
        }
    } else {
        addr->kind = SOCKET_ADDRESS_KIND_INET;
        addr->inet = g_new(InetSocketAddress, 1);
        addr->inet = inet_parse(str, errp);
        if (addr->inet == NULL) {
            goto fail;
        }
    }
    return addr;

fail:
    qapi_free_SocketAddress(addr);
    return NULL;
}

int socket_connect(SocketAddress *addr, Error **errp,
                   NonBlockingConnectHandler *callback, void *opaque)
{
    QemuOpts *opts;
    int fd;

898
    opts = qemu_opts_create_nofail(&dummy_opts);
899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928
    switch (addr->kind) {
    case SOCKET_ADDRESS_KIND_INET:
        inet_addr_to_opts(opts, addr->inet);
        fd = inet_connect_opts(opts, errp, callback, opaque);
        break;

    case SOCKET_ADDRESS_KIND_UNIX:
        qemu_opt_set(opts, "path", addr->q_unix->path);
        fd = unix_connect_opts(opts, errp, callback, opaque);
        break;

    case SOCKET_ADDRESS_KIND_FD:
        fd = monitor_get_fd(cur_mon, addr->fd->str, errp);
        if (callback) {
            callback(fd, opaque);
        }
        break;

    default:
        abort();
    }
    qemu_opts_del(opts);
    return fd;
}

int socket_listen(SocketAddress *addr, Error **errp)
{
    QemuOpts *opts;
    int fd;

929
    opts = qemu_opts_create_nofail(&dummy_opts);
930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951
    switch (addr->kind) {
    case SOCKET_ADDRESS_KIND_INET:
        inet_addr_to_opts(opts, addr->inet);
        fd = inet_listen_opts(opts, 0, errp);
        break;

    case SOCKET_ADDRESS_KIND_UNIX:
        qemu_opt_set(opts, "path", addr->q_unix->path);
        fd = unix_listen_opts(opts, errp);
        break;

    case SOCKET_ADDRESS_KIND_FD:
        fd = monitor_get_fd(cur_mon, addr->fd->str, errp);
        break;

    default:
        abort();
    }
    qemu_opts_del(opts);
    return fd;
}

952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
{
    QemuOpts *opts;
    int fd;

    opts = qemu_opts_create_nofail(&dummy_opts);
    switch (remote->kind) {
    case SOCKET_ADDRESS_KIND_INET:
        qemu_opt_set(opts, "host", remote->inet->host);
        qemu_opt_set(opts, "port", remote->inet->port);
        if (local) {
            qemu_opt_set(opts, "localaddr", local->inet->host);
            qemu_opt_set(opts, "localport", local->inet->port);
        }
        fd = inet_dgram_opts(opts, errp);
        break;

    default:
        error_setg(errp, "socket type unsupported for datagram");
        return -1;
    }
    qemu_opts_del(opts);
    return fd;
}

977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999
#ifdef _WIN32
static void socket_cleanup(void)
{
    WSACleanup();
}
#endif

int socket_init(void)
{
#ifdef _WIN32
    WSADATA Data;
    int ret, err;

    ret = WSAStartup(MAKEWORD(2,2), &Data);
    if (ret != 0) {
        err = WSAGetLastError();
        fprintf(stderr, "WSAStartup: %d\n", err);
        return -1;
    }
    atexit(socket_cleanup);
#endif
    return 0;
}