blob: b07129bb399ec5d792f2f7fb816e0a3d44d98e7d [file] [log] [blame]
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001/*
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
David 'Digit' Turnerca6a2e02010-12-23 00:59:44 +010029#ifndef INET6_ADDRSTRLEN
30# define INET6_ADDRSTRLEN 46
31#endif
32
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070033static int sockets_debug = 0;
34static const int on=1, off=0;
35
David Turner315ceb82010-09-10 14:15:17 +020036/* used temporarely until all users are converted to QemuOpts */
37static QemuOptsList dummy_opts = {
38 .name = "dummy",
39 .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head),
40 .desc = {
41 {
42 .name = "path",
43 .type = QEMU_OPT_STRING,
44 },{
45 .name = "host",
46 .type = QEMU_OPT_STRING,
47 },{
48 .name = "port",
49 .type = QEMU_OPT_STRING,
50 },{
51 .name = "to",
52 .type = QEMU_OPT_NUMBER,
53 },{
54 .name = "ipv4",
55 .type = QEMU_OPT_BOOL,
56 },{
57 .name = "ipv6",
58 .type = QEMU_OPT_BOOL,
David 'Digit' Turner8423ffa2010-12-23 00:57:28 +010059#ifdef CONFIG_ANDROID
60 },{
61 .name = "socket",
62 .type = QEMU_OPT_NUMBER,
63#endif
David Turner315ceb82010-09-10 14:15:17 +020064 },
65 { /* end if list */ }
66 },
67};
68
69
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070070static const char *sock_address_strfamily(SockAddress *s)
71{
72 switch (sock_address_get_family(s)) {
73 case SOCKET_IN6: return "ipv6";
74 case SOCKET_INET: return "ipv4";
75 case SOCKET_UNIX: return "unix";
76 default: return "????";
77 }
78}
79
David Turner315ceb82010-09-10 14:15:17 +020080int inet_listen_opts(QemuOpts *opts, int port_offset)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070081{
82 SockAddress** list;
83 SockAddress* e;
84 unsigned flags = SOCKET_LIST_PASSIVE;
David Turner315ceb82010-09-10 14:15:17 +020085 const char *addr;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070086 char port[33];
87 char uaddr[256+1];
David Turner315ceb82010-09-10 14:15:17 +020088 char uport[33];
89 int slisten,to,try_next,nn;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070090
David 'Digit' Turner8423ffa2010-12-23 00:57:28 +010091#ifdef CONFIG_ANDROID
92 const char* socket_fd = qemu_opt_get(opts, "socket");
93 if (socket_fd) {
94 return atoi(socket_fd);
95 }
96#endif
97
David Turner315ceb82010-09-10 14:15:17 +020098 if ((qemu_opt_get(opts, "host") == NULL) ||
99 (qemu_opt_get(opts, "port") == NULL)) {
100 fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__);
101 return -1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700102 }
David Turner315ceb82010-09-10 14:15:17 +0200103 pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port"));
104 addr = qemu_opt_get(opts, "host");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700105
David Turner315ceb82010-09-10 14:15:17 +0200106 to = qemu_opt_get_number(opts, "to", 0);
107 if (qemu_opt_get_bool(opts, "ipv4", 0))
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700108 flags |= SOCKET_LIST_FORCE_INET;
David Turner315ceb82010-09-10 14:15:17 +0200109 if (qemu_opt_get_bool(opts, "ipv6", 0))
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700110 flags |= SOCKET_LIST_FORCE_IN6;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700111
112 /* lookup */
113 if (port_offset)
114 snprintf(port, sizeof(port), "%d", atoi(port) + port_offset);
115
116 list = sock_address_list_create( strlen(addr) ? addr : NULL,
117 port,
118 flags );
119 if (list == NULL) {
120 fprintf(stderr,"%s: getaddrinfo(%s,%s): %s\n", __FUNCTION__,
121 addr, port, errno_str);
122 return -1;
123 }
124
125 /* create socket + bind */
126 for (nn = 0; list[nn] != NULL; nn++) {
127 SocketFamily family;
128
129 e = list[nn];
130 family = sock_address_get_family(e);
David Turner315ceb82010-09-10 14:15:17 +0200131
132 sock_address_get_numeric_info(e, uaddr, sizeof uaddr, uport, sizeof uport);
133 slisten = socket_create(family, SOCKET_STREAM);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700134 if (slisten < 0) {
135 fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
136 sock_address_strfamily(e), errno_str);
137 continue;
138 }
139
140 socket_set_xreuseaddr(slisten);
141#ifdef IPV6_V6ONLY
142 /* listen on both ipv4 and ipv6 */
David Turner315ceb82010-09-10 14:15:17 +0200143 if (family == SOCKET_IN6) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700144 socket_set_ipv6only(slisten);
145 }
146#endif
147
148 for (;;) {
149 if (socket_bind(slisten, e) == 0) {
150 if (sockets_debug)
151 fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
152 sock_address_strfamily(e), uaddr, sock_address_get_port(e));
153 goto listen;
154 }
155 socket_close(slisten);
156 try_next = to && (sock_address_get_port(e) <= to + port_offset);
157 if (!try_next || sockets_debug)
158 fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
159 sock_address_strfamily(e), uaddr, sock_address_get_port(e),
160 strerror(errno));
161 if (try_next) {
162 sock_address_set_port(e, sock_address_get_port(e) + 1);
163 continue;
164 }
165 break;
166 }
167 }
168 sock_address_list_free(list);
169 fprintf(stderr, "%s: FAILED\n", __FUNCTION__);
170 return -1;
171
172listen:
173 if (socket_listen(slisten,1) != 0) {
174 perror("listen");
175 socket_close(slisten);
176 return -1;
177 }
David Turner315ceb82010-09-10 14:15:17 +0200178 snprintf(uport, sizeof(uport), "%d", sock_address_get_port(e) - port_offset);
179 qemu_opt_set(opts, "host", uaddr);
180 qemu_opt_set(opts, "port", uport);
181 qemu_opt_set(opts, "ipv6", (e->family == SOCKET_IN6) ? "on" : "off");
182 qemu_opt_set(opts, "ipv4", (e->family != SOCKET_IN6) ? "on" : "off");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700183 sock_address_list_free(list);
184 return slisten;
185}
186
David Turner315ceb82010-09-10 14:15:17 +0200187int inet_connect_opts(QemuOpts *opts)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700188{
189 SockAddress** list;
190 SockAddress* e;
191 unsigned flags = 0;
David Turner315ceb82010-09-10 14:15:17 +0200192 const char *addr;
193 const char *port;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700194 int sock, nn;
195
David 'Digit' Turner8423ffa2010-12-23 00:57:28 +0100196#ifdef CONFIG_ANDROID
197 const char* socket_fd = qemu_opt_get(opts, "socket");
198 if (socket_fd) {
199 return atoi(socket_fd);
200 }
201#endif
202
David Turner315ceb82010-09-10 14:15:17 +0200203 addr = qemu_opt_get(opts, "host");
204 port = qemu_opt_get(opts, "port");
205 if (addr == NULL || port == NULL) {
206 fprintf(stderr, "inet_connect: host and/or port not specified\n");
207 return -1;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700208 }
209
David Turner315ceb82010-09-10 14:15:17 +0200210 if (qemu_opt_get_bool(opts, "ipv4", 0)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700211 flags &= SOCKET_LIST_FORCE_IN6;
212 flags |= SOCKET_LIST_FORCE_INET;
213 }
David Turner315ceb82010-09-10 14:15:17 +0200214 if (qemu_opt_get_bool(opts, "ipv6", 0)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700215 flags &= SOCKET_LIST_FORCE_INET;
216 flags |= SOCKET_LIST_FORCE_IN6;
217 }
218
219 /* lookup */
220 list = sock_address_list_create(addr, port, flags);
221 if (list == NULL) {
222 fprintf(stderr,"getaddrinfo(%s,%s): %s\n",
223 addr, port, errno_str);
224 return -1;
225 }
226
227 for (nn = 0; list[nn] != NULL; nn++) {
228 e = list[nn];
David Turner315ceb82010-09-10 14:15:17 +0200229 sock = socket_create(sock_address_get_family(e), SOCKET_STREAM);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700230 if (sock < 0) {
231 fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
232 sock_address_strfamily(e), errno_str);
233 continue;
234 }
235 socket_set_xreuseaddr(sock);
236
237 /* connect to peer */
238 if (socket_connect(sock,e) < 0) {
239 if (sockets_debug)
240 fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
241 sock_address_strfamily(e),
242 sock_address_to_string(e), addr, port, strerror(errno));
243 socket_close(sock);
244 continue;
245 }
246 if (sockets_debug)
247 fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__,
248 sock_address_strfamily(e),
249 sock_address_to_string(e), addr, port);
250
251 goto EXIT;
252 }
253 sock = -1;
254EXIT:
255 sock_address_list_free(list);
256 return sock;
257}
258
David 'Digit' Turnerca6a2e02010-12-23 00:59:44 +0100259int inet_dgram_opts(QemuOpts *opts)
260{
261 SockAddress** peer_list = NULL;
262 SockAddress** local_list = NULL;
263 SockAddress* e;
264 unsigned flags = 0;
265 const char *addr;
266 const char *port;
267 char uaddr[INET6_ADDRSTRLEN+1];
268 char uport[33];
269 int sock = -1;
270 int nn;
271
272 /* lookup peer addr */
273 addr = qemu_opt_get(opts, "host");
274 port = qemu_opt_get(opts, "port");
275 if (addr == NULL || strlen(addr) == 0) {
276 addr = "localhost";
277 }
278 if (port == NULL || strlen(port) == 0) {
279 fprintf(stderr, "inet_dgram: port not specified\n");
280 return -1;
281 }
282
283 flags = SOCKET_LIST_DGRAM;
284 if (qemu_opt_get_bool(opts, "ipv4", 0)) {
285 flags &= SOCKET_LIST_FORCE_IN6;
286 flags |= SOCKET_LIST_FORCE_INET;
287 }
288 if (qemu_opt_get_bool(opts, "ipv6", 0)) {
289 flags &= SOCKET_LIST_FORCE_INET;
290 flags |= SOCKET_LIST_FORCE_IN6;
291 }
292
293 peer_list = sock_address_list_create(addr, port, flags);
294 if (peer_list == NULL) {
295 fprintf(stderr,"getaddrinfo(%s,%s): %s\n",
296 addr, port, errno_str);
297 return -1;
298 }
299
300 /* lookup local addr */
301 addr = qemu_opt_get(opts, "localaddr");
302 port = qemu_opt_get(opts, "localport");
303 if (addr == NULL || strlen(addr) == 0) {
304 addr = NULL;
305 }
306 if (!port || strlen(port) == 0)
307 port = "0";
308
309 flags = SOCKET_LIST_DGRAM | SOCKET_LIST_PASSIVE;
310 local_list = sock_address_list_create(addr, port, flags);
311 if (local_list == NULL) {
312 fprintf(stderr,"getaddrinfo(%s,%s): %s\n",
313 addr, port, errno_str);
314 goto EXIT;
315 }
316
317 if (sock_address_get_numeric_info(local_list[0],
318 uaddr, INET6_ADDRSTRLEN,
319 uport, 32)) {
320 fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__);
321 goto EXIT;
322 }
323
324 for (nn = 0; peer_list[nn] != NULL; nn++) {
325 SockAddress *local = local_list[0];
326 e = peer_list[nn];
327 sock = socket_create(sock_address_get_family(e), SOCKET_DGRAM);
328 if (sock < 0) {
329 fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__,
330 sock_address_strfamily(e), errno_str);
331 continue;
332 }
333 socket_set_xreuseaddr(sock);
334
335 /* bind socket */
336 if (socket_bind(sock, local) < 0) {
337 fprintf(stderr,"%s: bind(%s,%s,%s): OK\n", __FUNCTION__,
338 sock_address_strfamily(local), addr, port);
339 socket_close(sock);
340 continue;
341 }
342
343 /* connect to peer */
344 if (socket_connect(sock,e) < 0) {
345 if (sockets_debug)
346 fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
347 sock_address_strfamily(e),
348 sock_address_to_string(e), addr, port, strerror(errno));
349 socket_close(sock);
350 continue;
351 }
352 if (sockets_debug)
353 fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__,
354 sock_address_strfamily(e),
355 sock_address_to_string(e), addr, port);
356
357 goto EXIT;
358 }
359 sock = -1;
360EXIT:
361 if (local_list)
362 sock_address_list_free(local_list);
363 if (peer_list)
364 sock_address_list_free(peer_list);
365 return sock;
366}
David 'Digit' Turner8423ffa2010-12-23 00:57:28 +0100367
David Turner315ceb82010-09-10 14:15:17 +0200368/* compatibility wrapper */
369static int inet_parse(QemuOpts *opts, const char *str)
370{
371 const char *optstr, *h;
372 char addr[64];
373 char port[33];
374 int pos;
375
376 /* parse address */
377 if (str[0] == ':') {
378 /* no host given */
379 addr[0] = '\0';
380 if (1 != sscanf(str,":%32[^,]%n",port,&pos)) {
381 fprintf(stderr, "%s: portonly parse error (%s)\n",
382 __FUNCTION__, str);
383 return -1;
384 }
385 } else if (str[0] == '[') {
386 /* IPv6 addr */
387 if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) {
388 fprintf(stderr, "%s: ipv6 parse error (%s)\n",
389 __FUNCTION__, str);
390 return -1;
391 }
392 qemu_opt_set(opts, "ipv6", "on");
393 } else if (qemu_isdigit(str[0])) {
394 /* IPv4 addr */
395 if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) {
396 fprintf(stderr, "%s: ipv4 parse error (%s)\n",
397 __FUNCTION__, str);
398 return -1;
399 }
400 qemu_opt_set(opts, "ipv4", "on");
401 } else {
402 /* hostname */
403 if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) {
404 fprintf(stderr, "%s: hostname parse error (%s)\n",
405 __FUNCTION__, str);
406 return -1;
407 }
408 }
409 qemu_opt_set(opts, "host", addr);
410 qemu_opt_set(opts, "port", port);
411
412 /* parse options */
413 optstr = str + pos;
414 h = strstr(optstr, ",to=");
415 if (h)
416 qemu_opt_set(opts, "to", h+4);
417 if (strstr(optstr, ",ipv4"))
418 qemu_opt_set(opts, "ipv4", "on");
419 if (strstr(optstr, ",ipv6"))
420 qemu_opt_set(opts, "ipv6", "on");
David 'Digit' Turner8423ffa2010-12-23 00:57:28 +0100421#ifdef CONFIG_ANDROID
422 h = strstr(optstr, ",socket=");
423 if (h) {
424 int socket_fd;
425 char str_fd[12];
426 if (1 != sscanf(h+7,"%d",&socket_fd)) {
427 fprintf(stderr,"%s: socket fd parse error (%s)\n",
428 __FUNCTION__, h+7);
429 return -1;
430 }
431 if (socket_fd < 0 || socket_fd >= INT_MAX) {
432 fprintf(stderr,"%s: socket fd range error (%d)\n",
433 __FUNCTION__, socket_fd);
434 return -1;
435 }
436 snprintf(str_fd, sizeof str_fd, "%d", socket_fd);
437 qemu_opt_set(opts, "socket", str_fd);
438 }
439#endif
David Turner315ceb82010-09-10 14:15:17 +0200440 return 0;
441}
442
443int inet_listen(const char *str, char *ostr, int olen,
444 int socktype, int port_offset)
445{
446 QemuOpts *opts;
447 char *optstr;
448 int sock = -1;
449
450 opts = qemu_opts_create(&dummy_opts, NULL, 0);
451 if (inet_parse(opts, str) == 0) {
452 sock = inet_listen_opts(opts, port_offset);
453 if (sock != -1 && ostr) {
454 optstr = strchr(str, ',');
455 if (qemu_opt_get_bool(opts, "ipv6", 0)) {
456 snprintf(ostr, olen, "[%s]:%s%s",
457 qemu_opt_get(opts, "host"),
458 qemu_opt_get(opts, "port"),
459 optstr ? optstr : "");
460 } else {
461 snprintf(ostr, olen, "%s:%s%s",
462 qemu_opt_get(opts, "host"),
463 qemu_opt_get(opts, "port"),
464 optstr ? optstr : "");
465 }
466 }
467 }
468 qemu_opts_del(opts);
469 return sock;
470}
471
472int inet_connect(const char *str, int socktype)
473{
474 QemuOpts *opts;
475 int sock = -1;
476
477 opts = qemu_opts_create(&dummy_opts, NULL, 0);
478 if (inet_parse(opts, str) == 0)
479 sock = inet_connect_opts(opts);
480 qemu_opts_del(opts);
481 return sock;
482}
483
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700484#ifndef _WIN32
485
David Turner315ceb82010-09-10 14:15:17 +0200486int unix_listen_opts(QemuOpts *opts)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700487{
David Turner315ceb82010-09-10 14:15:17 +0200488 const char *path = qemu_opt_get(opts, "path");
489 char unpath[PATH_MAX];
490 const char *upath;
491 int sock, fd;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700492
David Turner315ceb82010-09-10 14:15:17 +0200493 if (path && strlen(path)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700494 upath = path;
495 } else {
496 char *tmpdir = getenv("TMPDIR");
497 snprintf(unpath, sizeof(unpath), "%s/qemu-socket-XXXXXX",
498 tmpdir ? tmpdir : "/tmp");
David Turner315ceb82010-09-10 14:15:17 +0200499 upath = unpath;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700500 /*
501 * This dummy fd usage silences the mktemp() unsecure warning.
502 * Using mkstemp() doesn't make things more secure here
503 * though. bind() complains about existing files, so we have
504 * to unlink first and thus re-open the race window. The
505 * worst case possible is bind() failing, i.e. a DoS attack.
506 */
507 fd = mkstemp(unpath); close(fd);
David Turner315ceb82010-09-10 14:15:17 +0200508 qemu_opt_set(opts, "path", unpath);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700509 }
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700510
511 sock = socket_unix_server(upath, SOCKET_STREAM);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700512
513 if (sock < 0) {
514 fprintf(stderr, "bind(unix:%s): %s\n", upath, errno_str);
515 goto err;
516 }
517
518 if (sockets_debug)
519 fprintf(stderr, "bind(unix:%s): OK\n", upath);
520
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700521 return sock;
522
523err:
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700524 socket_close(sock);
525 return -1;
526}
527
David Turner315ceb82010-09-10 14:15:17 +0200528int unix_connect_opts(QemuOpts *opts)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700529{
530 SockAddress un;
David Turner315ceb82010-09-10 14:15:17 +0200531 const char *path = qemu_opt_get(opts, "path");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700532 int ret, sock;
533
534 sock = socket_create_unix(SOCKET_STREAM);
535 if (sock < 0) {
536 perror("socket(unix)");
537 return -1;
538 }
539
540 sock_address_init_unix(&un, path);
541 ret = socket_connect(sock, &un);
542 sock_address_done(&un);
543 if (ret < 0) {
544 fprintf(stderr, "connect(unix:%s): %s\n", path, errno_str);
545 return -1;
546 }
547
548
549 if (sockets_debug)
550 fprintf(stderr, "connect(unix:%s): OK\n", path);
551 return sock;
552}
553
David Turner315ceb82010-09-10 14:15:17 +0200554/* compatibility wrapper */
555int unix_listen(const char *str, char *ostr, int olen)
556{
557 QemuOpts *opts;
558 char *path, *optstr;
559 int sock, len;
560
561 opts = qemu_opts_create(&dummy_opts, NULL, 0);
562
563 optstr = strchr(str, ',');
564 if (optstr) {
565 len = optstr - str;
566 if (len) {
567 path = qemu_malloc(len+1);
568 snprintf(path, len+1, "%.*s", len, str);
569 qemu_opt_set(opts, "path", path);
570 qemu_free(path);
571 }
572 } else {
573 qemu_opt_set(opts, "path", str);
574 }
575
576 sock = unix_listen_opts(opts);
577
578 if (sock != -1 && ostr)
579 snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : "");
580 qemu_opts_del(opts);
581 return sock;
582}
583
584int unix_connect(const char *path)
585{
586 QemuOpts *opts;
587 int sock;
588
589 opts = qemu_opts_create(&dummy_opts, NULL, 0);
590 qemu_opt_set(opts, "path", path);
591 sock = unix_connect_opts(opts);
592 qemu_opts_del(opts);
593 return sock;
594}
595
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700596#else
597
David Turner315ceb82010-09-10 14:15:17 +0200598int unix_listen_opts(QemuOpts *opts)
599{
600 fprintf(stderr, "unix sockets are not available on windows\n");
601 return -1;
602}
603
604int unix_connect_opts(QemuOpts *opts)
605{
606 fprintf(stderr, "unix sockets are not available on windows\n");
607 return -1;
608}
609
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700610int unix_listen(const char *path, char *ostr, int olen)
611{
612 fprintf(stderr, "unix sockets are not available on windows\n");
613 return -1;
614}
615
616int unix_connect(const char *path)
617{
618 fprintf(stderr, "unix sockets are not available on windows\n");
619 return -1;
620}
621
622#endif
David Turner315ceb82010-09-10 14:15:17 +0200623
624#ifndef CONFIG_ANDROID /* see sockets.c */
625#ifdef _WIN32
626static void socket_cleanup(void)
627{
628 WSACleanup();
629}
630#endif
631
632int socket_init(void)
633{
634#ifdef _WIN32
635 WSADATA Data;
636 int ret, err;
637
638 ret = WSAStartup(MAKEWORD(2,2), &Data);
639 if (ret != 0) {
640 err = WSAGetLastError();
641 fprintf(stderr, "WSAStartup: %d\n", err);
642 return -1;
643 }
644 atexit(socket_cleanup);
645#endif
646 return 0;
647}
648#endif /* !CONFIG_ANDROID */