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