Statistics
| Branch: | Revision:

root / qemu-sockets.c @ dc1c13d9

History | View | Annotate | Download (19.1 kB)

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