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/main-loop.h" 282a8e21c7SDaniel P. Berrange #include "qapi/qmp-input-visitor.h" 292a8e21c7SDaniel P. Berrange #include "qapi/qmp-output-visitor.h" 302a8e21c7SDaniel P. Berrange #include "qapi-visit.h" 31baacf047SPaolo Bonzini 32baacf047SPaolo Bonzini #ifndef AI_ADDRCONFIG 33baacf047SPaolo Bonzini # define AI_ADDRCONFIG 0 34baacf047SPaolo Bonzini #endif 353de3d698SWolfgang Bumiller #ifndef AI_V4MAPPED 363de3d698SWolfgang Bumiller # define AI_V4MAPPED 0 373de3d698SWolfgang Bumiller #endif 38baacf047SPaolo Bonzini 39e62be888SKevin Wolf /* used temporarily until all users are converted to QemuOpts */ 40505c4a1cSDaniel P. Berrange static QemuOptsList socket_optslist = { 41e62be888SKevin Wolf .name = "socket", 42e62be888SKevin Wolf .head = QTAILQ_HEAD_INITIALIZER(socket_optslist.head), 43baacf047SPaolo Bonzini .desc = { 44baacf047SPaolo Bonzini { 45baacf047SPaolo Bonzini .name = "path", 46baacf047SPaolo Bonzini .type = QEMU_OPT_STRING, 47baacf047SPaolo Bonzini },{ 48baacf047SPaolo Bonzini .name = "host", 49baacf047SPaolo Bonzini .type = QEMU_OPT_STRING, 50baacf047SPaolo Bonzini },{ 51baacf047SPaolo Bonzini .name = "port", 52baacf047SPaolo Bonzini .type = QEMU_OPT_STRING, 53baacf047SPaolo Bonzini },{ 54b8981dc9SPeter Krempa .name = "localaddr", 55b8981dc9SPeter Krempa .type = QEMU_OPT_STRING, 56b8981dc9SPeter Krempa },{ 57b8981dc9SPeter Krempa .name = "localport", 58b8981dc9SPeter Krempa .type = QEMU_OPT_STRING, 59b8981dc9SPeter Krempa },{ 60baacf047SPaolo Bonzini .name = "to", 61baacf047SPaolo Bonzini .type = QEMU_OPT_NUMBER, 62baacf047SPaolo Bonzini },{ 63baacf047SPaolo Bonzini .name = "ipv4", 64baacf047SPaolo Bonzini .type = QEMU_OPT_BOOL, 65baacf047SPaolo Bonzini },{ 66baacf047SPaolo Bonzini .name = "ipv6", 67baacf047SPaolo Bonzini .type = QEMU_OPT_BOOL, 68baacf047SPaolo Bonzini }, 69baacf047SPaolo Bonzini { /* end if list */ } 70baacf047SPaolo Bonzini }, 71baacf047SPaolo Bonzini }; 72baacf047SPaolo Bonzini 73baacf047SPaolo Bonzini static int inet_getport(struct addrinfo *e) 74baacf047SPaolo Bonzini { 75baacf047SPaolo Bonzini struct sockaddr_in *i4; 76baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 77baacf047SPaolo Bonzini 78baacf047SPaolo Bonzini switch (e->ai_family) { 79baacf047SPaolo Bonzini case PF_INET6: 80baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 81baacf047SPaolo Bonzini return ntohs(i6->sin6_port); 82baacf047SPaolo Bonzini case PF_INET: 83baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 84baacf047SPaolo Bonzini return ntohs(i4->sin_port); 85baacf047SPaolo Bonzini default: 86baacf047SPaolo Bonzini return 0; 87baacf047SPaolo Bonzini } 88baacf047SPaolo Bonzini } 89baacf047SPaolo Bonzini 90baacf047SPaolo Bonzini static void inet_setport(struct addrinfo *e, int port) 91baacf047SPaolo Bonzini { 92baacf047SPaolo Bonzini struct sockaddr_in *i4; 93baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 94baacf047SPaolo Bonzini 95baacf047SPaolo Bonzini switch (e->ai_family) { 96baacf047SPaolo Bonzini case PF_INET6: 97baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 98baacf047SPaolo Bonzini i6->sin6_port = htons(port); 99baacf047SPaolo Bonzini break; 100baacf047SPaolo Bonzini case PF_INET: 101baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 102baacf047SPaolo Bonzini i4->sin_port = htons(port); 103baacf047SPaolo Bonzini break; 104baacf047SPaolo Bonzini } 105baacf047SPaolo Bonzini } 106baacf047SPaolo Bonzini 107a589569fSWenchao Xia NetworkAddressFamily inet_netfamily(int family) 108a589569fSWenchao Xia { 109a589569fSWenchao Xia switch (family) { 110a589569fSWenchao Xia case PF_INET6: return NETWORK_ADDRESS_FAMILY_IPV6; 111a589569fSWenchao Xia case PF_INET: return NETWORK_ADDRESS_FAMILY_IPV4; 112a589569fSWenchao Xia case PF_UNIX: return NETWORK_ADDRESS_FAMILY_UNIX; 113a589569fSWenchao Xia } 114a589569fSWenchao Xia return NETWORK_ADDRESS_FAMILY_UNKNOWN; 115a589569fSWenchao Xia } 116a589569fSWenchao Xia 117*1856835dSDaniel P. Berrange /* 118*1856835dSDaniel P. Berrange * Matrix we're trying to apply 119*1856835dSDaniel P. Berrange * 120*1856835dSDaniel P. Berrange * ipv4 ipv6 family 121*1856835dSDaniel P. Berrange * - - PF_UNSPEC 122*1856835dSDaniel P. Berrange * - f PF_INET 123*1856835dSDaniel P. Berrange * - t PF_INET6 124*1856835dSDaniel P. Berrange * f - PF_INET6 125*1856835dSDaniel P. Berrange * f f <error> 126*1856835dSDaniel P. Berrange * f t PF_INET6 127*1856835dSDaniel P. Berrange * t - PF_INET 128*1856835dSDaniel P. Berrange * t f PF_INET 129*1856835dSDaniel P. Berrange * t t PF_INET6 130*1856835dSDaniel P. Berrange * 131*1856835dSDaniel P. Berrange * NB, this matrix is only about getting the neccessary results 132*1856835dSDaniel P. Berrange * from getaddrinfo(). Some of the cases require further work 133*1856835dSDaniel P. Berrange * after reading results from getaddrinfo in order to fully 134*1856835dSDaniel P. Berrange * apply the logic the end user wants. eg with the last case 135*1856835dSDaniel P. Berrange * ipv4=t + ipv6=t + PF_INET6, getaddrinfo alone can only 136*1856835dSDaniel P. Berrange * guarantee the ipv6=t part of the request - we need more 137*1856835dSDaniel P. Berrange * checks to provide ipv4=t part of the guarantee. This is 138*1856835dSDaniel P. Berrange * outside scope of this method and not currently handled by 139*1856835dSDaniel P. Berrange * callers at all. 140*1856835dSDaniel P. Berrange */ 141*1856835dSDaniel P. Berrange static int inet_ai_family_from_address(InetSocketAddress *addr, 142*1856835dSDaniel P. Berrange Error **errp) 143*1856835dSDaniel P. Berrange { 144*1856835dSDaniel P. Berrange if (addr->has_ipv6 && addr->has_ipv4 && 145*1856835dSDaniel P. Berrange !addr->ipv6 && !addr->ipv4) { 146*1856835dSDaniel P. Berrange error_setg(errp, "Cannot disable IPv4 and IPv6 at same time"); 147*1856835dSDaniel P. Berrange return PF_UNSPEC; 148*1856835dSDaniel P. Berrange } 149*1856835dSDaniel P. Berrange if ((addr->has_ipv6 && addr->ipv6) || (addr->has_ipv4 && !addr->ipv4)) { 150*1856835dSDaniel P. Berrange return PF_INET6; 151*1856835dSDaniel P. Berrange } 152*1856835dSDaniel P. Berrange if ((addr->has_ipv4 && addr->ipv4) || (addr->has_ipv6 && !addr->ipv6)) { 153*1856835dSDaniel P. Berrange return PF_INET; 154*1856835dSDaniel P. Berrange } 155*1856835dSDaniel P. Berrange return PF_UNSPEC; 156*1856835dSDaniel P. Berrange } 157*1856835dSDaniel P. Berrange 158*1856835dSDaniel P. Berrange static int inet_listen_saddr(InetSocketAddress *saddr, 159*1856835dSDaniel P. Berrange int port_offset, 160*1856835dSDaniel P. Berrange bool update_addr, 161*1856835dSDaniel P. Berrange Error **errp) 162baacf047SPaolo Bonzini { 163baacf047SPaolo Bonzini struct addrinfo ai,*res,*e; 164baacf047SPaolo Bonzini char port[33]; 165baacf047SPaolo Bonzini char uaddr[INET6_ADDRSTRLEN+1]; 166baacf047SPaolo Bonzini char uport[33]; 167*1856835dSDaniel P. Berrange int slisten, rc, port_min, port_max, p; 168*1856835dSDaniel P. Berrange Error *err = NULL; 169baacf047SPaolo Bonzini 170baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 1713de3d698SWolfgang Bumiller ai.ai_flags = AI_PASSIVE; 172*1856835dSDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(saddr, &err); 173baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 174baacf047SPaolo Bonzini 175*1856835dSDaniel P. Berrange if (err) { 176*1856835dSDaniel P. Berrange error_propagate(errp, err); 177*1856835dSDaniel P. Berrange return -1; 178*1856835dSDaniel P. Berrange } 179*1856835dSDaniel P. Berrange 180*1856835dSDaniel P. Berrange if (saddr->host == NULL) { 1810983f5e6SDaniel P. Berrange error_setg(errp, "host not specified"); 182baacf047SPaolo Bonzini return -1; 183baacf047SPaolo Bonzini } 184*1856835dSDaniel P. Berrange if (saddr->port != NULL) { 185*1856835dSDaniel P. Berrange pstrcpy(port, sizeof(port), saddr->port); 1860983f5e6SDaniel P. Berrange } else { 1870983f5e6SDaniel P. Berrange port[0] = '\0'; 1880983f5e6SDaniel P. Berrange } 189baacf047SPaolo Bonzini 190baacf047SPaolo Bonzini /* lookup */ 1918bc89127SGerd Hoffmann if (port_offset) { 1928bc89127SGerd Hoffmann unsigned long long baseport; 1930983f5e6SDaniel P. Berrange if (strlen(port) == 0) { 1940983f5e6SDaniel P. Berrange error_setg(errp, "port not specified"); 1950983f5e6SDaniel P. Berrange return -1; 1960983f5e6SDaniel P. Berrange } 1978bc89127SGerd Hoffmann if (parse_uint_full(port, &baseport, 10) < 0) { 1988bc89127SGerd Hoffmann error_setg(errp, "can't convert to a number: %s", port); 1998bc89127SGerd Hoffmann return -1; 2008bc89127SGerd Hoffmann } 2018bc89127SGerd Hoffmann if (baseport > 65535 || 2028bc89127SGerd Hoffmann baseport + port_offset > 65535) { 2038bc89127SGerd Hoffmann error_setg(errp, "port %s out of range", port); 2048bc89127SGerd Hoffmann return -1; 2058bc89127SGerd Hoffmann } 2068bc89127SGerd Hoffmann snprintf(port, sizeof(port), "%d", (int)baseport + port_offset); 2078bc89127SGerd Hoffmann } 208*1856835dSDaniel P. Berrange rc = getaddrinfo(strlen(saddr->host) ? saddr->host : NULL, 2090983f5e6SDaniel P. Berrange strlen(port) ? port : NULL, &ai, &res); 210baacf047SPaolo Bonzini if (rc != 0) { 211*1856835dSDaniel P. Berrange error_setg(errp, "address resolution failed for %s:%s: %s", 212*1856835dSDaniel P. Berrange saddr->host, port, gai_strerror(rc)); 213baacf047SPaolo Bonzini return -1; 214baacf047SPaolo Bonzini } 215baacf047SPaolo Bonzini 216baacf047SPaolo Bonzini /* create socket + bind */ 217baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 218baacf047SPaolo Bonzini getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, 219baacf047SPaolo Bonzini uaddr,INET6_ADDRSTRLEN,uport,32, 220baacf047SPaolo Bonzini NI_NUMERICHOST | NI_NUMERICSERV); 221baacf047SPaolo Bonzini slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); 222baacf047SPaolo Bonzini if (slisten < 0) { 223baacf047SPaolo Bonzini if (!e->ai_next) { 224235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 225baacf047SPaolo Bonzini } 226baacf047SPaolo Bonzini continue; 227baacf047SPaolo Bonzini } 228baacf047SPaolo Bonzini 22904fd1c78SSebastian Ottlik socket_set_fast_reuse(slisten); 230baacf047SPaolo Bonzini #ifdef IPV6_V6ONLY 231baacf047SPaolo Bonzini if (e->ai_family == PF_INET6) { 232baacf047SPaolo Bonzini /* listen on both ipv4 and ipv6 */ 233f9b5426fSPeter Maydell const int off = 0; 2349957fc7fSStefan Weil qemu_setsockopt(slisten, IPPROTO_IPV6, IPV6_V6ONLY, &off, 235baacf047SPaolo Bonzini sizeof(off)); 236baacf047SPaolo Bonzini } 237baacf047SPaolo Bonzini #endif 238baacf047SPaolo Bonzini 239baacf047SPaolo Bonzini port_min = inet_getport(e); 240*1856835dSDaniel P. Berrange port_max = saddr->has_to ? saddr->to + port_offset : port_min; 241baacf047SPaolo Bonzini for (p = port_min; p <= port_max; p++) { 242baacf047SPaolo Bonzini inet_setport(e, p); 243baacf047SPaolo Bonzini if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) { 244baacf047SPaolo Bonzini goto listen; 245baacf047SPaolo Bonzini } 246baacf047SPaolo Bonzini if (p == port_max) { 247baacf047SPaolo Bonzini if (!e->ai_next) { 248235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to bind socket"); 249baacf047SPaolo Bonzini } 250baacf047SPaolo Bonzini } 251baacf047SPaolo Bonzini } 252baacf047SPaolo Bonzini closesocket(slisten); 253baacf047SPaolo Bonzini } 254baacf047SPaolo Bonzini freeaddrinfo(res); 255baacf047SPaolo Bonzini return -1; 256baacf047SPaolo Bonzini 257baacf047SPaolo Bonzini listen: 258baacf047SPaolo Bonzini if (listen(slisten,1) != 0) { 259235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to listen on socket"); 260baacf047SPaolo Bonzini closesocket(slisten); 261baacf047SPaolo Bonzini freeaddrinfo(res); 262baacf047SPaolo Bonzini return -1; 263baacf047SPaolo Bonzini } 264*1856835dSDaniel P. Berrange if (update_addr) { 265*1856835dSDaniel P. Berrange g_free(saddr->host); 266*1856835dSDaniel P. Berrange saddr->host = g_strdup(uaddr); 267*1856835dSDaniel P. Berrange g_free(saddr->port); 268*1856835dSDaniel P. Berrange saddr->port = g_strdup_printf("%d", 269*1856835dSDaniel P. Berrange inet_getport(e) - port_offset); 270*1856835dSDaniel P. Berrange saddr->has_ipv6 = saddr->ipv6 = e->ai_family == PF_INET6; 271*1856835dSDaniel P. Berrange saddr->has_ipv4 = saddr->ipv4 = e->ai_family != PF_INET6; 272*1856835dSDaniel P. Berrange } 273baacf047SPaolo Bonzini freeaddrinfo(res); 274baacf047SPaolo Bonzini return slisten; 275baacf047SPaolo Bonzini } 276baacf047SPaolo Bonzini 277baacf047SPaolo Bonzini #ifdef _WIN32 278baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 279baacf047SPaolo Bonzini ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY) 280baacf047SPaolo Bonzini #else 281baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 282baacf047SPaolo Bonzini ((rc) == -EINPROGRESS) 283baacf047SPaolo Bonzini #endif 284baacf047SPaolo Bonzini 285baacf047SPaolo Bonzini /* Struct to store connect state for non blocking connect */ 286baacf047SPaolo Bonzini typedef struct ConnectState { 287baacf047SPaolo Bonzini int fd; 288baacf047SPaolo Bonzini struct addrinfo *addr_list; 289baacf047SPaolo Bonzini struct addrinfo *current_addr; 290baacf047SPaolo Bonzini NonBlockingConnectHandler *callback; 291baacf047SPaolo Bonzini void *opaque; 292baacf047SPaolo Bonzini } ConnectState; 293baacf047SPaolo Bonzini 294baacf047SPaolo Bonzini static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, 295baacf047SPaolo Bonzini ConnectState *connect_state, Error **errp); 296baacf047SPaolo Bonzini 297baacf047SPaolo Bonzini static void wait_for_connect(void *opaque) 298baacf047SPaolo Bonzini { 299baacf047SPaolo Bonzini ConnectState *s = opaque; 300baacf047SPaolo Bonzini int val = 0, rc = 0; 301baacf047SPaolo Bonzini socklen_t valsize = sizeof(val); 302baacf047SPaolo Bonzini bool in_progress; 30351795029SCorey Minyard Error *err = NULL; 304baacf047SPaolo Bonzini 30582e1cc4bSFam Zheng qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 306baacf047SPaolo Bonzini 307baacf047SPaolo Bonzini do { 3089957fc7fSStefan Weil rc = qemu_getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize); 309baacf047SPaolo Bonzini } while (rc == -1 && socket_error() == EINTR); 310baacf047SPaolo Bonzini 311baacf047SPaolo Bonzini /* update rc to contain error */ 312baacf047SPaolo Bonzini if (!rc && val) { 313baacf047SPaolo Bonzini rc = -1; 31451795029SCorey Minyard errno = val; 315baacf047SPaolo Bonzini } 316baacf047SPaolo Bonzini 317baacf047SPaolo Bonzini /* connect error */ 318baacf047SPaolo Bonzini if (rc < 0) { 31951795029SCorey Minyard error_setg_errno(&err, errno, "Error connecting to socket"); 320baacf047SPaolo Bonzini closesocket(s->fd); 321baacf047SPaolo Bonzini s->fd = rc; 322baacf047SPaolo Bonzini } 323baacf047SPaolo Bonzini 324baacf047SPaolo Bonzini /* try to connect to the next address on the list */ 325baacf047SPaolo Bonzini if (s->current_addr) { 326baacf047SPaolo Bonzini while (s->current_addr->ai_next != NULL && s->fd < 0) { 327baacf047SPaolo Bonzini s->current_addr = s->current_addr->ai_next; 328baacf047SPaolo Bonzini s->fd = inet_connect_addr(s->current_addr, &in_progress, s, NULL); 32951795029SCorey Minyard if (s->fd < 0) { 33051795029SCorey Minyard error_free(err); 33151795029SCorey Minyard err = NULL; 33251795029SCorey Minyard error_setg_errno(&err, errno, "Unable to start socket connect"); 33351795029SCorey Minyard } 334baacf047SPaolo Bonzini /* connect in progress */ 335baacf047SPaolo Bonzini if (in_progress) { 33651795029SCorey Minyard goto out; 337baacf047SPaolo Bonzini } 338baacf047SPaolo Bonzini } 339baacf047SPaolo Bonzini 340baacf047SPaolo Bonzini freeaddrinfo(s->addr_list); 341baacf047SPaolo Bonzini } 342baacf047SPaolo Bonzini 343baacf047SPaolo Bonzini if (s->callback) { 34451795029SCorey Minyard s->callback(s->fd, err, s->opaque); 345baacf047SPaolo Bonzini } 346baacf047SPaolo Bonzini g_free(s); 34751795029SCorey Minyard out: 34851795029SCorey Minyard error_free(err); 349baacf047SPaolo Bonzini } 350baacf047SPaolo Bonzini 351baacf047SPaolo Bonzini static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, 352baacf047SPaolo Bonzini ConnectState *connect_state, Error **errp) 353baacf047SPaolo Bonzini { 354baacf047SPaolo Bonzini int sock, rc; 355baacf047SPaolo Bonzini 356baacf047SPaolo Bonzini *in_progress = false; 357baacf047SPaolo Bonzini 358baacf047SPaolo Bonzini sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); 359baacf047SPaolo Bonzini if (sock < 0) { 360235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 361baacf047SPaolo Bonzini return -1; 362baacf047SPaolo Bonzini } 36304fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 364baacf047SPaolo Bonzini if (connect_state != NULL) { 365f9e8caccSStefan Hajnoczi qemu_set_nonblock(sock); 366baacf047SPaolo Bonzini } 367baacf047SPaolo Bonzini /* connect to peer */ 368baacf047SPaolo Bonzini do { 369baacf047SPaolo Bonzini rc = 0; 370baacf047SPaolo Bonzini if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) { 371baacf047SPaolo Bonzini rc = -socket_error(); 372baacf047SPaolo Bonzini } 373baacf047SPaolo Bonzini } while (rc == -EINTR); 374baacf047SPaolo Bonzini 375baacf047SPaolo Bonzini if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 376baacf047SPaolo Bonzini connect_state->fd = sock; 37782e1cc4bSFam Zheng qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state); 378baacf047SPaolo Bonzini *in_progress = true; 379baacf047SPaolo Bonzini } else if (rc < 0) { 380235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to connect socket"); 381baacf047SPaolo Bonzini closesocket(sock); 382baacf047SPaolo Bonzini return -1; 383baacf047SPaolo Bonzini } 384baacf047SPaolo Bonzini return sock; 385baacf047SPaolo Bonzini } 386baacf047SPaolo Bonzini 387baacf047SPaolo Bonzini static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp) 388baacf047SPaolo Bonzini { 389baacf047SPaolo Bonzini struct addrinfo ai, *res; 390baacf047SPaolo Bonzini int rc; 391baacf047SPaolo Bonzini const char *addr; 392baacf047SPaolo Bonzini const char *port; 393baacf047SPaolo Bonzini 394baacf047SPaolo Bonzini memset(&ai, 0, sizeof(ai)); 395baacf047SPaolo Bonzini 3963de3d698SWolfgang Bumiller ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG; 397baacf047SPaolo Bonzini ai.ai_family = PF_UNSPEC; 398baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 399baacf047SPaolo Bonzini 400baacf047SPaolo Bonzini addr = qemu_opt_get(opts, "host"); 401baacf047SPaolo Bonzini port = qemu_opt_get(opts, "port"); 402baacf047SPaolo Bonzini if (addr == NULL || port == NULL) { 403baacf047SPaolo Bonzini error_setg(errp, "host and/or port not specified"); 404baacf047SPaolo Bonzini return NULL; 405baacf047SPaolo Bonzini } 406baacf047SPaolo Bonzini 407baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv4", 0)) { 408baacf047SPaolo Bonzini ai.ai_family = PF_INET; 409baacf047SPaolo Bonzini } 410baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv6", 0)) { 411baacf047SPaolo Bonzini ai.ai_family = PF_INET6; 412baacf047SPaolo Bonzini } 413baacf047SPaolo Bonzini 414baacf047SPaolo Bonzini /* lookup */ 415baacf047SPaolo Bonzini rc = getaddrinfo(addr, port, &ai, &res); 416baacf047SPaolo Bonzini if (rc != 0) { 417baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 418baacf047SPaolo Bonzini gai_strerror(rc)); 419baacf047SPaolo Bonzini return NULL; 420baacf047SPaolo Bonzini } 421baacf047SPaolo Bonzini return res; 422baacf047SPaolo Bonzini } 423baacf047SPaolo Bonzini 424baacf047SPaolo Bonzini /** 425baacf047SPaolo Bonzini * Create a socket and connect it to an address. 426baacf047SPaolo Bonzini * 427baacf047SPaolo Bonzini * @opts: QEMU options, recognized parameters strings "host" and "port", 428baacf047SPaolo Bonzini * bools "ipv4" and "ipv6". 429baacf047SPaolo Bonzini * @errp: set on error 430baacf047SPaolo Bonzini * @callback: callback function for non-blocking connect 431baacf047SPaolo Bonzini * @opaque: opaque for callback function 432baacf047SPaolo Bonzini * 433baacf047SPaolo Bonzini * Returns: -1 on error, file descriptor on success. 434baacf047SPaolo Bonzini * 435baacf047SPaolo Bonzini * If @callback is non-null, the connect is non-blocking. If this 436baacf047SPaolo Bonzini * function succeeds, callback will be called when the connection 437baacf047SPaolo Bonzini * completes, with the file descriptor on success, or -1 on error. 438baacf047SPaolo Bonzini */ 439505c4a1cSDaniel P. Berrange static int inet_connect_opts(QemuOpts *opts, Error **errp, 440baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 441baacf047SPaolo Bonzini { 4423f9286b7SMarkus Armbruster Error *local_err = NULL; 443baacf047SPaolo Bonzini struct addrinfo *res, *e; 444baacf047SPaolo Bonzini int sock = -1; 445baacf047SPaolo Bonzini bool in_progress; 446baacf047SPaolo Bonzini ConnectState *connect_state = NULL; 447baacf047SPaolo Bonzini 448baacf047SPaolo Bonzini res = inet_parse_connect_opts(opts, errp); 449baacf047SPaolo Bonzini if (!res) { 450baacf047SPaolo Bonzini return -1; 451baacf047SPaolo Bonzini } 452baacf047SPaolo Bonzini 453baacf047SPaolo Bonzini if (callback != NULL) { 454baacf047SPaolo Bonzini connect_state = g_malloc0(sizeof(*connect_state)); 455baacf047SPaolo Bonzini connect_state->addr_list = res; 456baacf047SPaolo Bonzini connect_state->callback = callback; 457baacf047SPaolo Bonzini connect_state->opaque = opaque; 458baacf047SPaolo Bonzini } 459baacf047SPaolo Bonzini 460baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 4613f9286b7SMarkus Armbruster error_free(local_err); 4623f9286b7SMarkus Armbruster local_err = NULL; 463baacf047SPaolo Bonzini if (connect_state != NULL) { 464baacf047SPaolo Bonzini connect_state->current_addr = e; 465baacf047SPaolo Bonzini } 4663f9286b7SMarkus Armbruster sock = inet_connect_addr(e, &in_progress, connect_state, &local_err); 4673f9286b7SMarkus Armbruster if (sock >= 0) { 468baacf047SPaolo Bonzini break; 469baacf047SPaolo Bonzini } 470baacf047SPaolo Bonzini } 4713f9286b7SMarkus Armbruster 4723f9286b7SMarkus Armbruster if (sock < 0) { 4733f9286b7SMarkus Armbruster error_propagate(errp, local_err); 4743f9286b7SMarkus Armbruster } else if (in_progress) { 4753f9286b7SMarkus Armbruster /* wait_for_connect() will do the rest */ 4763f9286b7SMarkus Armbruster return sock; 4773f9286b7SMarkus Armbruster } else { 4783f9286b7SMarkus Armbruster if (callback) { 47951795029SCorey Minyard callback(sock, NULL, opaque); 4803f9286b7SMarkus Armbruster } 4813f9286b7SMarkus Armbruster } 482baacf047SPaolo Bonzini g_free(connect_state); 483baacf047SPaolo Bonzini freeaddrinfo(res); 484baacf047SPaolo Bonzini return sock; 485baacf047SPaolo Bonzini } 486baacf047SPaolo Bonzini 487505c4a1cSDaniel P. Berrange static int inet_dgram_opts(QemuOpts *opts, Error **errp) 488baacf047SPaolo Bonzini { 489baacf047SPaolo Bonzini struct addrinfo ai, *peer = NULL, *local = NULL; 490baacf047SPaolo Bonzini const char *addr; 491baacf047SPaolo Bonzini const char *port; 492baacf047SPaolo Bonzini int sock = -1, rc; 493baacf047SPaolo Bonzini 494baacf047SPaolo Bonzini /* lookup peer addr */ 495baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 4963de3d698SWolfgang Bumiller ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG; 497baacf047SPaolo Bonzini ai.ai_family = PF_UNSPEC; 498baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 499baacf047SPaolo Bonzini 500baacf047SPaolo Bonzini addr = qemu_opt_get(opts, "host"); 501baacf047SPaolo Bonzini port = qemu_opt_get(opts, "port"); 502baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 503baacf047SPaolo Bonzini addr = "localhost"; 504baacf047SPaolo Bonzini } 505baacf047SPaolo Bonzini if (port == NULL || strlen(port) == 0) { 506baacf047SPaolo Bonzini error_setg(errp, "remote port not specified"); 507baacf047SPaolo Bonzini return -1; 508baacf047SPaolo Bonzini } 509baacf047SPaolo Bonzini 510baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv4", 0)) 511baacf047SPaolo Bonzini ai.ai_family = PF_INET; 512baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv6", 0)) 513baacf047SPaolo Bonzini ai.ai_family = PF_INET6; 514baacf047SPaolo Bonzini 515baacf047SPaolo Bonzini if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) { 516baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 517baacf047SPaolo Bonzini gai_strerror(rc)); 518baacf047SPaolo Bonzini return -1; 519baacf047SPaolo Bonzini } 520baacf047SPaolo Bonzini 521baacf047SPaolo Bonzini /* lookup local addr */ 522baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 523baacf047SPaolo Bonzini ai.ai_flags = AI_PASSIVE; 524baacf047SPaolo Bonzini ai.ai_family = peer->ai_family; 525baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 526baacf047SPaolo Bonzini 527baacf047SPaolo Bonzini addr = qemu_opt_get(opts, "localaddr"); 528baacf047SPaolo Bonzini port = qemu_opt_get(opts, "localport"); 529baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 530baacf047SPaolo Bonzini addr = NULL; 531baacf047SPaolo Bonzini } 532baacf047SPaolo Bonzini if (!port || strlen(port) == 0) 533baacf047SPaolo Bonzini port = "0"; 534baacf047SPaolo Bonzini 535baacf047SPaolo Bonzini if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) { 536baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 537baacf047SPaolo Bonzini gai_strerror(rc)); 538baacf047SPaolo Bonzini goto err; 539baacf047SPaolo Bonzini } 540baacf047SPaolo Bonzini 541baacf047SPaolo Bonzini /* create socket */ 542baacf047SPaolo Bonzini sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); 543baacf047SPaolo Bonzini if (sock < 0) { 544235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 545baacf047SPaolo Bonzini goto err; 546baacf047SPaolo Bonzini } 54704fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 548baacf047SPaolo Bonzini 549baacf047SPaolo Bonzini /* bind socket */ 550baacf047SPaolo Bonzini if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { 551235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to bind socket"); 552baacf047SPaolo Bonzini goto err; 553baacf047SPaolo Bonzini } 554baacf047SPaolo Bonzini 555baacf047SPaolo Bonzini /* connect to peer */ 556baacf047SPaolo Bonzini if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { 557235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to connect socket"); 558baacf047SPaolo Bonzini goto err; 559baacf047SPaolo Bonzini } 560baacf047SPaolo Bonzini 561baacf047SPaolo Bonzini freeaddrinfo(local); 562baacf047SPaolo Bonzini freeaddrinfo(peer); 563baacf047SPaolo Bonzini return sock; 564baacf047SPaolo Bonzini 565baacf047SPaolo Bonzini err: 566baacf047SPaolo Bonzini if (-1 != sock) 567baacf047SPaolo Bonzini closesocket(sock); 568baacf047SPaolo Bonzini if (local) 569baacf047SPaolo Bonzini freeaddrinfo(local); 570baacf047SPaolo Bonzini if (peer) 571baacf047SPaolo Bonzini freeaddrinfo(peer); 572baacf047SPaolo Bonzini return -1; 573baacf047SPaolo Bonzini } 574baacf047SPaolo Bonzini 575baacf047SPaolo Bonzini /* compatibility wrapper */ 576f17c90beSKevin Wolf InetSocketAddress *inet_parse(const char *str, Error **errp) 577baacf047SPaolo Bonzini { 578baacf047SPaolo Bonzini InetSocketAddress *addr; 579baacf047SPaolo Bonzini const char *optstr, *h; 58055a10996SKevin Wolf char host[65]; 581baacf047SPaolo Bonzini char port[33]; 582baacf047SPaolo Bonzini int to; 583baacf047SPaolo Bonzini int pos; 584baacf047SPaolo Bonzini 585baacf047SPaolo Bonzini addr = g_new0(InetSocketAddress, 1); 586baacf047SPaolo Bonzini 587baacf047SPaolo Bonzini /* parse address */ 588baacf047SPaolo Bonzini if (str[0] == ':') { 589baacf047SPaolo Bonzini /* no host given */ 590baacf047SPaolo Bonzini host[0] = '\0'; 591baacf047SPaolo Bonzini if (1 != sscanf(str, ":%32[^,]%n", port, &pos)) { 592baacf047SPaolo Bonzini error_setg(errp, "error parsing port in address '%s'", str); 593baacf047SPaolo Bonzini goto fail; 594baacf047SPaolo Bonzini } 595baacf047SPaolo Bonzini } else if (str[0] == '[') { 596baacf047SPaolo Bonzini /* IPv6 addr */ 597baacf047SPaolo Bonzini if (2 != sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos)) { 598baacf047SPaolo Bonzini error_setg(errp, "error parsing IPv6 address '%s'", str); 599baacf047SPaolo Bonzini goto fail; 600baacf047SPaolo Bonzini } 601baacf047SPaolo Bonzini addr->ipv6 = addr->has_ipv6 = true; 602baacf047SPaolo Bonzini } else { 603391b7b97SJán Tomko /* hostname or IPv4 addr */ 604baacf047SPaolo Bonzini if (2 != sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos)) { 605baacf047SPaolo Bonzini error_setg(errp, "error parsing address '%s'", str); 606baacf047SPaolo Bonzini goto fail; 607baacf047SPaolo Bonzini } 608391b7b97SJán Tomko if (host[strspn(host, "0123456789.")] == '\0') { 609391b7b97SJán Tomko addr->ipv4 = addr->has_ipv4 = true; 610391b7b97SJán Tomko } 611baacf047SPaolo Bonzini } 612baacf047SPaolo Bonzini 613baacf047SPaolo Bonzini addr->host = g_strdup(host); 614baacf047SPaolo Bonzini addr->port = g_strdup(port); 615baacf047SPaolo Bonzini 616baacf047SPaolo Bonzini /* parse options */ 617baacf047SPaolo Bonzini optstr = str + pos; 618baacf047SPaolo Bonzini h = strstr(optstr, ",to="); 619baacf047SPaolo Bonzini if (h) { 620baacf047SPaolo Bonzini h += 4; 621baacf047SPaolo Bonzini if (sscanf(h, "%d%n", &to, &pos) != 1 || 622baacf047SPaolo Bonzini (h[pos] != '\0' && h[pos] != ',')) { 623baacf047SPaolo Bonzini error_setg(errp, "error parsing to= argument"); 624baacf047SPaolo Bonzini goto fail; 625baacf047SPaolo Bonzini } 626baacf047SPaolo Bonzini addr->has_to = true; 627baacf047SPaolo Bonzini addr->to = to; 628baacf047SPaolo Bonzini } 629baacf047SPaolo Bonzini if (strstr(optstr, ",ipv4")) { 630baacf047SPaolo Bonzini addr->ipv4 = addr->has_ipv4 = true; 631baacf047SPaolo Bonzini } 632baacf047SPaolo Bonzini if (strstr(optstr, ",ipv6")) { 633baacf047SPaolo Bonzini addr->ipv6 = addr->has_ipv6 = true; 634baacf047SPaolo Bonzini } 635baacf047SPaolo Bonzini return addr; 636baacf047SPaolo Bonzini 637baacf047SPaolo Bonzini fail: 638baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 639baacf047SPaolo Bonzini return NULL; 640baacf047SPaolo Bonzini } 641baacf047SPaolo Bonzini 642f17c90beSKevin Wolf static void inet_addr_to_opts(QemuOpts *opts, const InetSocketAddress *addr) 643baacf047SPaolo Bonzini { 644b77e7c8eSPaolo Bonzini bool ipv4 = addr->has_ipv4 && addr->ipv4; 645b77e7c8eSPaolo Bonzini bool ipv6 = addr->has_ipv6 && addr->ipv6; 646baacf047SPaolo Bonzini 647b77e7c8eSPaolo Bonzini if (ipv4 || ipv6) { 648cccb7967SMarkus Armbruster qemu_opt_set_bool(opts, "ipv4", ipv4, &error_abort); 649cccb7967SMarkus Armbruster qemu_opt_set_bool(opts, "ipv6", ipv6, &error_abort); 650b77e7c8eSPaolo Bonzini } else if (addr->has_ipv4 || addr->has_ipv6) { 651b77e7c8eSPaolo Bonzini qemu_opt_set_bool(opts, "ipv4", !addr->has_ipv4, &error_abort); 652b77e7c8eSPaolo Bonzini qemu_opt_set_bool(opts, "ipv6", !addr->has_ipv6, &error_abort); 653baacf047SPaolo Bonzini } 654baacf047SPaolo Bonzini if (addr->has_to) { 65562b3de69SMarkus Armbruster qemu_opt_set_number(opts, "to", addr->to, &error_abort); 656baacf047SPaolo Bonzini } 657f43e47dbSMarkus Armbruster qemu_opt_set(opts, "host", addr->host, &error_abort); 658f43e47dbSMarkus Armbruster qemu_opt_set(opts, "port", addr->port, &error_abort); 659baacf047SPaolo Bonzini } 660baacf047SPaolo Bonzini 661baacf047SPaolo Bonzini int inet_listen(const char *str, char *ostr, int olen, 662baacf047SPaolo Bonzini int socktype, int port_offset, Error **errp) 663baacf047SPaolo Bonzini { 664baacf047SPaolo Bonzini char *optstr; 665baacf047SPaolo Bonzini int sock = -1; 666baacf047SPaolo Bonzini InetSocketAddress *addr; 667baacf047SPaolo Bonzini 668baacf047SPaolo Bonzini addr = inet_parse(str, errp); 669baacf047SPaolo Bonzini if (addr != NULL) { 670*1856835dSDaniel P. Berrange sock = inet_listen_saddr(addr, port_offset, true, errp); 671baacf047SPaolo Bonzini if (sock != -1 && ostr) { 672baacf047SPaolo Bonzini optstr = strchr(str, ','); 673*1856835dSDaniel P. Berrange if (addr->ipv6) { 674baacf047SPaolo Bonzini snprintf(ostr, olen, "[%s]:%s%s", 675*1856835dSDaniel P. Berrange addr->host, 676*1856835dSDaniel P. Berrange addr->port, 677baacf047SPaolo Bonzini optstr ? optstr : ""); 678baacf047SPaolo Bonzini } else { 679baacf047SPaolo Bonzini snprintf(ostr, olen, "%s:%s%s", 680*1856835dSDaniel P. Berrange addr->host, 681*1856835dSDaniel P. Berrange addr->port, 682baacf047SPaolo Bonzini optstr ? optstr : ""); 683baacf047SPaolo Bonzini } 684baacf047SPaolo Bonzini } 685*1856835dSDaniel P. Berrange qapi_free_InetSocketAddress(addr); 686baacf047SPaolo Bonzini } 687baacf047SPaolo Bonzini return sock; 688baacf047SPaolo Bonzini } 689baacf047SPaolo Bonzini 690baacf047SPaolo Bonzini /** 691baacf047SPaolo Bonzini * Create a blocking socket and connect it to an address. 692baacf047SPaolo Bonzini * 693baacf047SPaolo Bonzini * @str: address string 694baacf047SPaolo Bonzini * @errp: set in case of an error 695baacf047SPaolo Bonzini * 696baacf047SPaolo Bonzini * Returns -1 in case of error, file descriptor on success 697baacf047SPaolo Bonzini **/ 698baacf047SPaolo Bonzini int inet_connect(const char *str, Error **errp) 699baacf047SPaolo Bonzini { 700baacf047SPaolo Bonzini QemuOpts *opts; 701baacf047SPaolo Bonzini int sock = -1; 702baacf047SPaolo Bonzini InetSocketAddress *addr; 703baacf047SPaolo Bonzini 704baacf047SPaolo Bonzini addr = inet_parse(str, errp); 705baacf047SPaolo Bonzini if (addr != NULL) { 70687ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 707baacf047SPaolo Bonzini inet_addr_to_opts(opts, addr); 708baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 709baacf047SPaolo Bonzini sock = inet_connect_opts(opts, errp, NULL, NULL); 710baacf047SPaolo Bonzini qemu_opts_del(opts); 711baacf047SPaolo Bonzini } 712baacf047SPaolo Bonzini return sock; 713baacf047SPaolo Bonzini } 714baacf047SPaolo Bonzini 715baacf047SPaolo Bonzini /** 716baacf047SPaolo Bonzini * Create a non-blocking socket and connect it to an address. 717baacf047SPaolo Bonzini * Calls the callback function with fd in case of success or -1 in case of 718baacf047SPaolo Bonzini * error. 719baacf047SPaolo Bonzini * 720baacf047SPaolo Bonzini * @str: address string 721baacf047SPaolo Bonzini * @callback: callback function that is called when connect completes, 722baacf047SPaolo Bonzini * cannot be NULL. 723baacf047SPaolo Bonzini * @opaque: opaque for callback function 724baacf047SPaolo Bonzini * @errp: set in case of an error 725baacf047SPaolo Bonzini * 726baacf047SPaolo Bonzini * Returns: -1 on immediate error, file descriptor on success. 727baacf047SPaolo Bonzini **/ 728baacf047SPaolo Bonzini int inet_nonblocking_connect(const char *str, 729baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, 730baacf047SPaolo Bonzini void *opaque, Error **errp) 731baacf047SPaolo Bonzini { 732baacf047SPaolo Bonzini QemuOpts *opts; 733baacf047SPaolo Bonzini int sock = -1; 734baacf047SPaolo Bonzini InetSocketAddress *addr; 735baacf047SPaolo Bonzini 736baacf047SPaolo Bonzini g_assert(callback != NULL); 737baacf047SPaolo Bonzini 738baacf047SPaolo Bonzini addr = inet_parse(str, errp); 739baacf047SPaolo Bonzini if (addr != NULL) { 74087ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 741baacf047SPaolo Bonzini inet_addr_to_opts(opts, addr); 742baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 743baacf047SPaolo Bonzini sock = inet_connect_opts(opts, errp, callback, opaque); 744baacf047SPaolo Bonzini qemu_opts_del(opts); 745baacf047SPaolo Bonzini } 746baacf047SPaolo Bonzini return sock; 747baacf047SPaolo Bonzini } 748baacf047SPaolo Bonzini 749baacf047SPaolo Bonzini #ifndef _WIN32 750baacf047SPaolo Bonzini 751*1856835dSDaniel P. Berrange static int unix_listen_saddr(UnixSocketAddress *saddr, 752*1856835dSDaniel P. Berrange bool update_addr, 753*1856835dSDaniel P. Berrange Error **errp) 754baacf047SPaolo Bonzini { 755baacf047SPaolo Bonzini struct sockaddr_un un; 756baacf047SPaolo Bonzini int sock, fd; 757baacf047SPaolo Bonzini 758baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 759baacf047SPaolo Bonzini if (sock < 0) { 760b658c53dSPaolo Bonzini error_setg_errno(errp, errno, "Failed to create Unix socket"); 761baacf047SPaolo Bonzini return -1; 762baacf047SPaolo Bonzini } 763baacf047SPaolo Bonzini 764baacf047SPaolo Bonzini memset(&un, 0, sizeof(un)); 765baacf047SPaolo Bonzini un.sun_family = AF_UNIX; 766*1856835dSDaniel P. Berrange if (saddr->path && strlen(saddr->path)) { 767*1856835dSDaniel P. Berrange snprintf(un.sun_path, sizeof(un.sun_path), "%s", saddr->path); 768baacf047SPaolo Bonzini } else { 769b658c53dSPaolo Bonzini const char *tmpdir = getenv("TMPDIR"); 770b658c53dSPaolo Bonzini tmpdir = tmpdir ? tmpdir : "/tmp"; 771b658c53dSPaolo Bonzini if (snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX", 772b658c53dSPaolo Bonzini tmpdir) >= sizeof(un.sun_path)) { 773b658c53dSPaolo Bonzini error_setg_errno(errp, errno, 774b658c53dSPaolo Bonzini "TMPDIR environment variable (%s) too large", tmpdir); 775b658c53dSPaolo Bonzini goto err; 776b658c53dSPaolo Bonzini } 777b658c53dSPaolo Bonzini 778baacf047SPaolo Bonzini /* 779baacf047SPaolo Bonzini * This dummy fd usage silences the mktemp() unsecure warning. 780baacf047SPaolo Bonzini * Using mkstemp() doesn't make things more secure here 781baacf047SPaolo Bonzini * though. bind() complains about existing files, so we have 782baacf047SPaolo Bonzini * to unlink first and thus re-open the race window. The 783baacf047SPaolo Bonzini * worst case possible is bind() failing, i.e. a DoS attack. 784baacf047SPaolo Bonzini */ 785b658c53dSPaolo Bonzini fd = mkstemp(un.sun_path); 786b658c53dSPaolo Bonzini if (fd < 0) { 787b658c53dSPaolo Bonzini error_setg_errno(errp, errno, 788b658c53dSPaolo Bonzini "Failed to make a temporary socket name in %s", tmpdir); 789b658c53dSPaolo Bonzini goto err; 790b658c53dSPaolo Bonzini } 791b658c53dSPaolo Bonzini close(fd); 792*1856835dSDaniel P. Berrange if (update_addr) { 793*1856835dSDaniel P. Berrange g_free(saddr->path); 794*1856835dSDaniel P. Berrange saddr->path = g_strdup(un.sun_path); 795*1856835dSDaniel P. Berrange } 796baacf047SPaolo Bonzini } 797baacf047SPaolo Bonzini 798a2f31f18SPaolo Bonzini if (unlink(un.sun_path) < 0 && errno != ENOENT) { 7990ef705a2SCole Robinson error_setg_errno(errp, errno, 8000ef705a2SCole Robinson "Failed to unlink socket %s", un.sun_path); 8010ef705a2SCole Robinson goto err; 8020ef705a2SCole Robinson } 803baacf047SPaolo Bonzini if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { 804b658c53dSPaolo Bonzini error_setg_errno(errp, errno, "Failed to bind socket to %s", un.sun_path); 805baacf047SPaolo Bonzini goto err; 806baacf047SPaolo Bonzini } 807baacf047SPaolo Bonzini if (listen(sock, 1) < 0) { 808235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to listen on socket"); 809baacf047SPaolo Bonzini goto err; 810baacf047SPaolo Bonzini } 811baacf047SPaolo Bonzini 812baacf047SPaolo Bonzini return sock; 813baacf047SPaolo Bonzini 814baacf047SPaolo Bonzini err: 815baacf047SPaolo Bonzini closesocket(sock); 816baacf047SPaolo Bonzini return -1; 817baacf047SPaolo Bonzini } 818baacf047SPaolo Bonzini 819505c4a1cSDaniel P. Berrange static int unix_connect_opts(QemuOpts *opts, Error **errp, 820baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 821baacf047SPaolo Bonzini { 822baacf047SPaolo Bonzini struct sockaddr_un un; 823baacf047SPaolo Bonzini const char *path = qemu_opt_get(opts, "path"); 824baacf047SPaolo Bonzini ConnectState *connect_state = NULL; 825baacf047SPaolo Bonzini int sock, rc; 826baacf047SPaolo Bonzini 8278108fd3eSGonglei if (path == NULL) { 828312fd5f2SMarkus Armbruster error_setg(errp, "unix connect: no path specified"); 829baacf047SPaolo Bonzini return -1; 830baacf047SPaolo Bonzini } 831baacf047SPaolo Bonzini 832baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 833baacf047SPaolo Bonzini if (sock < 0) { 834235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 835baacf047SPaolo Bonzini return -1; 836baacf047SPaolo Bonzini } 837baacf047SPaolo Bonzini if (callback != NULL) { 838baacf047SPaolo Bonzini connect_state = g_malloc0(sizeof(*connect_state)); 839baacf047SPaolo Bonzini connect_state->callback = callback; 840baacf047SPaolo Bonzini connect_state->opaque = opaque; 841f9e8caccSStefan Hajnoczi qemu_set_nonblock(sock); 842baacf047SPaolo Bonzini } 843baacf047SPaolo Bonzini 844baacf047SPaolo Bonzini memset(&un, 0, sizeof(un)); 845baacf047SPaolo Bonzini un.sun_family = AF_UNIX; 846baacf047SPaolo Bonzini snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); 847baacf047SPaolo Bonzini 848baacf047SPaolo Bonzini /* connect to peer */ 849baacf047SPaolo Bonzini do { 850baacf047SPaolo Bonzini rc = 0; 851baacf047SPaolo Bonzini if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { 852baacf047SPaolo Bonzini rc = -socket_error(); 853baacf047SPaolo Bonzini } 854baacf047SPaolo Bonzini } while (rc == -EINTR); 855baacf047SPaolo Bonzini 856baacf047SPaolo Bonzini if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 857baacf047SPaolo Bonzini connect_state->fd = sock; 85882e1cc4bSFam Zheng qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state); 859baacf047SPaolo Bonzini return sock; 860baacf047SPaolo Bonzini } else if (rc >= 0) { 861baacf047SPaolo Bonzini /* non blocking socket immediate success, call callback */ 862baacf047SPaolo Bonzini if (callback != NULL) { 86351795029SCorey Minyard callback(sock, NULL, opaque); 864baacf047SPaolo Bonzini } 865baacf047SPaolo Bonzini } 866baacf047SPaolo Bonzini 867baacf047SPaolo Bonzini if (rc < 0) { 868235256a2SMarkus Armbruster error_setg_errno(errp, -rc, "Failed to connect socket"); 869baacf047SPaolo Bonzini close(sock); 870baacf047SPaolo Bonzini sock = -1; 871baacf047SPaolo Bonzini } 872baacf047SPaolo Bonzini 873baacf047SPaolo Bonzini g_free(connect_state); 874baacf047SPaolo Bonzini return sock; 875baacf047SPaolo Bonzini } 876baacf047SPaolo Bonzini 877baacf047SPaolo Bonzini #else 878baacf047SPaolo Bonzini 879*1856835dSDaniel P. Berrange static int unix_listen_saddr(UnixSocketAddress *saddr, 880*1856835dSDaniel P. Berrange bool update_addr, 881*1856835dSDaniel P. Berrange Error **errp) 882baacf047SPaolo Bonzini { 883baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 884baacf047SPaolo Bonzini errno = ENOTSUP; 885baacf047SPaolo Bonzini return -1; 886baacf047SPaolo Bonzini } 887baacf047SPaolo Bonzini 888505c4a1cSDaniel P. Berrange static int unix_connect_opts(QemuOpts *opts, Error **errp, 889baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 890baacf047SPaolo Bonzini { 891baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 892baacf047SPaolo Bonzini errno = ENOTSUP; 893baacf047SPaolo Bonzini return -1; 894baacf047SPaolo Bonzini } 895baacf047SPaolo Bonzini #endif 896baacf047SPaolo Bonzini 897baacf047SPaolo Bonzini /* compatibility wrapper */ 898baacf047SPaolo Bonzini int unix_listen(const char *str, char *ostr, int olen, Error **errp) 899baacf047SPaolo Bonzini { 900baacf047SPaolo Bonzini char *path, *optstr; 901baacf047SPaolo Bonzini int sock, len; 902*1856835dSDaniel P. Berrange UnixSocketAddress *saddr; 903baacf047SPaolo Bonzini 904*1856835dSDaniel P. Berrange saddr = g_new0(UnixSocketAddress, 1); 905baacf047SPaolo Bonzini 906baacf047SPaolo Bonzini optstr = strchr(str, ','); 907baacf047SPaolo Bonzini if (optstr) { 908baacf047SPaolo Bonzini len = optstr - str; 909baacf047SPaolo Bonzini if (len) { 910baacf047SPaolo Bonzini path = g_malloc(len+1); 911baacf047SPaolo Bonzini snprintf(path, len+1, "%.*s", len, str); 912*1856835dSDaniel P. Berrange saddr->path = path; 913baacf047SPaolo Bonzini } 914baacf047SPaolo Bonzini } else { 915*1856835dSDaniel P. Berrange saddr->path = g_strdup(str); 916baacf047SPaolo Bonzini } 917baacf047SPaolo Bonzini 918*1856835dSDaniel P. Berrange sock = unix_listen_saddr(saddr, true, errp); 919baacf047SPaolo Bonzini 920baacf047SPaolo Bonzini if (sock != -1 && ostr) 921*1856835dSDaniel P. Berrange snprintf(ostr, olen, "%s%s", saddr->path, optstr ? optstr : ""); 922*1856835dSDaniel P. Berrange qapi_free_UnixSocketAddress(saddr); 923baacf047SPaolo Bonzini return sock; 924baacf047SPaolo Bonzini } 925baacf047SPaolo Bonzini 926baacf047SPaolo Bonzini int unix_connect(const char *path, Error **errp) 927baacf047SPaolo Bonzini { 928baacf047SPaolo Bonzini QemuOpts *opts; 929baacf047SPaolo Bonzini int sock; 930baacf047SPaolo Bonzini 93187ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 932f43e47dbSMarkus Armbruster qemu_opt_set(opts, "path", path, &error_abort); 933baacf047SPaolo Bonzini sock = unix_connect_opts(opts, errp, NULL, NULL); 934baacf047SPaolo Bonzini qemu_opts_del(opts); 935baacf047SPaolo Bonzini return sock; 936baacf047SPaolo Bonzini } 937baacf047SPaolo Bonzini 938baacf047SPaolo Bonzini 939baacf047SPaolo Bonzini int unix_nonblocking_connect(const char *path, 940baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, 941baacf047SPaolo Bonzini void *opaque, Error **errp) 942baacf047SPaolo Bonzini { 943baacf047SPaolo Bonzini QemuOpts *opts; 944baacf047SPaolo Bonzini int sock = -1; 945baacf047SPaolo Bonzini 946baacf047SPaolo Bonzini g_assert(callback != NULL); 947baacf047SPaolo Bonzini 94887ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 949f43e47dbSMarkus Armbruster qemu_opt_set(opts, "path", path, &error_abort); 950baacf047SPaolo Bonzini sock = unix_connect_opts(opts, errp, callback, opaque); 951baacf047SPaolo Bonzini qemu_opts_del(opts); 952baacf047SPaolo Bonzini return sock; 953baacf047SPaolo Bonzini } 954baacf047SPaolo Bonzini 955baacf047SPaolo Bonzini SocketAddress *socket_parse(const char *str, Error **errp) 956baacf047SPaolo Bonzini { 957afde3f8bSGerd Hoffmann SocketAddress *addr; 958baacf047SPaolo Bonzini 959afde3f8bSGerd Hoffmann addr = g_new0(SocketAddress, 1); 960baacf047SPaolo Bonzini if (strstart(str, "unix:", NULL)) { 961baacf047SPaolo Bonzini if (str[5] == '\0') { 962312fd5f2SMarkus Armbruster error_setg(errp, "invalid Unix socket address"); 963baacf047SPaolo Bonzini goto fail; 964baacf047SPaolo Bonzini } else { 9652d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_UNIX; 9662d32addaSEric Blake addr->u.q_unix = g_new(UnixSocketAddress, 1); 9672d32addaSEric Blake addr->u.q_unix->path = g_strdup(str + 5); 968baacf047SPaolo Bonzini } 969baacf047SPaolo Bonzini } else if (strstart(str, "fd:", NULL)) { 970baacf047SPaolo Bonzini if (str[3] == '\0') { 971312fd5f2SMarkus Armbruster error_setg(errp, "invalid file descriptor address"); 972baacf047SPaolo Bonzini goto fail; 973baacf047SPaolo Bonzini } else { 9742d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_FD; 9752d32addaSEric Blake addr->u.fd = g_new(String, 1); 9762d32addaSEric Blake addr->u.fd->str = g_strdup(str + 3); 977baacf047SPaolo Bonzini } 978baacf047SPaolo Bonzini } else { 9792d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_INET; 9802d32addaSEric Blake addr->u.inet = inet_parse(str, errp); 9812d32addaSEric Blake if (addr->u.inet == NULL) { 982baacf047SPaolo Bonzini goto fail; 983baacf047SPaolo Bonzini } 984baacf047SPaolo Bonzini } 985baacf047SPaolo Bonzini return addr; 986baacf047SPaolo Bonzini 987baacf047SPaolo Bonzini fail: 988baacf047SPaolo Bonzini qapi_free_SocketAddress(addr); 989baacf047SPaolo Bonzini return NULL; 990baacf047SPaolo Bonzini } 991baacf047SPaolo Bonzini 992baacf047SPaolo Bonzini int socket_connect(SocketAddress *addr, Error **errp, 993baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 994baacf047SPaolo Bonzini { 995baacf047SPaolo Bonzini QemuOpts *opts; 996baacf047SPaolo Bonzini int fd; 997baacf047SPaolo Bonzini 99887ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 9992d32addaSEric Blake switch (addr->type) { 1000baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_INET: 10012d32addaSEric Blake inet_addr_to_opts(opts, addr->u.inet); 1002baacf047SPaolo Bonzini fd = inet_connect_opts(opts, errp, callback, opaque); 1003baacf047SPaolo Bonzini break; 1004baacf047SPaolo Bonzini 1005baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_UNIX: 10062d32addaSEric Blake qemu_opt_set(opts, "path", addr->u.q_unix->path, &error_abort); 1007baacf047SPaolo Bonzini fd = unix_connect_opts(opts, errp, callback, opaque); 1008baacf047SPaolo Bonzini break; 1009baacf047SPaolo Bonzini 1010baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_FD: 10112d32addaSEric Blake fd = monitor_get_fd(cur_mon, addr->u.fd->str, errp); 1012d1ec72a4SGerd Hoffmann if (fd >= 0 && callback) { 10131a751ebfSStefan Hajnoczi qemu_set_nonblock(fd); 101451795029SCorey Minyard callback(fd, NULL, opaque); 1015baacf047SPaolo Bonzini } 1016baacf047SPaolo Bonzini break; 1017baacf047SPaolo Bonzini 1018baacf047SPaolo Bonzini default: 1019baacf047SPaolo Bonzini abort(); 1020baacf047SPaolo Bonzini } 1021baacf047SPaolo Bonzini qemu_opts_del(opts); 1022baacf047SPaolo Bonzini return fd; 1023baacf047SPaolo Bonzini } 1024baacf047SPaolo Bonzini 1025baacf047SPaolo Bonzini int socket_listen(SocketAddress *addr, Error **errp) 1026baacf047SPaolo Bonzini { 1027baacf047SPaolo Bonzini int fd; 1028baacf047SPaolo Bonzini 10292d32addaSEric Blake switch (addr->type) { 1030baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_INET: 1031*1856835dSDaniel P. Berrange fd = inet_listen_saddr(addr->u.inet, 0, false, errp); 1032baacf047SPaolo Bonzini break; 1033baacf047SPaolo Bonzini 1034baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_UNIX: 1035*1856835dSDaniel P. Berrange fd = unix_listen_saddr(addr->u.q_unix, false, errp); 1036baacf047SPaolo Bonzini break; 1037baacf047SPaolo Bonzini 1038baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_FD: 10392d32addaSEric Blake fd = monitor_get_fd(cur_mon, addr->u.fd->str, errp); 1040baacf047SPaolo Bonzini break; 1041baacf047SPaolo Bonzini 1042baacf047SPaolo Bonzini default: 1043baacf047SPaolo Bonzini abort(); 1044baacf047SPaolo Bonzini } 1045baacf047SPaolo Bonzini return fd; 1046baacf047SPaolo Bonzini } 1047baacf047SPaolo Bonzini 10483ecc059dSGerd Hoffmann int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp) 10493ecc059dSGerd Hoffmann { 10503ecc059dSGerd Hoffmann QemuOpts *opts; 10513ecc059dSGerd Hoffmann int fd; 10523ecc059dSGerd Hoffmann 105387ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 10542d32addaSEric Blake switch (remote->type) { 10553ecc059dSGerd Hoffmann case SOCKET_ADDRESS_KIND_INET: 10562d32addaSEric Blake inet_addr_to_opts(opts, remote->u.inet); 10573ecc059dSGerd Hoffmann if (local) { 10582d32addaSEric Blake qemu_opt_set(opts, "localaddr", local->u.inet->host, &error_abort); 10592d32addaSEric Blake qemu_opt_set(opts, "localport", local->u.inet->port, &error_abort); 10603ecc059dSGerd Hoffmann } 10613ecc059dSGerd Hoffmann fd = inet_dgram_opts(opts, errp); 10623ecc059dSGerd Hoffmann break; 10633ecc059dSGerd Hoffmann 10643ecc059dSGerd Hoffmann default: 10653ecc059dSGerd Hoffmann error_setg(errp, "socket type unsupported for datagram"); 10667a5b6af1SGerd Hoffmann fd = -1; 10673ecc059dSGerd Hoffmann } 10683ecc059dSGerd Hoffmann qemu_opts_del(opts); 10693ecc059dSGerd Hoffmann return fd; 10703ecc059dSGerd Hoffmann } 107117c55decSDaniel P. Berrange 107217c55decSDaniel P. Berrange 107317c55decSDaniel P. Berrange static SocketAddress * 107417c55decSDaniel P. Berrange socket_sockaddr_to_address_inet(struct sockaddr_storage *sa, 107517c55decSDaniel P. Berrange socklen_t salen, 107617c55decSDaniel P. Berrange Error **errp) 107717c55decSDaniel P. Berrange { 107817c55decSDaniel P. Berrange char host[NI_MAXHOST]; 107917c55decSDaniel P. Berrange char serv[NI_MAXSERV]; 108017c55decSDaniel P. Berrange SocketAddress *addr; 108117c55decSDaniel P. Berrange int ret; 108217c55decSDaniel P. Berrange 108317c55decSDaniel P. Berrange ret = getnameinfo((struct sockaddr *)sa, salen, 108417c55decSDaniel P. Berrange host, sizeof(host), 108517c55decSDaniel P. Berrange serv, sizeof(serv), 108617c55decSDaniel P. Berrange NI_NUMERICHOST | NI_NUMERICSERV); 108717c55decSDaniel P. Berrange if (ret != 0) { 108817c55decSDaniel P. Berrange error_setg(errp, "Cannot format numeric socket address: %s", 108917c55decSDaniel P. Berrange gai_strerror(ret)); 109017c55decSDaniel P. Berrange return NULL; 109117c55decSDaniel P. Berrange } 109217c55decSDaniel P. Berrange 109317c55decSDaniel P. Berrange addr = g_new0(SocketAddress, 1); 10942d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_INET; 10952d32addaSEric Blake addr->u.inet = g_new0(InetSocketAddress, 1); 10962d32addaSEric Blake addr->u.inet->host = g_strdup(host); 10972d32addaSEric Blake addr->u.inet->port = g_strdup(serv); 109817c55decSDaniel P. Berrange if (sa->ss_family == AF_INET) { 10992d32addaSEric Blake addr->u.inet->has_ipv4 = addr->u.inet->ipv4 = true; 110017c55decSDaniel P. Berrange } else { 11012d32addaSEric Blake addr->u.inet->has_ipv6 = addr->u.inet->ipv6 = true; 110217c55decSDaniel P. Berrange } 110317c55decSDaniel P. Berrange 110417c55decSDaniel P. Berrange return addr; 110517c55decSDaniel P. Berrange } 110617c55decSDaniel P. Berrange 110717c55decSDaniel P. Berrange 110817c55decSDaniel P. Berrange #ifndef WIN32 110917c55decSDaniel P. Berrange static SocketAddress * 111017c55decSDaniel P. Berrange socket_sockaddr_to_address_unix(struct sockaddr_storage *sa, 111117c55decSDaniel P. Berrange socklen_t salen, 111217c55decSDaniel P. Berrange Error **errp) 111317c55decSDaniel P. Berrange { 111417c55decSDaniel P. Berrange SocketAddress *addr; 111517c55decSDaniel P. Berrange struct sockaddr_un *su = (struct sockaddr_un *)sa; 111617c55decSDaniel P. Berrange 111717c55decSDaniel P. Berrange addr = g_new0(SocketAddress, 1); 11182d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_UNIX; 11192d32addaSEric Blake addr->u.q_unix = g_new0(UnixSocketAddress, 1); 112017c55decSDaniel P. Berrange if (su->sun_path[0]) { 11212d32addaSEric Blake addr->u.q_unix->path = g_strndup(su->sun_path, 112217c55decSDaniel P. Berrange sizeof(su->sun_path)); 112317c55decSDaniel P. Berrange } 112417c55decSDaniel P. Berrange 112517c55decSDaniel P. Berrange return addr; 112617c55decSDaniel P. Berrange } 112717c55decSDaniel P. Berrange #endif /* WIN32 */ 112817c55decSDaniel P. Berrange 1129559607eaSDaniel P. Berrange SocketAddress * 113017c55decSDaniel P. Berrange socket_sockaddr_to_address(struct sockaddr_storage *sa, 113117c55decSDaniel P. Berrange socklen_t salen, 113217c55decSDaniel P. Berrange Error **errp) 113317c55decSDaniel P. Berrange { 113417c55decSDaniel P. Berrange switch (sa->ss_family) { 113517c55decSDaniel P. Berrange case AF_INET: 113617c55decSDaniel P. Berrange case AF_INET6: 113717c55decSDaniel P. Berrange return socket_sockaddr_to_address_inet(sa, salen, errp); 113817c55decSDaniel P. Berrange 113917c55decSDaniel P. Berrange #ifndef WIN32 114017c55decSDaniel P. Berrange case AF_UNIX: 114117c55decSDaniel P. Berrange return socket_sockaddr_to_address_unix(sa, salen, errp); 114217c55decSDaniel P. Berrange #endif /* WIN32 */ 114317c55decSDaniel P. Berrange 114417c55decSDaniel P. Berrange default: 114517c55decSDaniel P. Berrange error_setg(errp, "socket family %d unsupported", 114617c55decSDaniel P. Berrange sa->ss_family); 114717c55decSDaniel P. Berrange return NULL; 114817c55decSDaniel P. Berrange } 114917c55decSDaniel P. Berrange return 0; 115017c55decSDaniel P. Berrange } 115117c55decSDaniel P. Berrange 115217c55decSDaniel P. Berrange 115317c55decSDaniel P. Berrange SocketAddress *socket_local_address(int fd, Error **errp) 115417c55decSDaniel P. Berrange { 115517c55decSDaniel P. Berrange struct sockaddr_storage ss; 115617c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 115717c55decSDaniel P. Berrange 115817c55decSDaniel P. Berrange if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) { 115917c55decSDaniel P. Berrange error_setg_errno(errp, socket_error(), "%s", 116017c55decSDaniel P. Berrange "Unable to query local socket address"); 116117c55decSDaniel P. Berrange return NULL; 116217c55decSDaniel P. Berrange } 116317c55decSDaniel P. Berrange 116417c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 116517c55decSDaniel P. Berrange } 116617c55decSDaniel P. Berrange 116717c55decSDaniel P. Berrange 116817c55decSDaniel P. Berrange SocketAddress *socket_remote_address(int fd, Error **errp) 116917c55decSDaniel P. Berrange { 117017c55decSDaniel P. Berrange struct sockaddr_storage ss; 117117c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 117217c55decSDaniel P. Berrange 117317c55decSDaniel P. Berrange if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) { 117417c55decSDaniel P. Berrange error_setg_errno(errp, socket_error(), "%s", 117517c55decSDaniel P. Berrange "Unable to query remote socket address"); 117617c55decSDaniel P. Berrange return NULL; 117717c55decSDaniel P. Berrange } 117817c55decSDaniel P. Berrange 117917c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 118017c55decSDaniel P. Berrange } 11812a8e21c7SDaniel P. Berrange 11822a8e21c7SDaniel P. Berrange 11832a8e21c7SDaniel P. Berrange void qapi_copy_SocketAddress(SocketAddress **p_dest, 11842a8e21c7SDaniel P. Berrange SocketAddress *src) 11852a8e21c7SDaniel P. Berrange { 11862a8e21c7SDaniel P. Berrange QmpOutputVisitor *qov; 11872a8e21c7SDaniel P. Berrange QmpInputVisitor *qiv; 11882a8e21c7SDaniel P. Berrange Visitor *ov, *iv; 11892a8e21c7SDaniel P. Berrange QObject *obj; 11902a8e21c7SDaniel P. Berrange 11912a8e21c7SDaniel P. Berrange *p_dest = NULL; 11922a8e21c7SDaniel P. Berrange 11932a8e21c7SDaniel P. Berrange qov = qmp_output_visitor_new(); 11942a8e21c7SDaniel P. Berrange ov = qmp_output_get_visitor(qov); 11952a8e21c7SDaniel P. Berrange visit_type_SocketAddress(ov, &src, NULL, &error_abort); 11962a8e21c7SDaniel P. Berrange obj = qmp_output_get_qobject(qov); 11972a8e21c7SDaniel P. Berrange qmp_output_visitor_cleanup(qov); 11982a8e21c7SDaniel P. Berrange if (!obj) { 11992a8e21c7SDaniel P. Berrange return; 12002a8e21c7SDaniel P. Berrange } 12012a8e21c7SDaniel P. Berrange 12022a8e21c7SDaniel P. Berrange qiv = qmp_input_visitor_new(obj); 12032a8e21c7SDaniel P. Berrange iv = qmp_input_get_visitor(qiv); 12042a8e21c7SDaniel P. Berrange visit_type_SocketAddress(iv, p_dest, NULL, &error_abort); 12052a8e21c7SDaniel P. Berrange qmp_input_visitor_cleanup(qiv); 12062a8e21c7SDaniel P. Berrange qobject_decref(obj); 12072a8e21c7SDaniel P. Berrange } 1208