qemu/qemu-sockets.c
<<
>>
Prefs
   1/*
   2 *  inet and unix socket functions for qemu
   3 *
   4 *  (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License as published by
   8 *  the Free Software Foundation; under version 2 of the License.
   9 *
  10 *  This program is distributed in the hope that it will be useful,
  11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 *  GNU General Public License for more details.
  14 */
  15#include <stdio.h>
  16#include <stdlib.h>
  17#include <string.h>
  18#include <ctype.h>
  19#include <errno.h>
  20#include <unistd.h>
  21
  22#include "qemu_socket.h"
  23#include "qemu-common.h" /* for qemu_isdigit */
  24
  25#ifndef AI_ADDRCONFIG
  26# define AI_ADDRCONFIG 0
  27#endif
  28
  29static int sockets_debug = 0;
  30static const int on=1, off=0;
  31
  32/* used temporarely until all users are converted to QemuOpts */
  33static QemuOptsList dummy_opts = {
  34    .name = "dummy",
  35    .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
  36    .desc = {
  37        {
  38            .name = "path",
  39            .type = QEMU_OPT_STRING,
  40        },{
  41            .name = "host",
  42            .type = QEMU_OPT_STRING,
  43        },{
  44            .name = "port",
  45            .type = QEMU_OPT_STRING,
  46        },{
  47            .name = "to",
  48            .type = QEMU_OPT_NUMBER,
  49        },{
  50            .name = "ipv4",
  51            .type = QEMU_OPT_BOOL,
  52        },{
  53            .name = "ipv6",
  54            .type = QEMU_OPT_BOOL,
  55        },
  56        { /* end if list */ }
  57    },
  58};
  59
  60static int inet_getport(struct addrinfo *e)
  61{
  62    struct sockaddr_in *i4;
  63    struct sockaddr_in6 *i6;
  64
  65    switch (e->ai_family) {
  66    case PF_INET6:
  67        i6 = (void*)e->ai_addr;
  68        return ntohs(i6->sin6_port);
  69    case PF_INET:
  70        i4 = (void*)e->ai_addr;
  71        return ntohs(i4->sin_port);
  72    default:
  73        return 0;
  74    }
  75}
  76
  77static void inet_setport(struct addrinfo *e, int port)
  78{
  79    struct sockaddr_in *i4;
  80    struct sockaddr_in6 *i6;
  81
  82    switch (e->ai_family) {
  83    case PF_INET6:
  84        i6 = (void*)e->ai_addr;
  85        i6->sin6_port = htons(port);
  86        break;
  87    case PF_INET:
  88        i4 = (void*)e->ai_addr;
  89        i4->sin_port = htons(port);
  90        break;
  91    }
  92}
  93
  94const char *inet_strfamily(int family)
  95{
  96    switch (family) {
  97    case PF_INET6: return "ipv6";
  98    case PF_INET:  return "ipv4";
  99    case PF_UNIX:  return "unix";
 100    }
 101    return "unknown";
 102}
 103
 104static void inet_print_addrinfo(const char *tag, struct addrinfo *res)
 105{
 106    struct addrinfo *e;
 107    char uaddr[INET6_ADDRSTRLEN+1];
 108    char uport[33];
 109
 110    for (e = res; e != NULL; e = e->ai_next) {
 111        getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
 112                    uaddr,INET6_ADDRSTRLEN,uport,32,
 113                    NI_NUMERICHOST | NI_NUMERICSERV);
 114        fprintf(stderr,"%s: getaddrinfo: family %s, host %s, port %s\n",
 115                tag, inet_strfamily(e->ai_family), uaddr, uport);
 116    }
 117}
 118
 119int inet_listen_opts(QemuOpts *opts, int port_offset)
 120{
 121    struct addrinfo ai,*res,*e;
 122    const char *addr;
 123    char port[33];
 124    char uaddr[INET6_ADDRSTRLEN+1];
 125    char uport[33];
 126    int slisten,rc,to,try_next;
 127
 128    memset(&ai,0, sizeof(ai));
 129    ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
 130    ai.ai_family = PF_UNSPEC;
 131    ai.ai_socktype = SOCK_STREAM;
 132
 133    if ((qemu_opt_get(opts, "host") == NULL) ||
 134        (qemu_opt_get(opts, "port") == NULL)) {
 135        fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__);
 136        return -1;
 137    }
 138    pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
 139    addr = qemu_opt_get(opts, "host");
 140
 141    to = qemu_opt_get_number(opts, "to", 0);
 142    if (qemu_opt_get_bool(opts, "ipv4", 0))
 143        ai.ai_family = PF_INET;
 144    if (qemu_opt_get_bool(opts, "ipv6", 0))
 145        ai.ai_family = PF_INET6;
 146
 147    /* lookup */
 148    if (port_offset)
 149        snprintf(port, sizeof(port), "%d", atoi(port) + port_offset);
 150    rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res);
 151    if (rc != 0) {
 152        fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
 153                gai_strerror(rc));
 154        return -1;
 155    }
 156    if (sockets_debug)
 157        inet_print_addrinfo(__FUNCTION__, res);
 158
 159    /* create socket + bind */
 160    for (e = res; e != NULL; e = e->ai_next) {
 161        getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
 162                        uaddr,INET6_ADDRSTRLEN,uport,32,
 163                        NI_NUMERICHOST | NI_NUMERICSERV);
 164        slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
 165        if (slisten < 0) {
 166            fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
 167                    inet_strfamily(e->ai_family), strerror(errno));
 168            continue;
 169        }
 170
 171        setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
 172#ifdef IPV6_V6ONLY
 173        if (e->ai_family == PF_INET6) {
 174            /* listen on both ipv4 and ipv6 */
 175            setsockopt(slisten,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&off,
 176                sizeof(off));
 177        }
 178#endif
 179
 180        for (;;) {
 181            if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
 182                if (sockets_debug)
 183                    fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
 184                        inet_strfamily(e->ai_family), uaddr, inet_getport(e));
 185                goto listen;
 186            }
 187            try_next = to && (inet_getport(e) <= to + port_offset);
 188            if (!try_next || sockets_debug)
 189                fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
 190                        inet_strfamily(e->ai_family), uaddr, inet_getport(e),
 191                        strerror(errno));
 192            if (try_next) {
 193                inet_setport(e, inet_getport(e) + 1);
 194                continue;
 195            }
 196            break;
 197        }
 198        closesocket(slisten);
 199    }
 200    fprintf(stderr, "%s: FAILED\n", __FUNCTION__);
 201    freeaddrinfo(res);
 202    return -1;
 203
 204listen:
 205    if (listen(slisten,1) != 0) {
 206        perror("listen");
 207        closesocket(slisten);
 208        freeaddrinfo(res);
 209        return -1;
 210    }
 211    snprintf(uport, sizeof(uport), "%d", inet_getport(e) - port_offset);
 212    qemu_opt_set(opts, "host", uaddr);
 213    qemu_opt_set(opts, "port", uport);
 214    qemu_opt_set(opts, "ipv6", (e->ai_family == PF_INET6) ? "on" : "off");
 215    qemu_opt_set(opts, "ipv4", (e->ai_family != PF_INET6) ? "on" : "off");
 216    freeaddrinfo(res);
 217    return slisten;
 218}
 219
 220int inet_connect_opts(QemuOpts *opts)
 221{
 222    struct addrinfo ai,*res,*e;
 223    const char *addr;
 224    const char *port;
 225    char uaddr[INET6_ADDRSTRLEN+1];
 226    char uport[33];
 227    int sock,rc;
 228
 229    memset(&ai,0, sizeof(ai));
 230    ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
 231    ai.ai_family = PF_UNSPEC;
 232    ai.ai_socktype = SOCK_STREAM;
 233
 234    addr = qemu_opt_get(opts, "host");
 235    port = qemu_opt_get(opts, "port");
 236    if (addr == NULL || port == NULL) {
 237        fprintf(stderr, "inet_connect: host and/or port not specified\n");
 238        return -1;
 239    }
 240
 241    if (qemu_opt_get_bool(opts, "ipv4", 0))
 242        ai.ai_family = PF_INET;
 243    if (qemu_opt_get_bool(opts, "ipv6", 0))
 244        ai.ai_family = PF_INET6;
 245
 246    /* lookup */
 247    if (0 != (rc = getaddrinfo(addr, port, &ai, &res))) {
 248        fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
 249                gai_strerror(rc));
 250        return -1;
 251    }
 252    if (sockets_debug)
 253        inet_print_addrinfo(__FUNCTION__, res);
 254
 255    for (e = res; e != NULL; e = e->ai_next) {
 256        if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
 257                            uaddr,INET6_ADDRSTRLEN,uport,32,
 258                            NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
 259            fprintf(stderr,"%s: getnameinfo: oops\n", __FUNCTION__);
 260            continue;
 261        }
 262        sock = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol);
 263        if (sock < 0) {
 264            fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
 265            inet_strfamily(e->ai_family), strerror(errno));
 266            continue;
 267        }
 268        setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
 269
 270        /* connect to peer */
 271        if (connect(sock,e->ai_addr,e->ai_addrlen) < 0) {
 272            if (sockets_debug || NULL == e->ai_next)
 273                fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
 274                        inet_strfamily(e->ai_family),
 275                        e->ai_canonname, uaddr, uport, strerror(errno));
 276            closesocket(sock);
 277            continue;
 278        }
 279        if (sockets_debug)
 280            fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__,
 281                    inet_strfamily(e->ai_family),
 282                    e->ai_canonname, uaddr, uport);
 283        freeaddrinfo(res);
 284        return sock;
 285    }
 286    freeaddrinfo(res);
 287    return -1;
 288}
 289
 290int inet_dgram_opts(QemuOpts *opts)
 291{
 292    struct addrinfo ai, *peer = NULL, *local = NULL;
 293    const char *addr;
 294    const char *port;
 295    char uaddr[INET6_ADDRSTRLEN+1];
 296    char uport[33];
 297    int sock = -1, rc;
 298
 299    /* lookup peer addr */
 300    memset(&ai,0, sizeof(ai));
 301    ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
 302    ai.ai_family = PF_UNSPEC;
 303    ai.ai_socktype = SOCK_DGRAM;
 304
 305    addr = qemu_opt_get(opts, "host");
 306    port = qemu_opt_get(opts, "port");
 307    if (addr == NULL || strlen(addr) == 0) {
 308        addr = "localhost";
 309    }
 310    if (port == NULL || strlen(port) == 0) {
 311        fprintf(stderr, "inet_dgram: port not specified\n");
 312        return -1;
 313    }
 314
 315    if (qemu_opt_get_bool(opts, "ipv4", 0))
 316        ai.ai_family = PF_INET;
 317    if (qemu_opt_get_bool(opts, "ipv6", 0))
 318        ai.ai_family = PF_INET6;
 319
 320    if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) {
 321        fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
 322                gai_strerror(rc));
 323        return -1;
 324    }
 325    if (sockets_debug) {
 326        fprintf(stderr, "%s: peer (%s:%s)\n", __FUNCTION__, addr, port);
 327        inet_print_addrinfo(__FUNCTION__, peer);
 328    }
 329
 330    /* lookup local addr */
 331    memset(&ai,0, sizeof(ai));
 332    ai.ai_flags = AI_PASSIVE;
 333    ai.ai_family = peer->ai_family;
 334    ai.ai_socktype = SOCK_DGRAM;
 335
 336    addr = qemu_opt_get(opts, "localaddr");
 337    port = qemu_opt_get(opts, "localport");
 338    if (addr == NULL || strlen(addr) == 0) {
 339        addr = NULL;
 340    }
 341    if (!port || strlen(port) == 0)
 342        port = "0";
 343
 344    if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) {
 345        fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port,
 346                gai_strerror(rc));
 347        return -1;
 348    }
 349    if (sockets_debug) {
 350        fprintf(stderr, "%s: local (%s:%s)\n", __FUNCTION__, addr, port);
 351        inet_print_addrinfo(__FUNCTION__, local);
 352    }
 353
 354    /* create socket */
 355    sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol);
 356    if (sock < 0) {
 357        fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
 358                inet_strfamily(peer->ai_family), strerror(errno));
 359        goto err;
 360    }
 361    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
 362
 363    /* bind socket */
 364    if (getnameinfo((struct sockaddr*)local->ai_addr,local->ai_addrlen,
 365                    uaddr,INET6_ADDRSTRLEN,uport,32,
 366                    NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
 367        fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__);
 368        goto err;
 369    }
 370    if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) {
 371        fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
 372                inet_strfamily(local->ai_family), uaddr, inet_getport(local));
 373        goto err;
 374    }
 375
 376    /* connect to peer */
 377    if (getnameinfo((struct sockaddr*)peer->ai_addr, peer->ai_addrlen,
 378                    uaddr, INET6_ADDRSTRLEN, uport, 32,
 379                    NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
 380        fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__);
 381        goto err;
 382    }
 383    if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) {
 384        fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
 385                inet_strfamily(peer->ai_family),
 386                peer->ai_canonname, uaddr, uport, strerror(errno));
 387        goto err;
 388    }
 389
 390    freeaddrinfo(local);
 391    freeaddrinfo(peer);
 392    return sock;
 393
 394err:
 395    if (-1 != sock)
 396        closesocket(sock);
 397    if (local)
 398        freeaddrinfo(local);
 399    if (peer)
 400        freeaddrinfo(peer);
 401    return -1;
 402}
 403
 404/* compatibility wrapper */
 405static int inet_parse(QemuOpts *opts, const char *str)
 406{
 407    const char *optstr, *h;
 408    char addr[64];
 409    char port[33];
 410    int pos;
 411
 412    /* parse address */
 413    if (str[0] == ':') {
 414        /* no host given */
 415        addr[0] = '\0';
 416        if (1 != sscanf(str,":%32[^,]%n",port,&pos)) {
 417            fprintf(stderr, "%s: portonly parse error (%s)\n",
 418                    __FUNCTION__, str);
 419            return -1;
 420        }
 421    } else if (str[0] == '[') {
 422        /* IPv6 addr */
 423        if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) {
 424            fprintf(stderr, "%s: ipv6 parse error (%s)\n",
 425                    __FUNCTION__, str);
 426            return -1;
 427        }
 428        qemu_opt_set(opts, "ipv6", "on");
 429    } else if (qemu_isdigit(str[0])) {
 430        /* IPv4 addr */
 431        if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) {
 432            fprintf(stderr, "%s: ipv4 parse error (%s)\n",
 433                    __FUNCTION__, str);
 434            return -1;
 435        }
 436        qemu_opt_set(opts, "ipv4", "on");
 437    } else {
 438        /* hostname */
 439        if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) {
 440            fprintf(stderr, "%s: hostname parse error (%s)\n",
 441                    __FUNCTION__, str);
 442            return -1;
 443        }
 444    }
 445    qemu_opt_set(opts, "host", addr);
 446    qemu_opt_set(opts, "port", port);
 447
 448    /* parse options */
 449    optstr = str + pos;
 450    h = strstr(optstr, ",to=");
 451    if (h)
 452        qemu_opt_set(opts, "to", h+4);
 453    if (strstr(optstr, ",ipv4"))
 454        qemu_opt_set(opts, "ipv4", "on");
 455    if (strstr(optstr, ",ipv6"))
 456        qemu_opt_set(opts, "ipv6", "on");
 457    return 0;
 458}
 459
 460int inet_listen(const char *str, char *ostr, int olen,
 461                int socktype, int port_offset)
 462{
 463    QemuOpts *opts;
 464    char *optstr;
 465    int sock = -1;
 466
 467    opts = qemu_opts_create(&dummy_opts, NULL, 0);
 468    if (inet_parse(opts, str) == 0) {
 469        sock = inet_listen_opts(opts, port_offset);
 470        if (sock != -1 && ostr) {
 471            optstr = strchr(str, ',');
 472            if (qemu_opt_get_bool(opts, "ipv6", 0)) {
 473                snprintf(ostr, olen, "[%s]:%s%s",
 474                         qemu_opt_get(opts, "host"),
 475                         qemu_opt_get(opts, "port"),
 476                         optstr ? optstr : "");
 477            } else {
 478                snprintf(ostr, olen, "%s:%s%s",
 479                         qemu_opt_get(opts, "host"),
 480                         qemu_opt_get(opts, "port"),
 481                         optstr ? optstr : "");
 482            }
 483        }
 484    }
 485    qemu_opts_del(opts);
 486    return sock;
 487}
 488
 489int inet_connect(const char *str, int socktype)
 490{
 491    QemuOpts *opts;
 492    int sock = -1;
 493
 494    opts = qemu_opts_create(&dummy_opts, NULL, 0);
 495    if (inet_parse(opts, str) == 0)
 496        sock = inet_connect_opts(opts);
 497    qemu_opts_del(opts);
 498    return sock;
 499}
 500
 501#ifndef _WIN32
 502
 503int unix_listen_opts(QemuOpts *opts)
 504{
 505    struct sockaddr_un un;
 506    const char *path = qemu_opt_get(opts, "path");
 507    int sock, fd;
 508
 509    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
 510    if (sock < 0) {
 511        perror("socket(unix)");
 512        return -1;
 513    }
 514
 515    memset(&un, 0, sizeof(un));
 516    un.sun_family = AF_UNIX;
 517    if (path && strlen(path)) {
 518        snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
 519    } else {
 520        char *tmpdir = getenv("TMPDIR");
 521        snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX",
 522                 tmpdir ? tmpdir : "/tmp");
 523        /*
 524         * This dummy fd usage silences the mktemp() unsecure warning.
 525         * Using mkstemp() doesn't make things more secure here
 526         * though.  bind() complains about existing files, so we have
 527         * to unlink first and thus re-open the race window.  The
 528         * worst case possible is bind() failing, i.e. a DoS attack.
 529         */
 530        fd = mkstemp(un.sun_path); close(fd);
 531        qemu_opt_set(opts, "path", un.sun_path);
 532    }
 533
 534    unlink(un.sun_path);
 535    if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
 536        fprintf(stderr, "bind(unix:%s): %s\n", un.sun_path, strerror(errno));
 537        goto err;
 538    }
 539    if (listen(sock, 1) < 0) {
 540        fprintf(stderr, "listen(unix:%s): %s\n", un.sun_path, strerror(errno));
 541        goto err;
 542    }
 543
 544    if (sockets_debug)
 545        fprintf(stderr, "bind(unix:%s): OK\n", un.sun_path);
 546    return sock;
 547
 548err:
 549    closesocket(sock);
 550    return -1;
 551}
 552
 553int unix_connect_opts(QemuOpts *opts)
 554{
 555    struct sockaddr_un un;
 556    const char *path = qemu_opt_get(opts, "path");
 557    int sock;
 558
 559    if (NULL == path) {
 560        fprintf(stderr, "unix connect: no path specified\n");
 561        return -1;
 562    }
 563
 564    sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
 565    if (sock < 0) {
 566        perror("socket(unix)");
 567        return -1;
 568    }
 569
 570    memset(&un, 0, sizeof(un));
 571    un.sun_family = AF_UNIX;
 572    snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
 573    if (connect(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
 574        fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno));
 575        return -1;
 576    }
 577
 578    if (sockets_debug)
 579        fprintf(stderr, "connect(unix:%s): OK\n", path);
 580    return sock;
 581}
 582
 583/* compatibility wrapper */
 584int unix_listen(const char *str, char *ostr, int olen)
 585{
 586    QemuOpts *opts;
 587    char *path, *optstr;
 588    int sock, len;
 589
 590    opts = qemu_opts_create(&dummy_opts, NULL, 0);
 591
 592    optstr = strchr(str, ',');
 593    if (optstr) {
 594        len = optstr - str;
 595        if (len) {
 596            path = qemu_malloc(len+1);
 597            snprintf(path, len+1, "%.*s", len, str);
 598            qemu_opt_set(opts, "path", path);
 599            qemu_free(path);
 600        }
 601    } else {
 602        qemu_opt_set(opts, "path", str);
 603    }
 604
 605    sock = unix_listen_opts(opts);
 606
 607    if (sock != -1 && ostr)
 608        snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : "");
 609    qemu_opts_del(opts);
 610    return sock;
 611}
 612
 613int unix_connect(const char *path)
 614{
 615    QemuOpts *opts;
 616    int sock;
 617
 618    opts = qemu_opts_create(&dummy_opts, NULL, 0);
 619    qemu_opt_set(opts, "path", path);
 620    sock = unix_connect_opts(opts);
 621    qemu_opts_del(opts);
 622    return sock;
 623}
 624
 625#else
 626
 627int unix_listen_opts(QemuOpts *opts)
 628{
 629    fprintf(stderr, "unix sockets are not available on windows\n");
 630    return -1;
 631}
 632
 633int unix_connect_opts(QemuOpts *opts)
 634{
 635    fprintf(stderr, "unix sockets are not available on windows\n");
 636    return -1;
 637}
 638
 639int unix_listen(const char *path, char *ostr, int olen)
 640{
 641    fprintf(stderr, "unix sockets are not available on windows\n");
 642    return -1;
 643}
 644
 645int unix_connect(const char *path)
 646{
 647    fprintf(stderr, "unix sockets are not available on windows\n");
 648    return -1;
 649}
 650
 651#endif
 652
 653#ifdef _WIN32
 654static void socket_cleanup(void)
 655{
 656    WSACleanup();
 657}
 658#endif
 659
 660int socket_init(void)
 661{
 662#ifdef _WIN32
 663    WSADATA Data;
 664    int ret, err;
 665
 666    ret = WSAStartup(MAKEWORD(2,2), &Data);
 667    if (ret != 0) {
 668        err = WSAGetLastError();
 669        fprintf(stderr, "WSAStartup: %d\n", err);
 670        return -1;
 671    }
 672    atexit(socket_cleanup);
 673#endif
 674    return 0;
 675}
 676