1baacf047SPaolo Bonzini /* 2baacf047SPaolo Bonzini * inet and unix socket functions for qemu 3baacf047SPaolo Bonzini * 4baacf047SPaolo Bonzini * (c) 2008 Gerd Hoffmann <kraxel@redhat.com> 5baacf047SPaolo Bonzini * 6baacf047SPaolo Bonzini * This program is free software; you can redistribute it and/or modify 7baacf047SPaolo Bonzini * it under the terms of the GNU General Public License as published by 8baacf047SPaolo Bonzini * the Free Software Foundation; under version 2 of the License. 9baacf047SPaolo Bonzini * 10baacf047SPaolo Bonzini * This program is distributed in the hope that it will be useful, 11baacf047SPaolo Bonzini * but WITHOUT ANY WARRANTY; without even the implied warranty of 12baacf047SPaolo Bonzini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13baacf047SPaolo Bonzini * GNU General Public License for more details. 14baacf047SPaolo Bonzini * 15baacf047SPaolo Bonzini * Contributions after 2012-01-13 are licensed under the terms of the 16baacf047SPaolo Bonzini * GNU GPL, version 2 or (at your option) any later version. 17baacf047SPaolo Bonzini */ 18baacf047SPaolo Bonzini #include <stdio.h> 19baacf047SPaolo Bonzini #include <stdlib.h> 20baacf047SPaolo Bonzini #include <string.h> 21baacf047SPaolo Bonzini #include <ctype.h> 22baacf047SPaolo Bonzini #include <errno.h> 23baacf047SPaolo Bonzini #include <unistd.h> 24baacf047SPaolo Bonzini 25baacf047SPaolo Bonzini #include "monitor/monitor.h" 26baacf047SPaolo Bonzini #include "qemu/sockets.h" 27baacf047SPaolo Bonzini #include "qemu-common.h" /* for qemu_isdigit */ 28baacf047SPaolo Bonzini #include "qemu/main-loop.h" 29baacf047SPaolo Bonzini 30baacf047SPaolo Bonzini #ifndef AI_ADDRCONFIG 31baacf047SPaolo Bonzini # define AI_ADDRCONFIG 0 32baacf047SPaolo Bonzini #endif 33baacf047SPaolo Bonzini 34baacf047SPaolo Bonzini static const int on=1, off=0; 35baacf047SPaolo Bonzini 36baacf047SPaolo Bonzini /* used temporarely until all users are converted to QemuOpts */ 37baacf047SPaolo Bonzini static QemuOptsList dummy_opts = { 38baacf047SPaolo Bonzini .name = "dummy", 39baacf047SPaolo Bonzini .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head), 40baacf047SPaolo Bonzini .desc = { 41baacf047SPaolo Bonzini { 42baacf047SPaolo Bonzini .name = "path", 43baacf047SPaolo Bonzini .type = QEMU_OPT_STRING, 44baacf047SPaolo Bonzini },{ 45baacf047SPaolo Bonzini .name = "host", 46baacf047SPaolo Bonzini .type = QEMU_OPT_STRING, 47baacf047SPaolo Bonzini },{ 48baacf047SPaolo Bonzini .name = "port", 49baacf047SPaolo Bonzini .type = QEMU_OPT_STRING, 50baacf047SPaolo Bonzini },{ 51baacf047SPaolo Bonzini .name = "to", 52baacf047SPaolo Bonzini .type = QEMU_OPT_NUMBER, 53baacf047SPaolo Bonzini },{ 54baacf047SPaolo Bonzini .name = "ipv4", 55baacf047SPaolo Bonzini .type = QEMU_OPT_BOOL, 56baacf047SPaolo Bonzini },{ 57baacf047SPaolo Bonzini .name = "ipv6", 58baacf047SPaolo Bonzini .type = QEMU_OPT_BOOL, 59baacf047SPaolo Bonzini }, 60baacf047SPaolo Bonzini { /* end if list */ } 61baacf047SPaolo Bonzini }, 62baacf047SPaolo Bonzini }; 63baacf047SPaolo Bonzini 64baacf047SPaolo Bonzini static int inet_getport(struct addrinfo *e) 65baacf047SPaolo Bonzini { 66baacf047SPaolo Bonzini struct sockaddr_in *i4; 67baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 68baacf047SPaolo Bonzini 69baacf047SPaolo Bonzini switch (e->ai_family) { 70baacf047SPaolo Bonzini case PF_INET6: 71baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 72baacf047SPaolo Bonzini return ntohs(i6->sin6_port); 73baacf047SPaolo Bonzini case PF_INET: 74baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 75baacf047SPaolo Bonzini return ntohs(i4->sin_port); 76baacf047SPaolo Bonzini default: 77baacf047SPaolo Bonzini return 0; 78baacf047SPaolo Bonzini } 79baacf047SPaolo Bonzini } 80baacf047SPaolo Bonzini 81baacf047SPaolo Bonzini static void inet_setport(struct addrinfo *e, int port) 82baacf047SPaolo Bonzini { 83baacf047SPaolo Bonzini struct sockaddr_in *i4; 84baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 85baacf047SPaolo Bonzini 86baacf047SPaolo Bonzini switch (e->ai_family) { 87baacf047SPaolo Bonzini case PF_INET6: 88baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 89baacf047SPaolo Bonzini i6->sin6_port = htons(port); 90baacf047SPaolo Bonzini break; 91baacf047SPaolo Bonzini case PF_INET: 92baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 93baacf047SPaolo Bonzini i4->sin_port = htons(port); 94baacf047SPaolo Bonzini break; 95baacf047SPaolo Bonzini } 96baacf047SPaolo Bonzini } 97baacf047SPaolo Bonzini 98baacf047SPaolo Bonzini const char *inet_strfamily(int family) 99baacf047SPaolo Bonzini { 100baacf047SPaolo Bonzini switch (family) { 101baacf047SPaolo Bonzini case PF_INET6: return "ipv6"; 102baacf047SPaolo Bonzini case PF_INET: return "ipv4"; 103baacf047SPaolo Bonzini case PF_UNIX: return "unix"; 104baacf047SPaolo Bonzini } 105baacf047SPaolo Bonzini return "unknown"; 106baacf047SPaolo Bonzini } 107baacf047SPaolo Bonzini 108baacf047SPaolo Bonzini int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp) 109baacf047SPaolo Bonzini { 110baacf047SPaolo Bonzini struct addrinfo ai,*res,*e; 111baacf047SPaolo Bonzini const char *addr; 112baacf047SPaolo Bonzini char port[33]; 113baacf047SPaolo Bonzini char uaddr[INET6_ADDRSTRLEN+1]; 114baacf047SPaolo Bonzini char uport[33]; 115baacf047SPaolo Bonzini int slisten, rc, to, port_min, port_max, p; 116baacf047SPaolo Bonzini 117baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 118baacf047SPaolo Bonzini ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; 119baacf047SPaolo Bonzini ai.ai_family = PF_UNSPEC; 120baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 121baacf047SPaolo Bonzini 122baacf047SPaolo Bonzini if ((qemu_opt_get(opts, "host") == NULL) || 123baacf047SPaolo Bonzini (qemu_opt_get(opts, "port") == NULL)) { 124baacf047SPaolo Bonzini error_setg(errp, "host and/or port not specified"); 125baacf047SPaolo Bonzini return -1; 126baacf047SPaolo Bonzini } 127baacf047SPaolo Bonzini pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port")); 128baacf047SPaolo Bonzini addr = qemu_opt_get(opts, "host"); 129baacf047SPaolo Bonzini 130baacf047SPaolo Bonzini to = qemu_opt_get_number(opts, "to", 0); 131baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv4", 0)) 132baacf047SPaolo Bonzini ai.ai_family = PF_INET; 133baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv6", 0)) 134baacf047SPaolo Bonzini ai.ai_family = PF_INET6; 135baacf047SPaolo Bonzini 136baacf047SPaolo Bonzini /* lookup */ 137baacf047SPaolo Bonzini if (port_offset) 138baacf047SPaolo Bonzini snprintf(port, sizeof(port), "%d", atoi(port) + port_offset); 139baacf047SPaolo Bonzini rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res); 140baacf047SPaolo Bonzini if (rc != 0) { 141baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 142baacf047SPaolo Bonzini gai_strerror(rc)); 143baacf047SPaolo Bonzini return -1; 144baacf047SPaolo Bonzini } 145baacf047SPaolo Bonzini 146baacf047SPaolo Bonzini /* create socket + bind */ 147baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 148baacf047SPaolo Bonzini getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, 149baacf047SPaolo Bonzini uaddr,INET6_ADDRSTRLEN,uport,32, 150baacf047SPaolo Bonzini NI_NUMERICHOST | NI_NUMERICSERV); 151baacf047SPaolo Bonzini slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); 152baacf047SPaolo Bonzini if (slisten < 0) { 153baacf047SPaolo Bonzini if (!e->ai_next) { 154baacf047SPaolo Bonzini error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); 155baacf047SPaolo Bonzini } 156baacf047SPaolo Bonzini continue; 157baacf047SPaolo Bonzini } 158baacf047SPaolo Bonzini 159baacf047SPaolo Bonzini setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); 160baacf047SPaolo Bonzini #ifdef IPV6_V6ONLY 161baacf047SPaolo Bonzini if (e->ai_family == PF_INET6) { 162baacf047SPaolo Bonzini /* listen on both ipv4 and ipv6 */ 163baacf047SPaolo Bonzini setsockopt(slisten,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&off, 164baacf047SPaolo Bonzini sizeof(off)); 165baacf047SPaolo Bonzini } 166baacf047SPaolo Bonzini #endif 167baacf047SPaolo Bonzini 168baacf047SPaolo Bonzini port_min = inet_getport(e); 169baacf047SPaolo Bonzini port_max = to ? to + port_offset : port_min; 170baacf047SPaolo Bonzini for (p = port_min; p <= port_max; p++) { 171baacf047SPaolo Bonzini inet_setport(e, p); 172baacf047SPaolo Bonzini if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) { 173baacf047SPaolo Bonzini goto listen; 174baacf047SPaolo Bonzini } 175baacf047SPaolo Bonzini if (p == port_max) { 176baacf047SPaolo Bonzini if (!e->ai_next) { 177baacf047SPaolo Bonzini error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); 178baacf047SPaolo Bonzini } 179baacf047SPaolo Bonzini } 180baacf047SPaolo Bonzini } 181baacf047SPaolo Bonzini closesocket(slisten); 182baacf047SPaolo Bonzini } 183baacf047SPaolo Bonzini freeaddrinfo(res); 184baacf047SPaolo Bonzini return -1; 185baacf047SPaolo Bonzini 186baacf047SPaolo Bonzini listen: 187baacf047SPaolo Bonzini if (listen(slisten,1) != 0) { 188baacf047SPaolo Bonzini error_set_errno(errp, errno, QERR_SOCKET_LISTEN_FAILED); 189baacf047SPaolo Bonzini closesocket(slisten); 190baacf047SPaolo Bonzini freeaddrinfo(res); 191baacf047SPaolo Bonzini return -1; 192baacf047SPaolo Bonzini } 193baacf047SPaolo Bonzini snprintf(uport, sizeof(uport), "%d", inet_getport(e) - port_offset); 194baacf047SPaolo Bonzini qemu_opt_set(opts, "host", uaddr); 195baacf047SPaolo Bonzini qemu_opt_set(opts, "port", uport); 196baacf047SPaolo Bonzini qemu_opt_set(opts, "ipv6", (e->ai_family == PF_INET6) ? "on" : "off"); 197baacf047SPaolo Bonzini qemu_opt_set(opts, "ipv4", (e->ai_family != PF_INET6) ? "on" : "off"); 198baacf047SPaolo Bonzini freeaddrinfo(res); 199baacf047SPaolo Bonzini return slisten; 200baacf047SPaolo Bonzini } 201baacf047SPaolo Bonzini 202baacf047SPaolo Bonzini #ifdef _WIN32 203baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 204baacf047SPaolo Bonzini ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY) 205baacf047SPaolo Bonzini #else 206baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 207baacf047SPaolo Bonzini ((rc) == -EINPROGRESS) 208baacf047SPaolo Bonzini #endif 209baacf047SPaolo Bonzini 210baacf047SPaolo Bonzini /* Struct to store connect state for non blocking connect */ 211baacf047SPaolo Bonzini typedef struct ConnectState { 212baacf047SPaolo Bonzini int fd; 213baacf047SPaolo Bonzini struct addrinfo *addr_list; 214baacf047SPaolo Bonzini struct addrinfo *current_addr; 215baacf047SPaolo Bonzini NonBlockingConnectHandler *callback; 216baacf047SPaolo Bonzini void *opaque; 217baacf047SPaolo Bonzini } ConnectState; 218baacf047SPaolo Bonzini 219baacf047SPaolo Bonzini static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, 220baacf047SPaolo Bonzini ConnectState *connect_state, Error **errp); 221baacf047SPaolo Bonzini 222baacf047SPaolo Bonzini static void wait_for_connect(void *opaque) 223baacf047SPaolo Bonzini { 224baacf047SPaolo Bonzini ConnectState *s = opaque; 225baacf047SPaolo Bonzini int val = 0, rc = 0; 226baacf047SPaolo Bonzini socklen_t valsize = sizeof(val); 227baacf047SPaolo Bonzini bool in_progress; 228baacf047SPaolo Bonzini 229baacf047SPaolo Bonzini qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); 230baacf047SPaolo Bonzini 231baacf047SPaolo Bonzini do { 232baacf047SPaolo Bonzini rc = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize); 233baacf047SPaolo Bonzini } while (rc == -1 && socket_error() == EINTR); 234baacf047SPaolo Bonzini 235baacf047SPaolo Bonzini /* update rc to contain error */ 236baacf047SPaolo Bonzini if (!rc && val) { 237baacf047SPaolo Bonzini rc = -1; 238baacf047SPaolo Bonzini } 239baacf047SPaolo Bonzini 240baacf047SPaolo Bonzini /* connect error */ 241baacf047SPaolo Bonzini if (rc < 0) { 242baacf047SPaolo Bonzini closesocket(s->fd); 243baacf047SPaolo Bonzini s->fd = rc; 244baacf047SPaolo Bonzini } 245baacf047SPaolo Bonzini 246baacf047SPaolo Bonzini /* try to connect to the next address on the list */ 247baacf047SPaolo Bonzini if (s->current_addr) { 248baacf047SPaolo Bonzini while (s->current_addr->ai_next != NULL && s->fd < 0) { 249baacf047SPaolo Bonzini s->current_addr = s->current_addr->ai_next; 250baacf047SPaolo Bonzini s->fd = inet_connect_addr(s->current_addr, &in_progress, s, NULL); 251baacf047SPaolo Bonzini /* connect in progress */ 252baacf047SPaolo Bonzini if (in_progress) { 253baacf047SPaolo Bonzini return; 254baacf047SPaolo Bonzini } 255baacf047SPaolo Bonzini } 256baacf047SPaolo Bonzini 257baacf047SPaolo Bonzini freeaddrinfo(s->addr_list); 258baacf047SPaolo Bonzini } 259baacf047SPaolo Bonzini 260baacf047SPaolo Bonzini if (s->callback) { 261baacf047SPaolo Bonzini s->callback(s->fd, s->opaque); 262baacf047SPaolo Bonzini } 263baacf047SPaolo Bonzini g_free(s); 264baacf047SPaolo Bonzini } 265baacf047SPaolo Bonzini 266baacf047SPaolo Bonzini static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, 267baacf047SPaolo Bonzini ConnectState *connect_state, Error **errp) 268baacf047SPaolo Bonzini { 269baacf047SPaolo Bonzini int sock, rc; 270baacf047SPaolo Bonzini 271baacf047SPaolo Bonzini *in_progress = false; 272baacf047SPaolo Bonzini 273baacf047SPaolo Bonzini sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); 274baacf047SPaolo Bonzini if (sock < 0) { 275baacf047SPaolo Bonzini error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); 276baacf047SPaolo Bonzini return -1; 277baacf047SPaolo Bonzini } 278baacf047SPaolo Bonzini qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 279baacf047SPaolo Bonzini if (connect_state != NULL) { 280baacf047SPaolo Bonzini socket_set_nonblock(sock); 281baacf047SPaolo Bonzini } 282baacf047SPaolo Bonzini /* connect to peer */ 283baacf047SPaolo Bonzini do { 284baacf047SPaolo Bonzini rc = 0; 285baacf047SPaolo Bonzini if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) { 286baacf047SPaolo Bonzini rc = -socket_error(); 287baacf047SPaolo Bonzini } 288baacf047SPaolo Bonzini } while (rc == -EINTR); 289baacf047SPaolo Bonzini 290baacf047SPaolo Bonzini if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 291baacf047SPaolo Bonzini connect_state->fd = sock; 292baacf047SPaolo Bonzini qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect, 293baacf047SPaolo Bonzini connect_state); 294baacf047SPaolo Bonzini *in_progress = true; 295baacf047SPaolo Bonzini } else if (rc < 0) { 296baacf047SPaolo Bonzini error_set_errno(errp, errno, QERR_SOCKET_CONNECT_FAILED); 297baacf047SPaolo Bonzini closesocket(sock); 298baacf047SPaolo Bonzini return -1; 299baacf047SPaolo Bonzini } 300baacf047SPaolo Bonzini return sock; 301baacf047SPaolo Bonzini } 302baacf047SPaolo Bonzini 303baacf047SPaolo Bonzini static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp) 304baacf047SPaolo Bonzini { 305baacf047SPaolo Bonzini struct addrinfo ai, *res; 306baacf047SPaolo Bonzini int rc; 307baacf047SPaolo Bonzini const char *addr; 308baacf047SPaolo Bonzini const char *port; 309baacf047SPaolo Bonzini 310baacf047SPaolo Bonzini memset(&ai, 0, sizeof(ai)); 311baacf047SPaolo Bonzini 312baacf047SPaolo Bonzini ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; 313baacf047SPaolo Bonzini ai.ai_family = PF_UNSPEC; 314baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 315baacf047SPaolo Bonzini 316baacf047SPaolo Bonzini addr = qemu_opt_get(opts, "host"); 317baacf047SPaolo Bonzini port = qemu_opt_get(opts, "port"); 318baacf047SPaolo Bonzini if (addr == NULL || port == NULL) { 319baacf047SPaolo Bonzini error_setg(errp, "host and/or port not specified"); 320baacf047SPaolo Bonzini return NULL; 321baacf047SPaolo Bonzini } 322baacf047SPaolo Bonzini 323baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv4", 0)) { 324baacf047SPaolo Bonzini ai.ai_family = PF_INET; 325baacf047SPaolo Bonzini } 326baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv6", 0)) { 327baacf047SPaolo Bonzini ai.ai_family = PF_INET6; 328baacf047SPaolo Bonzini } 329baacf047SPaolo Bonzini 330baacf047SPaolo Bonzini /* lookup */ 331baacf047SPaolo Bonzini rc = getaddrinfo(addr, port, &ai, &res); 332baacf047SPaolo Bonzini if (rc != 0) { 333baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 334baacf047SPaolo Bonzini gai_strerror(rc)); 335baacf047SPaolo Bonzini return NULL; 336baacf047SPaolo Bonzini } 337baacf047SPaolo Bonzini return res; 338baacf047SPaolo Bonzini } 339baacf047SPaolo Bonzini 340baacf047SPaolo Bonzini /** 341baacf047SPaolo Bonzini * Create a socket and connect it to an address. 342baacf047SPaolo Bonzini * 343baacf047SPaolo Bonzini * @opts: QEMU options, recognized parameters strings "host" and "port", 344baacf047SPaolo Bonzini * bools "ipv4" and "ipv6". 345baacf047SPaolo Bonzini * @errp: set on error 346baacf047SPaolo Bonzini * @callback: callback function for non-blocking connect 347baacf047SPaolo Bonzini * @opaque: opaque for callback function 348baacf047SPaolo Bonzini * 349baacf047SPaolo Bonzini * Returns: -1 on error, file descriptor on success. 350baacf047SPaolo Bonzini * 351baacf047SPaolo Bonzini * If @callback is non-null, the connect is non-blocking. If this 352baacf047SPaolo Bonzini * function succeeds, callback will be called when the connection 353baacf047SPaolo Bonzini * completes, with the file descriptor on success, or -1 on error. 354baacf047SPaolo Bonzini */ 355baacf047SPaolo Bonzini int inet_connect_opts(QemuOpts *opts, Error **errp, 356baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 357baacf047SPaolo Bonzini { 358baacf047SPaolo Bonzini struct addrinfo *res, *e; 359baacf047SPaolo Bonzini int sock = -1; 360baacf047SPaolo Bonzini bool in_progress; 361baacf047SPaolo Bonzini ConnectState *connect_state = NULL; 362baacf047SPaolo Bonzini 363baacf047SPaolo Bonzini res = inet_parse_connect_opts(opts, errp); 364baacf047SPaolo Bonzini if (!res) { 365baacf047SPaolo Bonzini return -1; 366baacf047SPaolo Bonzini } 367baacf047SPaolo Bonzini 368baacf047SPaolo Bonzini if (callback != NULL) { 369baacf047SPaolo Bonzini connect_state = g_malloc0(sizeof(*connect_state)); 370baacf047SPaolo Bonzini connect_state->addr_list = res; 371baacf047SPaolo Bonzini connect_state->callback = callback; 372baacf047SPaolo Bonzini connect_state->opaque = opaque; 373baacf047SPaolo Bonzini } 374baacf047SPaolo Bonzini 375baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 376baacf047SPaolo Bonzini if (connect_state != NULL) { 377baacf047SPaolo Bonzini connect_state->current_addr = e; 378baacf047SPaolo Bonzini } 379baacf047SPaolo Bonzini sock = inet_connect_addr(e, &in_progress, connect_state, errp); 380baacf047SPaolo Bonzini if (in_progress) { 381baacf047SPaolo Bonzini return sock; 382baacf047SPaolo Bonzini } else if (sock >= 0) { 383baacf047SPaolo Bonzini /* non blocking socket immediate success, call callback */ 384baacf047SPaolo Bonzini if (callback != NULL) { 385baacf047SPaolo Bonzini callback(sock, opaque); 386baacf047SPaolo Bonzini } 387baacf047SPaolo Bonzini break; 388baacf047SPaolo Bonzini } 389baacf047SPaolo Bonzini } 390baacf047SPaolo Bonzini g_free(connect_state); 391baacf047SPaolo Bonzini freeaddrinfo(res); 392baacf047SPaolo Bonzini return sock; 393baacf047SPaolo Bonzini } 394baacf047SPaolo Bonzini 395baacf047SPaolo Bonzini int inet_dgram_opts(QemuOpts *opts, Error **errp) 396baacf047SPaolo Bonzini { 397baacf047SPaolo Bonzini struct addrinfo ai, *peer = NULL, *local = NULL; 398baacf047SPaolo Bonzini const char *addr; 399baacf047SPaolo Bonzini const char *port; 400baacf047SPaolo Bonzini int sock = -1, rc; 401baacf047SPaolo Bonzini 402baacf047SPaolo Bonzini /* lookup peer addr */ 403baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 404baacf047SPaolo Bonzini ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; 405baacf047SPaolo Bonzini ai.ai_family = PF_UNSPEC; 406baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 407baacf047SPaolo Bonzini 408baacf047SPaolo Bonzini addr = qemu_opt_get(opts, "host"); 409baacf047SPaolo Bonzini port = qemu_opt_get(opts, "port"); 410baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 411baacf047SPaolo Bonzini addr = "localhost"; 412baacf047SPaolo Bonzini } 413baacf047SPaolo Bonzini if (port == NULL || strlen(port) == 0) { 414baacf047SPaolo Bonzini error_setg(errp, "remote port not specified"); 415baacf047SPaolo Bonzini return -1; 416baacf047SPaolo Bonzini } 417baacf047SPaolo Bonzini 418baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv4", 0)) 419baacf047SPaolo Bonzini ai.ai_family = PF_INET; 420baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv6", 0)) 421baacf047SPaolo Bonzini ai.ai_family = PF_INET6; 422baacf047SPaolo Bonzini 423baacf047SPaolo Bonzini if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) { 424baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 425baacf047SPaolo Bonzini gai_strerror(rc)); 426baacf047SPaolo Bonzini return -1; 427baacf047SPaolo Bonzini } 428baacf047SPaolo Bonzini 429baacf047SPaolo Bonzini /* lookup local addr */ 430baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 431baacf047SPaolo Bonzini ai.ai_flags = AI_PASSIVE; 432baacf047SPaolo Bonzini ai.ai_family = peer->ai_family; 433baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 434baacf047SPaolo Bonzini 435baacf047SPaolo Bonzini addr = qemu_opt_get(opts, "localaddr"); 436baacf047SPaolo Bonzini port = qemu_opt_get(opts, "localport"); 437baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 438baacf047SPaolo Bonzini addr = NULL; 439baacf047SPaolo Bonzini } 440baacf047SPaolo Bonzini if (!port || strlen(port) == 0) 441baacf047SPaolo Bonzini port = "0"; 442baacf047SPaolo Bonzini 443baacf047SPaolo Bonzini if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) { 444baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 445baacf047SPaolo Bonzini gai_strerror(rc)); 446baacf047SPaolo Bonzini goto err; 447baacf047SPaolo Bonzini } 448baacf047SPaolo Bonzini 449baacf047SPaolo Bonzini /* create socket */ 450baacf047SPaolo Bonzini sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); 451baacf047SPaolo Bonzini if (sock < 0) { 452baacf047SPaolo Bonzini error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); 453baacf047SPaolo Bonzini goto err; 454baacf047SPaolo Bonzini } 455baacf047SPaolo Bonzini setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); 456baacf047SPaolo Bonzini 457baacf047SPaolo Bonzini /* bind socket */ 458baacf047SPaolo Bonzini if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { 459baacf047SPaolo Bonzini error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); 460baacf047SPaolo Bonzini goto err; 461baacf047SPaolo Bonzini } 462baacf047SPaolo Bonzini 463baacf047SPaolo Bonzini /* connect to peer */ 464baacf047SPaolo Bonzini if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { 465baacf047SPaolo Bonzini error_set_errno(errp, errno, QERR_SOCKET_CONNECT_FAILED); 466baacf047SPaolo Bonzini goto err; 467baacf047SPaolo Bonzini } 468baacf047SPaolo Bonzini 469baacf047SPaolo Bonzini freeaddrinfo(local); 470baacf047SPaolo Bonzini freeaddrinfo(peer); 471baacf047SPaolo Bonzini return sock; 472baacf047SPaolo Bonzini 473baacf047SPaolo Bonzini err: 474baacf047SPaolo Bonzini if (-1 != sock) 475baacf047SPaolo Bonzini closesocket(sock); 476baacf047SPaolo Bonzini if (local) 477baacf047SPaolo Bonzini freeaddrinfo(local); 478baacf047SPaolo Bonzini if (peer) 479baacf047SPaolo Bonzini freeaddrinfo(peer); 480baacf047SPaolo Bonzini return -1; 481baacf047SPaolo Bonzini } 482baacf047SPaolo Bonzini 483baacf047SPaolo Bonzini /* compatibility wrapper */ 484baacf047SPaolo Bonzini static InetSocketAddress *inet_parse(const char *str, Error **errp) 485baacf047SPaolo Bonzini { 486baacf047SPaolo Bonzini InetSocketAddress *addr; 487baacf047SPaolo Bonzini const char *optstr, *h; 488baacf047SPaolo Bonzini char host[64]; 489baacf047SPaolo Bonzini char port[33]; 490baacf047SPaolo Bonzini int to; 491baacf047SPaolo Bonzini int pos; 492baacf047SPaolo Bonzini 493baacf047SPaolo Bonzini addr = g_new0(InetSocketAddress, 1); 494baacf047SPaolo Bonzini 495baacf047SPaolo Bonzini /* parse address */ 496baacf047SPaolo Bonzini if (str[0] == ':') { 497baacf047SPaolo Bonzini /* no host given */ 498baacf047SPaolo Bonzini host[0] = '\0'; 499baacf047SPaolo Bonzini if (1 != sscanf(str, ":%32[^,]%n", port, &pos)) { 500baacf047SPaolo Bonzini error_setg(errp, "error parsing port in address '%s'", str); 501baacf047SPaolo Bonzini goto fail; 502baacf047SPaolo Bonzini } 503baacf047SPaolo Bonzini } else if (str[0] == '[') { 504baacf047SPaolo Bonzini /* IPv6 addr */ 505baacf047SPaolo Bonzini if (2 != sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos)) { 506baacf047SPaolo Bonzini error_setg(errp, "error parsing IPv6 address '%s'", str); 507baacf047SPaolo Bonzini goto fail; 508baacf047SPaolo Bonzini } 509baacf047SPaolo Bonzini addr->ipv6 = addr->has_ipv6 = true; 510baacf047SPaolo Bonzini } else if (qemu_isdigit(str[0])) { 511baacf047SPaolo Bonzini /* IPv4 addr */ 512baacf047SPaolo Bonzini if (2 != sscanf(str, "%64[0-9.]:%32[^,]%n", host, port, &pos)) { 513baacf047SPaolo Bonzini error_setg(errp, "error parsing IPv4 address '%s'", str); 514baacf047SPaolo Bonzini goto fail; 515baacf047SPaolo Bonzini } 516baacf047SPaolo Bonzini addr->ipv4 = addr->has_ipv4 = true; 517baacf047SPaolo Bonzini } else { 518baacf047SPaolo Bonzini /* hostname */ 519baacf047SPaolo Bonzini if (2 != sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos)) { 520baacf047SPaolo Bonzini error_setg(errp, "error parsing address '%s'", str); 521baacf047SPaolo Bonzini goto fail; 522baacf047SPaolo Bonzini } 523baacf047SPaolo Bonzini } 524baacf047SPaolo Bonzini 525baacf047SPaolo Bonzini addr->host = g_strdup(host); 526baacf047SPaolo Bonzini addr->port = g_strdup(port); 527baacf047SPaolo Bonzini 528baacf047SPaolo Bonzini /* parse options */ 529baacf047SPaolo Bonzini optstr = str + pos; 530baacf047SPaolo Bonzini h = strstr(optstr, ",to="); 531baacf047SPaolo Bonzini if (h) { 532baacf047SPaolo Bonzini h += 4; 533baacf047SPaolo Bonzini if (sscanf(h, "%d%n", &to, &pos) != 1 || 534baacf047SPaolo Bonzini (h[pos] != '\0' && h[pos] != ',')) { 535baacf047SPaolo Bonzini error_setg(errp, "error parsing to= argument"); 536baacf047SPaolo Bonzini goto fail; 537baacf047SPaolo Bonzini } 538baacf047SPaolo Bonzini addr->has_to = true; 539baacf047SPaolo Bonzini addr->to = to; 540baacf047SPaolo Bonzini } 541baacf047SPaolo Bonzini if (strstr(optstr, ",ipv4")) { 542baacf047SPaolo Bonzini addr->ipv4 = addr->has_ipv4 = true; 543baacf047SPaolo Bonzini } 544baacf047SPaolo Bonzini if (strstr(optstr, ",ipv6")) { 545baacf047SPaolo Bonzini addr->ipv6 = addr->has_ipv6 = true; 546baacf047SPaolo Bonzini } 547baacf047SPaolo Bonzini return addr; 548baacf047SPaolo Bonzini 549baacf047SPaolo Bonzini fail: 550baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 551baacf047SPaolo Bonzini return NULL; 552baacf047SPaolo Bonzini } 553baacf047SPaolo Bonzini 554baacf047SPaolo Bonzini static void inet_addr_to_opts(QemuOpts *opts, InetSocketAddress *addr) 555baacf047SPaolo Bonzini { 556baacf047SPaolo Bonzini bool ipv4 = addr->ipv4 || !addr->has_ipv4; 557baacf047SPaolo Bonzini bool ipv6 = addr->ipv6 || !addr->has_ipv6; 558baacf047SPaolo Bonzini 559baacf047SPaolo Bonzini if (!ipv4 || !ipv6) { 560baacf047SPaolo Bonzini qemu_opt_set_bool(opts, "ipv4", ipv4); 561baacf047SPaolo Bonzini qemu_opt_set_bool(opts, "ipv6", ipv6); 562baacf047SPaolo Bonzini } 563baacf047SPaolo Bonzini if (addr->has_to) { 564baacf047SPaolo Bonzini char to[20]; 565baacf047SPaolo Bonzini snprintf(to, sizeof(to), "%d", addr->to); 566baacf047SPaolo Bonzini qemu_opt_set(opts, "to", to); 567baacf047SPaolo Bonzini } 568baacf047SPaolo Bonzini qemu_opt_set(opts, "host", addr->host); 569baacf047SPaolo Bonzini qemu_opt_set(opts, "port", addr->port); 570baacf047SPaolo Bonzini } 571baacf047SPaolo Bonzini 572baacf047SPaolo Bonzini int inet_listen(const char *str, char *ostr, int olen, 573baacf047SPaolo Bonzini int socktype, int port_offset, Error **errp) 574baacf047SPaolo Bonzini { 575baacf047SPaolo Bonzini QemuOpts *opts; 576baacf047SPaolo Bonzini char *optstr; 577baacf047SPaolo Bonzini int sock = -1; 578baacf047SPaolo Bonzini InetSocketAddress *addr; 579baacf047SPaolo Bonzini 580baacf047SPaolo Bonzini addr = inet_parse(str, errp); 581baacf047SPaolo Bonzini if (addr != NULL) { 582baacf047SPaolo Bonzini opts = qemu_opts_create_nofail(&dummy_opts); 583baacf047SPaolo Bonzini inet_addr_to_opts(opts, addr); 584baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 585baacf047SPaolo Bonzini sock = inet_listen_opts(opts, port_offset, errp); 586baacf047SPaolo Bonzini if (sock != -1 && ostr) { 587baacf047SPaolo Bonzini optstr = strchr(str, ','); 588baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv6", 0)) { 589baacf047SPaolo Bonzini snprintf(ostr, olen, "[%s]:%s%s", 590baacf047SPaolo Bonzini qemu_opt_get(opts, "host"), 591baacf047SPaolo Bonzini qemu_opt_get(opts, "port"), 592baacf047SPaolo Bonzini optstr ? optstr : ""); 593baacf047SPaolo Bonzini } else { 594baacf047SPaolo Bonzini snprintf(ostr, olen, "%s:%s%s", 595baacf047SPaolo Bonzini qemu_opt_get(opts, "host"), 596baacf047SPaolo Bonzini qemu_opt_get(opts, "port"), 597baacf047SPaolo Bonzini optstr ? optstr : ""); 598baacf047SPaolo Bonzini } 599baacf047SPaolo Bonzini } 600baacf047SPaolo Bonzini qemu_opts_del(opts); 601baacf047SPaolo Bonzini } 602baacf047SPaolo Bonzini return sock; 603baacf047SPaolo Bonzini } 604baacf047SPaolo Bonzini 605baacf047SPaolo Bonzini /** 606baacf047SPaolo Bonzini * Create a blocking socket and connect it to an address. 607baacf047SPaolo Bonzini * 608baacf047SPaolo Bonzini * @str: address string 609baacf047SPaolo Bonzini * @errp: set in case of an error 610baacf047SPaolo Bonzini * 611baacf047SPaolo Bonzini * Returns -1 in case of error, file descriptor on success 612baacf047SPaolo Bonzini **/ 613baacf047SPaolo Bonzini int inet_connect(const char *str, Error **errp) 614baacf047SPaolo Bonzini { 615baacf047SPaolo Bonzini QemuOpts *opts; 616baacf047SPaolo Bonzini int sock = -1; 617baacf047SPaolo Bonzini InetSocketAddress *addr; 618baacf047SPaolo Bonzini 619baacf047SPaolo Bonzini addr = inet_parse(str, errp); 620baacf047SPaolo Bonzini if (addr != NULL) { 621baacf047SPaolo Bonzini opts = qemu_opts_create_nofail(&dummy_opts); 622baacf047SPaolo Bonzini inet_addr_to_opts(opts, addr); 623baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 624baacf047SPaolo Bonzini sock = inet_connect_opts(opts, errp, NULL, NULL); 625baacf047SPaolo Bonzini qemu_opts_del(opts); 626baacf047SPaolo Bonzini } 627baacf047SPaolo Bonzini return sock; 628baacf047SPaolo Bonzini } 629baacf047SPaolo Bonzini 630baacf047SPaolo Bonzini /** 631baacf047SPaolo Bonzini * Create a non-blocking socket and connect it to an address. 632baacf047SPaolo Bonzini * Calls the callback function with fd in case of success or -1 in case of 633baacf047SPaolo Bonzini * error. 634baacf047SPaolo Bonzini * 635baacf047SPaolo Bonzini * @str: address string 636baacf047SPaolo Bonzini * @callback: callback function that is called when connect completes, 637baacf047SPaolo Bonzini * cannot be NULL. 638baacf047SPaolo Bonzini * @opaque: opaque for callback function 639baacf047SPaolo Bonzini * @errp: set in case of an error 640baacf047SPaolo Bonzini * 641baacf047SPaolo Bonzini * Returns: -1 on immediate error, file descriptor on success. 642baacf047SPaolo Bonzini **/ 643baacf047SPaolo Bonzini int inet_nonblocking_connect(const char *str, 644baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, 645baacf047SPaolo Bonzini void *opaque, Error **errp) 646baacf047SPaolo Bonzini { 647baacf047SPaolo Bonzini QemuOpts *opts; 648baacf047SPaolo Bonzini int sock = -1; 649baacf047SPaolo Bonzini InetSocketAddress *addr; 650baacf047SPaolo Bonzini 651baacf047SPaolo Bonzini g_assert(callback != NULL); 652baacf047SPaolo Bonzini 653baacf047SPaolo Bonzini addr = inet_parse(str, errp); 654baacf047SPaolo Bonzini if (addr != NULL) { 655baacf047SPaolo Bonzini opts = qemu_opts_create_nofail(&dummy_opts); 656baacf047SPaolo Bonzini inet_addr_to_opts(opts, addr); 657baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 658baacf047SPaolo Bonzini sock = inet_connect_opts(opts, errp, callback, opaque); 659baacf047SPaolo Bonzini qemu_opts_del(opts); 660baacf047SPaolo Bonzini } 661baacf047SPaolo Bonzini return sock; 662baacf047SPaolo Bonzini } 663baacf047SPaolo Bonzini 664baacf047SPaolo Bonzini #ifndef _WIN32 665baacf047SPaolo Bonzini 666baacf047SPaolo Bonzini int unix_listen_opts(QemuOpts *opts, Error **errp) 667baacf047SPaolo Bonzini { 668baacf047SPaolo Bonzini struct sockaddr_un un; 669baacf047SPaolo Bonzini const char *path = qemu_opt_get(opts, "path"); 670baacf047SPaolo Bonzini int sock, fd; 671baacf047SPaolo Bonzini 672baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 673baacf047SPaolo Bonzini if (sock < 0) { 674baacf047SPaolo Bonzini error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); 675baacf047SPaolo Bonzini return -1; 676baacf047SPaolo Bonzini } 677baacf047SPaolo Bonzini 678baacf047SPaolo Bonzini memset(&un, 0, sizeof(un)); 679baacf047SPaolo Bonzini un.sun_family = AF_UNIX; 680baacf047SPaolo Bonzini if (path && strlen(path)) { 681baacf047SPaolo Bonzini snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); 682baacf047SPaolo Bonzini } else { 683baacf047SPaolo Bonzini char *tmpdir = getenv("TMPDIR"); 684baacf047SPaolo Bonzini snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX", 685baacf047SPaolo Bonzini tmpdir ? tmpdir : "/tmp"); 686baacf047SPaolo Bonzini /* 687baacf047SPaolo Bonzini * This dummy fd usage silences the mktemp() unsecure warning. 688baacf047SPaolo Bonzini * Using mkstemp() doesn't make things more secure here 689baacf047SPaolo Bonzini * though. bind() complains about existing files, so we have 690baacf047SPaolo Bonzini * to unlink first and thus re-open the race window. The 691baacf047SPaolo Bonzini * worst case possible is bind() failing, i.e. a DoS attack. 692baacf047SPaolo Bonzini */ 693baacf047SPaolo Bonzini fd = mkstemp(un.sun_path); close(fd); 694baacf047SPaolo Bonzini qemu_opt_set(opts, "path", un.sun_path); 695baacf047SPaolo Bonzini } 696baacf047SPaolo Bonzini 697baacf047SPaolo Bonzini unlink(un.sun_path); 698baacf047SPaolo Bonzini if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { 699baacf047SPaolo Bonzini error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); 700baacf047SPaolo Bonzini goto err; 701baacf047SPaolo Bonzini } 702baacf047SPaolo Bonzini if (listen(sock, 1) < 0) { 703baacf047SPaolo Bonzini error_set_errno(errp, errno, QERR_SOCKET_LISTEN_FAILED); 704baacf047SPaolo Bonzini goto err; 705baacf047SPaolo Bonzini } 706baacf047SPaolo Bonzini 707baacf047SPaolo Bonzini return sock; 708baacf047SPaolo Bonzini 709baacf047SPaolo Bonzini err: 710baacf047SPaolo Bonzini closesocket(sock); 711baacf047SPaolo Bonzini return -1; 712baacf047SPaolo Bonzini } 713baacf047SPaolo Bonzini 714baacf047SPaolo Bonzini int unix_connect_opts(QemuOpts *opts, Error **errp, 715baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 716baacf047SPaolo Bonzini { 717baacf047SPaolo Bonzini struct sockaddr_un un; 718baacf047SPaolo Bonzini const char *path = qemu_opt_get(opts, "path"); 719baacf047SPaolo Bonzini ConnectState *connect_state = NULL; 720baacf047SPaolo Bonzini int sock, rc; 721baacf047SPaolo Bonzini 722baacf047SPaolo Bonzini if (NULL == path) { 723*312fd5f2SMarkus Armbruster error_setg(errp, "unix connect: no path specified"); 724baacf047SPaolo Bonzini return -1; 725baacf047SPaolo Bonzini } 726baacf047SPaolo Bonzini 727baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 728baacf047SPaolo Bonzini if (sock < 0) { 729baacf047SPaolo Bonzini error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); 730baacf047SPaolo Bonzini return -1; 731baacf047SPaolo Bonzini } 732baacf047SPaolo Bonzini if (callback != NULL) { 733baacf047SPaolo Bonzini connect_state = g_malloc0(sizeof(*connect_state)); 734baacf047SPaolo Bonzini connect_state->callback = callback; 735baacf047SPaolo Bonzini connect_state->opaque = opaque; 736baacf047SPaolo Bonzini socket_set_nonblock(sock); 737baacf047SPaolo Bonzini } 738baacf047SPaolo Bonzini 739baacf047SPaolo Bonzini memset(&un, 0, sizeof(un)); 740baacf047SPaolo Bonzini un.sun_family = AF_UNIX; 741baacf047SPaolo Bonzini snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); 742baacf047SPaolo Bonzini 743baacf047SPaolo Bonzini /* connect to peer */ 744baacf047SPaolo Bonzini do { 745baacf047SPaolo Bonzini rc = 0; 746baacf047SPaolo Bonzini if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { 747baacf047SPaolo Bonzini rc = -socket_error(); 748baacf047SPaolo Bonzini } 749baacf047SPaolo Bonzini } while (rc == -EINTR); 750baacf047SPaolo Bonzini 751baacf047SPaolo Bonzini if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 752baacf047SPaolo Bonzini connect_state->fd = sock; 753baacf047SPaolo Bonzini qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect, 754baacf047SPaolo Bonzini connect_state); 755baacf047SPaolo Bonzini return sock; 756baacf047SPaolo Bonzini } else if (rc >= 0) { 757baacf047SPaolo Bonzini /* non blocking socket immediate success, call callback */ 758baacf047SPaolo Bonzini if (callback != NULL) { 759baacf047SPaolo Bonzini callback(sock, opaque); 760baacf047SPaolo Bonzini } 761baacf047SPaolo Bonzini } 762baacf047SPaolo Bonzini 763baacf047SPaolo Bonzini if (rc < 0) { 764baacf047SPaolo Bonzini error_set_errno(errp, -rc, QERR_SOCKET_CONNECT_FAILED); 765baacf047SPaolo Bonzini close(sock); 766baacf047SPaolo Bonzini sock = -1; 767baacf047SPaolo Bonzini } 768baacf047SPaolo Bonzini 769baacf047SPaolo Bonzini g_free(connect_state); 770baacf047SPaolo Bonzini return sock; 771baacf047SPaolo Bonzini } 772baacf047SPaolo Bonzini 773baacf047SPaolo Bonzini #else 774baacf047SPaolo Bonzini 775baacf047SPaolo Bonzini int unix_listen_opts(QemuOpts *opts, Error **errp) 776baacf047SPaolo Bonzini { 777baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 778baacf047SPaolo Bonzini errno = ENOTSUP; 779baacf047SPaolo Bonzini return -1; 780baacf047SPaolo Bonzini } 781baacf047SPaolo Bonzini 782baacf047SPaolo Bonzini int unix_connect_opts(QemuOpts *opts, Error **errp, 783baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 784baacf047SPaolo Bonzini { 785baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 786baacf047SPaolo Bonzini errno = ENOTSUP; 787baacf047SPaolo Bonzini return -1; 788baacf047SPaolo Bonzini } 789baacf047SPaolo Bonzini #endif 790baacf047SPaolo Bonzini 791baacf047SPaolo Bonzini /* compatibility wrapper */ 792baacf047SPaolo Bonzini int unix_listen(const char *str, char *ostr, int olen, Error **errp) 793baacf047SPaolo Bonzini { 794baacf047SPaolo Bonzini QemuOpts *opts; 795baacf047SPaolo Bonzini char *path, *optstr; 796baacf047SPaolo Bonzini int sock, len; 797baacf047SPaolo Bonzini 798baacf047SPaolo Bonzini opts = qemu_opts_create_nofail(&dummy_opts); 799baacf047SPaolo Bonzini 800baacf047SPaolo Bonzini optstr = strchr(str, ','); 801baacf047SPaolo Bonzini if (optstr) { 802baacf047SPaolo Bonzini len = optstr - str; 803baacf047SPaolo Bonzini if (len) { 804baacf047SPaolo Bonzini path = g_malloc(len+1); 805baacf047SPaolo Bonzini snprintf(path, len+1, "%.*s", len, str); 806baacf047SPaolo Bonzini qemu_opt_set(opts, "path", path); 807baacf047SPaolo Bonzini g_free(path); 808baacf047SPaolo Bonzini } 809baacf047SPaolo Bonzini } else { 810baacf047SPaolo Bonzini qemu_opt_set(opts, "path", str); 811baacf047SPaolo Bonzini } 812baacf047SPaolo Bonzini 813baacf047SPaolo Bonzini sock = unix_listen_opts(opts, errp); 814baacf047SPaolo Bonzini 815baacf047SPaolo Bonzini if (sock != -1 && ostr) 816baacf047SPaolo Bonzini snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : ""); 817baacf047SPaolo Bonzini qemu_opts_del(opts); 818baacf047SPaolo Bonzini return sock; 819baacf047SPaolo Bonzini } 820baacf047SPaolo Bonzini 821baacf047SPaolo Bonzini int unix_connect(const char *path, Error **errp) 822baacf047SPaolo Bonzini { 823baacf047SPaolo Bonzini QemuOpts *opts; 824baacf047SPaolo Bonzini int sock; 825baacf047SPaolo Bonzini 826baacf047SPaolo Bonzini opts = qemu_opts_create_nofail(&dummy_opts); 827baacf047SPaolo Bonzini qemu_opt_set(opts, "path", path); 828baacf047SPaolo Bonzini sock = unix_connect_opts(opts, errp, NULL, NULL); 829baacf047SPaolo Bonzini qemu_opts_del(opts); 830baacf047SPaolo Bonzini return sock; 831baacf047SPaolo Bonzini } 832baacf047SPaolo Bonzini 833baacf047SPaolo Bonzini 834baacf047SPaolo Bonzini int unix_nonblocking_connect(const char *path, 835baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, 836baacf047SPaolo Bonzini void *opaque, Error **errp) 837baacf047SPaolo Bonzini { 838baacf047SPaolo Bonzini QemuOpts *opts; 839baacf047SPaolo Bonzini int sock = -1; 840baacf047SPaolo Bonzini 841baacf047SPaolo Bonzini g_assert(callback != NULL); 842baacf047SPaolo Bonzini 843baacf047SPaolo Bonzini opts = qemu_opts_create_nofail(&dummy_opts); 844baacf047SPaolo Bonzini qemu_opt_set(opts, "path", path); 845baacf047SPaolo Bonzini sock = unix_connect_opts(opts, errp, callback, opaque); 846baacf047SPaolo Bonzini qemu_opts_del(opts); 847baacf047SPaolo Bonzini return sock; 848baacf047SPaolo Bonzini } 849baacf047SPaolo Bonzini 850baacf047SPaolo Bonzini SocketAddress *socket_parse(const char *str, Error **errp) 851baacf047SPaolo Bonzini { 852baacf047SPaolo Bonzini SocketAddress *addr = NULL; 853baacf047SPaolo Bonzini 854baacf047SPaolo Bonzini addr = g_new(SocketAddress, 1); 855baacf047SPaolo Bonzini if (strstart(str, "unix:", NULL)) { 856baacf047SPaolo Bonzini if (str[5] == '\0') { 857*312fd5f2SMarkus Armbruster error_setg(errp, "invalid Unix socket address"); 858baacf047SPaolo Bonzini goto fail; 859baacf047SPaolo Bonzini } else { 860baacf047SPaolo Bonzini addr->kind = SOCKET_ADDRESS_KIND_UNIX; 861baacf047SPaolo Bonzini addr->q_unix = g_new(UnixSocketAddress, 1); 862baacf047SPaolo Bonzini addr->q_unix->path = g_strdup(str + 5); 863baacf047SPaolo Bonzini } 864baacf047SPaolo Bonzini } else if (strstart(str, "fd:", NULL)) { 865baacf047SPaolo Bonzini if (str[3] == '\0') { 866*312fd5f2SMarkus Armbruster error_setg(errp, "invalid file descriptor address"); 867baacf047SPaolo Bonzini goto fail; 868baacf047SPaolo Bonzini } else { 869baacf047SPaolo Bonzini addr->kind = SOCKET_ADDRESS_KIND_FD; 870baacf047SPaolo Bonzini addr->fd = g_new(String, 1); 871baacf047SPaolo Bonzini addr->fd->str = g_strdup(str + 3); 872baacf047SPaolo Bonzini } 873baacf047SPaolo Bonzini } else { 874baacf047SPaolo Bonzini addr->kind = SOCKET_ADDRESS_KIND_INET; 875baacf047SPaolo Bonzini addr->inet = g_new(InetSocketAddress, 1); 876baacf047SPaolo Bonzini addr->inet = inet_parse(str, errp); 877baacf047SPaolo Bonzini if (addr->inet == NULL) { 878baacf047SPaolo Bonzini goto fail; 879baacf047SPaolo Bonzini } 880baacf047SPaolo Bonzini } 881baacf047SPaolo Bonzini return addr; 882baacf047SPaolo Bonzini 883baacf047SPaolo Bonzini fail: 884baacf047SPaolo Bonzini qapi_free_SocketAddress(addr); 885baacf047SPaolo Bonzini return NULL; 886baacf047SPaolo Bonzini } 887baacf047SPaolo Bonzini 888baacf047SPaolo Bonzini int socket_connect(SocketAddress *addr, Error **errp, 889baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 890baacf047SPaolo Bonzini { 891baacf047SPaolo Bonzini QemuOpts *opts; 892baacf047SPaolo Bonzini int fd; 893baacf047SPaolo Bonzini 894baacf047SPaolo Bonzini opts = qemu_opts_create_nofail(&dummy_opts); 895baacf047SPaolo Bonzini switch (addr->kind) { 896baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_INET: 897baacf047SPaolo Bonzini inet_addr_to_opts(opts, addr->inet); 898baacf047SPaolo Bonzini fd = inet_connect_opts(opts, errp, callback, opaque); 899baacf047SPaolo Bonzini break; 900baacf047SPaolo Bonzini 901baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_UNIX: 902baacf047SPaolo Bonzini qemu_opt_set(opts, "path", addr->q_unix->path); 903baacf047SPaolo Bonzini fd = unix_connect_opts(opts, errp, callback, opaque); 904baacf047SPaolo Bonzini break; 905baacf047SPaolo Bonzini 906baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_FD: 907baacf047SPaolo Bonzini fd = monitor_get_fd(cur_mon, addr->fd->str, errp); 908baacf047SPaolo Bonzini if (callback) { 909baacf047SPaolo Bonzini callback(fd, opaque); 910baacf047SPaolo Bonzini } 911baacf047SPaolo Bonzini break; 912baacf047SPaolo Bonzini 913baacf047SPaolo Bonzini default: 914baacf047SPaolo Bonzini abort(); 915baacf047SPaolo Bonzini } 916baacf047SPaolo Bonzini qemu_opts_del(opts); 917baacf047SPaolo Bonzini return fd; 918baacf047SPaolo Bonzini } 919baacf047SPaolo Bonzini 920baacf047SPaolo Bonzini int socket_listen(SocketAddress *addr, Error **errp) 921baacf047SPaolo Bonzini { 922baacf047SPaolo Bonzini QemuOpts *opts; 923baacf047SPaolo Bonzini int fd; 924baacf047SPaolo Bonzini 925baacf047SPaolo Bonzini opts = qemu_opts_create_nofail(&dummy_opts); 926baacf047SPaolo Bonzini switch (addr->kind) { 927baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_INET: 928baacf047SPaolo Bonzini inet_addr_to_opts(opts, addr->inet); 929baacf047SPaolo Bonzini fd = inet_listen_opts(opts, 0, errp); 930baacf047SPaolo Bonzini break; 931baacf047SPaolo Bonzini 932baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_UNIX: 933baacf047SPaolo Bonzini qemu_opt_set(opts, "path", addr->q_unix->path); 934baacf047SPaolo Bonzini fd = unix_listen_opts(opts, errp); 935baacf047SPaolo Bonzini break; 936baacf047SPaolo Bonzini 937baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_FD: 938baacf047SPaolo Bonzini fd = monitor_get_fd(cur_mon, addr->fd->str, errp); 939baacf047SPaolo Bonzini break; 940baacf047SPaolo Bonzini 941baacf047SPaolo Bonzini default: 942baacf047SPaolo Bonzini abort(); 943baacf047SPaolo Bonzini } 944baacf047SPaolo Bonzini qemu_opts_del(opts); 945baacf047SPaolo Bonzini return fd; 946baacf047SPaolo Bonzini } 947baacf047SPaolo Bonzini 948baacf047SPaolo Bonzini #ifdef _WIN32 949baacf047SPaolo Bonzini static void socket_cleanup(void) 950baacf047SPaolo Bonzini { 951baacf047SPaolo Bonzini WSACleanup(); 952baacf047SPaolo Bonzini } 953baacf047SPaolo Bonzini #endif 954baacf047SPaolo Bonzini 955baacf047SPaolo Bonzini int socket_init(void) 956baacf047SPaolo Bonzini { 957baacf047SPaolo Bonzini #ifdef _WIN32 958baacf047SPaolo Bonzini WSADATA Data; 959baacf047SPaolo Bonzini int ret, err; 960baacf047SPaolo Bonzini 961baacf047SPaolo Bonzini ret = WSAStartup(MAKEWORD(2,2), &Data); 962baacf047SPaolo Bonzini if (ret != 0) { 963baacf047SPaolo Bonzini err = WSAGetLastError(); 964baacf047SPaolo Bonzini fprintf(stderr, "WSAStartup: %d\n", err); 965baacf047SPaolo Bonzini return -1; 966baacf047SPaolo Bonzini } 967baacf047SPaolo Bonzini atexit(socket_cleanup); 968baacf047SPaolo Bonzini #endif 969baacf047SPaolo Bonzini return 0; 970baacf047SPaolo Bonzini } 971