15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * inet and unix socket functions for qemu 35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * (c) 2008 Gerd Hoffmann <kraxel@redhat.com> 55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This program is free software; you can redistribute it and/or modify 75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * it under the terms of the GNU General Public License as published by 85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the Free Software Foundation; under version 2 of the License. 95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This program is distributed in the hope that it will be useful, 115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * but WITHOUT ANY WARRANTY; without even the implied warranty of 125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * GNU General Public License for more details. 145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <stdio.h> 165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <stdlib.h> 175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <string.h> 185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <ctype.h> 195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <errno.h> 205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <unistd.h> 215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22d0edecb426b34ddb9b10b81dea19aee04a61a385David 'Digit' Turner#include "qemu/sockets.h" 235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h" /* for qemu_isdigit */ 245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef AI_ADDRCONFIG 265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define AI_ADDRCONFIG 0 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 29ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner#ifndef INET6_ADDRSTRLEN 30ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner# define INET6_ADDRSTRLEN 46 31ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner#endif 32ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner 335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int sockets_debug = 0; 345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const int on=1, off=0; 355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 36315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner/* used temporarely until all users are converted to QemuOpts */ 37315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerstatic QemuOptsList dummy_opts = { 38315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .name = "dummy", 39315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head), 40315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .desc = { 41315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner { 42315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .name = "path", 43315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .type = QEMU_OPT_STRING, 44315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner },{ 45315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .name = "host", 46315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .type = QEMU_OPT_STRING, 47315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner },{ 48315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .name = "port", 49315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .type = QEMU_OPT_STRING, 50315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner },{ 51315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .name = "to", 52315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .type = QEMU_OPT_NUMBER, 53315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner },{ 54315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .name = "ipv4", 55315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .type = QEMU_OPT_BOOL, 56315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner },{ 57315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .name = "ipv6", 58315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner .type = QEMU_OPT_BOOL, 598423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner#ifdef CONFIG_ANDROID 608423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner },{ 618423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner .name = "socket", 628423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner .type = QEMU_OPT_NUMBER, 638423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner#endif 64315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner }, 65315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner { /* end if list */ } 66315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner }, 67315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner}; 68315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 69315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const char *sock_address_strfamily(SockAddress *s) 715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (sock_address_get_family(s)) { 735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case SOCKET_IN6: return "ipv6"; 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case SOCKET_INET: return "ipv4"; 755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case SOCKET_UNIX: return "unix"; 765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: return "????"; 775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 80315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerint inet_listen_opts(QemuOpts *opts, int port_offset) 815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SockAddress** list; 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SockAddress* e; 845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned flags = SOCKET_LIST_PASSIVE; 85315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner const char *addr; 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char port[33]; 875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char uaddr[256+1]; 88315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner char uport[33]; 89315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner int slisten,to,try_next,nn; 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 918423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner#ifdef CONFIG_ANDROID 928423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner const char* socket_fd = qemu_opt_get(opts, "socket"); 938423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner if (socket_fd) { 948423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner return atoi(socket_fd); 958423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner } 968423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner#endif 978423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner 98315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if ((qemu_opt_get(opts, "host") == NULL) || 99315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner (qemu_opt_get(opts, "port") == NULL)) { 100315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__); 101315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return -1; 1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 103315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port")); 104315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner addr = qemu_opt_get(opts, "host"); 1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 106315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner to = qemu_opt_get_number(opts, "to", 0); 107315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (qemu_opt_get_bool(opts, "ipv4", 0)) 1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner flags |= SOCKET_LIST_FORCE_INET; 109315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (qemu_opt_get_bool(opts, "ipv6", 0)) 1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner flags |= SOCKET_LIST_FORCE_IN6; 1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* lookup */ 1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (port_offset) 1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(port, sizeof(port), "%d", atoi(port) + port_offset); 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner list = sock_address_list_create( strlen(addr) ? addr : NULL, 1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner port, 1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner flags ); 1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (list == NULL) { 1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr,"%s: getaddrinfo(%s,%s): %s\n", __FUNCTION__, 1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr, port, errno_str); 1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* create socket + bind */ 1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (nn = 0; list[nn] != NULL; nn++) { 1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SocketFamily family; 1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner e = list[nn]; 1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner family = sock_address_get_family(e); 131315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 132315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner sock_address_get_numeric_info(e, uaddr, sizeof uaddr, uport, sizeof uport); 133315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner slisten = socket_create(family, SOCKET_STREAM); 1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slisten < 0) { 1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, 1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_strfamily(e), errno_str); 1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_set_xreuseaddr(slisten); 1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef IPV6_V6ONLY 1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* listen on both ipv4 and ipv6 */ 143315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (family == SOCKET_IN6) { 1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_set_ipv6only(slisten); 1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (;;) { 1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (socket_bind(slisten, e) == 0) { 1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sockets_debug) 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__, 1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_strfamily(e), uaddr, sock_address_get_port(e)); 1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto listen; 1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_close(slisten); 1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner try_next = to && (sock_address_get_port(e) <= to + port_offset); 1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!try_next || sockets_debug) 1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__, 1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_strfamily(e), uaddr, sock_address_get_port(e), 1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner strerror(errno)); 1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (try_next) { 1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_set_port(e, sock_address_get_port(e) + 1); 1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_list_free(list); 1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "%s: FAILED\n", __FUNCTION__); 1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerlisten: 1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (socket_listen(slisten,1) != 0) { 1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner perror("listen"); 1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_close(slisten); 1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 178315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner snprintf(uport, sizeof(uport), "%d", sock_address_get_port(e) - port_offset); 179315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "host", uaddr); 180315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "port", uport); 181315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "ipv6", (e->family == SOCKET_IN6) ? "on" : "off"); 182315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "ipv4", (e->family != SOCKET_IN6) ? "on" : "off"); 1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_list_free(list); 1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return slisten; 1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 187315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerint inet_connect_opts(QemuOpts *opts) 1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SockAddress** list; 1905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SockAddress* e; 1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned flags = 0; 192315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner const char *addr; 193315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner const char *port; 1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int sock, nn; 1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1968423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner#ifdef CONFIG_ANDROID 1978423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner const char* socket_fd = qemu_opt_get(opts, "socket"); 1988423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner if (socket_fd) { 1998423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner return atoi(socket_fd); 2008423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner } 2018423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner#endif 2028423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner 203315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner addr = qemu_opt_get(opts, "host"); 204315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner port = qemu_opt_get(opts, "port"); 205315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (addr == NULL || port == NULL) { 206315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner fprintf(stderr, "inet_connect: host and/or port not specified\n"); 207315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return -1; 2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 210315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (qemu_opt_get_bool(opts, "ipv4", 0)) { 2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner flags &= SOCKET_LIST_FORCE_IN6; 2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner flags |= SOCKET_LIST_FORCE_INET; 2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 214315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (qemu_opt_get_bool(opts, "ipv6", 0)) { 2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner flags &= SOCKET_LIST_FORCE_INET; 2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner flags |= SOCKET_LIST_FORCE_IN6; 2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* lookup */ 2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner list = sock_address_list_create(addr, port, flags); 2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (list == NULL) { 2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr,"getaddrinfo(%s,%s): %s\n", 2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner addr, port, errno_str); 2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (nn = 0; list[nn] != NULL; nn++) { 2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner e = list[nn]; 229315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner sock = socket_create(sock_address_get_family(e), SOCKET_STREAM); 2305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sock < 0) { 2315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, 2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_strfamily(e), errno_str); 2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_set_xreuseaddr(sock); 2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* connect to peer */ 2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (socket_connect(sock,e) < 0) { 2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sockets_debug) 2405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, 2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_strfamily(e), 2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_to_string(e), addr, port, strerror(errno)); 2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_close(sock); 2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sockets_debug) 2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__, 2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_strfamily(e), 2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_to_string(e), addr, port); 2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto EXIT; 2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock = -1; 2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerEXIT: 2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_list_free(list); 2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return sock; 2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 259ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turnerint inet_dgram_opts(QemuOpts *opts) 260ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner{ 261ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner SockAddress** peer_list = NULL; 262ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner SockAddress** local_list = NULL; 263ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner SockAddress* e; 264ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner unsigned flags = 0; 265ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner const char *addr; 266ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner const char *port; 267ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner char uaddr[INET6_ADDRSTRLEN+1]; 268ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner char uport[33]; 269ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner int sock = -1; 270ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner int nn; 271ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner 272ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner /* lookup peer addr */ 273ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner addr = qemu_opt_get(opts, "host"); 274ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner port = qemu_opt_get(opts, "port"); 275ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (addr == NULL || strlen(addr) == 0) { 276ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner addr = "localhost"; 277ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner } 278ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (port == NULL || strlen(port) == 0) { 279ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner fprintf(stderr, "inet_dgram: port not specified\n"); 280ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner return -1; 281ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner } 282ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner 283ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner flags = SOCKET_LIST_DGRAM; 284ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (qemu_opt_get_bool(opts, "ipv4", 0)) { 285ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner flags &= SOCKET_LIST_FORCE_IN6; 286ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner flags |= SOCKET_LIST_FORCE_INET; 287ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner } 288ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (qemu_opt_get_bool(opts, "ipv6", 0)) { 289ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner flags &= SOCKET_LIST_FORCE_INET; 290ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner flags |= SOCKET_LIST_FORCE_IN6; 291ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner } 292ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner 293ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner peer_list = sock_address_list_create(addr, port, flags); 294ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (peer_list == NULL) { 295ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner fprintf(stderr,"getaddrinfo(%s,%s): %s\n", 296ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner addr, port, errno_str); 297ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner return -1; 298ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner } 299ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner 300ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner /* lookup local addr */ 301ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner addr = qemu_opt_get(opts, "localaddr"); 302ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner port = qemu_opt_get(opts, "localport"); 303ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (addr == NULL || strlen(addr) == 0) { 304ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner addr = NULL; 305ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner } 306ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (!port || strlen(port) == 0) 307ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner port = "0"; 308ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner 309ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner flags = SOCKET_LIST_DGRAM | SOCKET_LIST_PASSIVE; 310ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner local_list = sock_address_list_create(addr, port, flags); 311ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (local_list == NULL) { 312ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner fprintf(stderr,"getaddrinfo(%s,%s): %s\n", 313ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner addr, port, errno_str); 314ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner goto EXIT; 315ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner } 316ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner 317ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (sock_address_get_numeric_info(local_list[0], 318ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner uaddr, INET6_ADDRSTRLEN, 319ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner uport, 32)) { 320ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__); 321ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner goto EXIT; 322ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner } 323ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner 324ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner for (nn = 0; peer_list[nn] != NULL; nn++) { 325ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner SockAddress *local = local_list[0]; 326ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner e = peer_list[nn]; 327ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner sock = socket_create(sock_address_get_family(e), SOCKET_DGRAM); 328ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (sock < 0) { 329ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, 330ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner sock_address_strfamily(e), errno_str); 331ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner continue; 332ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner } 333ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner socket_set_xreuseaddr(sock); 334ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner 335ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner /* bind socket */ 336ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (socket_bind(sock, local) < 0) { 337ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner fprintf(stderr,"%s: bind(%s,%s,%s): OK\n", __FUNCTION__, 338ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner sock_address_strfamily(local), addr, port); 339ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner socket_close(sock); 340ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner continue; 341ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner } 342ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner 343ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner /* connect to peer */ 344ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (socket_connect(sock,e) < 0) { 345ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (sockets_debug) 346ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, 347ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner sock_address_strfamily(e), 348ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner sock_address_to_string(e), addr, port, strerror(errno)); 349ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner socket_close(sock); 350ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner continue; 351ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner } 352ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (sockets_debug) 353ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__, 354ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner sock_address_strfamily(e), 355ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner sock_address_to_string(e), addr, port); 356ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner 357ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner goto EXIT; 358ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner } 359ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner sock = -1; 360ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' TurnerEXIT: 361ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (local_list) 362ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner sock_address_list_free(local_list); 363ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner if (peer_list) 364ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner sock_address_list_free(peer_list); 365ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner return sock; 366ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48David 'Digit' Turner} 3678423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner 368315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner/* compatibility wrapper */ 369315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerstatic int inet_parse(QemuOpts *opts, const char *str) 370315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner{ 371315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner const char *optstr, *h; 372315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner char addr[64]; 373315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner char port[33]; 374315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner int pos; 375315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 376315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner /* parse address */ 377315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (str[0] == ':') { 378315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner /* no host given */ 379315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner addr[0] = '\0'; 380315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (1 != sscanf(str,":%32[^,]%n",port,&pos)) { 381315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner fprintf(stderr, "%s: portonly parse error (%s)\n", 382315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner __FUNCTION__, str); 383315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return -1; 384315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } 385315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } else if (str[0] == '[') { 386315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner /* IPv6 addr */ 387315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) { 388315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner fprintf(stderr, "%s: ipv6 parse error (%s)\n", 389315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner __FUNCTION__, str); 390315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return -1; 391315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } 392315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "ipv6", "on"); 393315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } else if (qemu_isdigit(str[0])) { 394315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner /* IPv4 addr */ 395315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) { 396315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner fprintf(stderr, "%s: ipv4 parse error (%s)\n", 397315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner __FUNCTION__, str); 398315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return -1; 399315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } 400315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "ipv4", "on"); 401315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } else { 402315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner /* hostname */ 403315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) { 404315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner fprintf(stderr, "%s: hostname parse error (%s)\n", 405315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner __FUNCTION__, str); 406315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return -1; 407315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } 408315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } 409315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "host", addr); 410315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "port", port); 411315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 412315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner /* parse options */ 413315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner optstr = str + pos; 414315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner h = strstr(optstr, ",to="); 415315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (h) 416315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "to", h+4); 417315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (strstr(optstr, ",ipv4")) 418315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "ipv4", "on"); 419315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (strstr(optstr, ",ipv6")) 420315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "ipv6", "on"); 4218423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner#ifdef CONFIG_ANDROID 4228423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner h = strstr(optstr, ",socket="); 4238423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner if (h) { 4248423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner int socket_fd; 4258423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner char str_fd[12]; 4268423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner if (1 != sscanf(h+7,"%d",&socket_fd)) { 4278423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner fprintf(stderr,"%s: socket fd parse error (%s)\n", 4288423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner __FUNCTION__, h+7); 4298423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner return -1; 4308423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner } 4318423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner if (socket_fd < 0 || socket_fd >= INT_MAX) { 4328423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner fprintf(stderr,"%s: socket fd range error (%d)\n", 4338423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner __FUNCTION__, socket_fd); 4348423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner return -1; 4358423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner } 4368423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner snprintf(str_fd, sizeof str_fd, "%d", socket_fd); 4378423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner qemu_opt_set(opts, "socket", str_fd); 4388423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner } 4398423ffa1a8c56e65220e2a354cd62f71f99a7a06David 'Digit' Turner#endif 440315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return 0; 441315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner} 442315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 443315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerint inet_listen(const char *str, char *ostr, int olen, 444315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner int socktype, int port_offset) 445315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner{ 446315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner QemuOpts *opts; 447315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner char *optstr; 448315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner int sock = -1; 449315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 450315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner opts = qemu_opts_create(&dummy_opts, NULL, 0); 451315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (inet_parse(opts, str) == 0) { 452315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner sock = inet_listen_opts(opts, port_offset); 453315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (sock != -1 && ostr) { 454315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner optstr = strchr(str, ','); 455315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (qemu_opt_get_bool(opts, "ipv6", 0)) { 456315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner snprintf(ostr, olen, "[%s]:%s%s", 457315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_get(opts, "host"), 458315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_get(opts, "port"), 459315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner optstr ? optstr : ""); 460315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } else { 461315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner snprintf(ostr, olen, "%s:%s%s", 462315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_get(opts, "host"), 463315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_get(opts, "port"), 464315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner optstr ? optstr : ""); 465315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } 466315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } 467315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } 468315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opts_del(opts); 469315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return sock; 470315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner} 471315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 472315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerint inet_connect(const char *str, int socktype) 473315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner{ 474315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner QemuOpts *opts; 475315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner int sock = -1; 476315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 477315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner opts = qemu_opts_create(&dummy_opts, NULL, 0); 478315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (inet_parse(opts, str) == 0) 479315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner sock = inet_connect_opts(opts); 480315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opts_del(opts); 481315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return sock; 482315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner} 483315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32 4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 486315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerint unix_listen_opts(QemuOpts *opts) 4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 488315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner const char *path = qemu_opt_get(opts, "path"); 489315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner char unpath[PATH_MAX]; 490315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner const char *upath; 491315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner int sock, fd; 492315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 493315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (path && strlen(path)) { 4945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner upath = path; 4955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 4965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *tmpdir = getenv("TMPDIR"); 4975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(unpath, sizeof(unpath), "%s/qemu-socket-XXXXXX", 4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmpdir ? tmpdir : "/tmp"); 499315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner upath = unpath; 5005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 5015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This dummy fd usage silences the mktemp() unsecure warning. 5025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Using mkstemp() doesn't make things more secure here 5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * though. bind() complains about existing files, so we have 5045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * to unlink first and thus re-open the race window. The 5055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * worst case possible is bind() failing, i.e. a DoS attack. 5065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 5075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd = mkstemp(unpath); close(fd); 508315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "path", unpath); 5095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock = socket_unix_server(upath, SOCKET_STREAM); 5125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sock < 0) { 5145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "bind(unix:%s): %s\n", upath, errno_str); 5155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto err; 5165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sockets_debug) 5195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "bind(unix:%s): OK\n", upath); 5205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return sock; 5225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnererr: 5245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_close(sock); 5255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 5265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 528315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerint unix_connect_opts(QemuOpts *opts) 5295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 5305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SockAddress un; 531315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner const char *path = qemu_opt_get(opts, "path"); 5325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret, sock; 5335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock = socket_create_unix(SOCKET_STREAM); 5355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sock < 0) { 5365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner perror("socket(unix)"); 5375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 5385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_init_unix(&un, path); 5415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = socket_connect(sock, &un); 5425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock_address_done(&un); 5435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 5445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "connect(unix:%s): %s\n", path, errno_str); 5455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 5465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sockets_debug) 5505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "connect(unix:%s): OK\n", path); 5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return sock; 5525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 554315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner/* compatibility wrapper */ 555315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerint unix_listen(const char *str, char *ostr, int olen) 556315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner{ 557315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner QemuOpts *opts; 558315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner char *path, *optstr; 559315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner int sock, len; 560315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 561315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner opts = qemu_opts_create(&dummy_opts, NULL, 0); 562315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 563315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner optstr = strchr(str, ','); 564315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (optstr) { 565315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner len = optstr - str; 566315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (len) { 567aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner path = g_malloc(len+1); 568315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner snprintf(path, len+1, "%.*s", len, str); 569315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "path", path); 570aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner g_free(path); 571315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } 572315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } else { 573315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "path", str); 574315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } 575315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 576315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner sock = unix_listen_opts(opts); 577315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 578315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (sock != -1 && ostr) 579315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : ""); 580315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opts_del(opts); 581315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return sock; 582315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner} 583315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 584315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerint unix_connect(const char *path) 585315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner{ 586315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner QemuOpts *opts; 587315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner int sock; 588315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 589315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner opts = qemu_opts_create(&dummy_opts, NULL, 0); 590315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opt_set(opts, "path", path); 591315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner sock = unix_connect_opts(opts); 592315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner qemu_opts_del(opts); 593315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return sock; 594315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner} 595315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 5965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 5975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 598315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerint unix_listen_opts(QemuOpts *opts) 599315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner{ 600315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner fprintf(stderr, "unix sockets are not available on windows\n"); 601315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return -1; 602315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner} 603315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 604315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerint unix_connect_opts(QemuOpts *opts) 605315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner{ 606315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner fprintf(stderr, "unix sockets are not available on windows\n"); 607315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return -1; 608315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner} 609315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 6105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint unix_listen(const char *path, char *ostr, int olen) 6115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "unix sockets are not available on windows\n"); 6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint unix_connect(const char *path) 6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "unix sockets are not available on windows\n"); 6195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 6205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 623315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 624315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner#ifndef CONFIG_ANDROID /* see sockets.c */ 625315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner#ifdef _WIN32 626315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerstatic void socket_cleanup(void) 627315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner{ 628315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner WSACleanup(); 629315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner} 630315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner#endif 631315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 632315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turnerint socket_init(void) 633315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner{ 634315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner#ifdef _WIN32 635315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner WSADATA Data; 636315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner int ret, err; 637315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner 638315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner ret = WSAStartup(MAKEWORD(2,2), &Data); 639315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner if (ret != 0) { 640315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner err = WSAGetLastError(); 641315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner fprintf(stderr, "WSAStartup: %d\n", err); 642315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return -1; 643315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner } 644315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner atexit(socket_cleanup); 645315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner#endif 646315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner return 0; 647315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner} 648315ceb8a16eb7a2102fee4946898e7b8a202e86aDavid Turner#endif /* !CONFIG_ANDROID */ 649