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