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" 28baacf047SPaolo Bonzini 29baacf047SPaolo Bonzini #ifndef AI_ADDRCONFIG 30baacf047SPaolo Bonzini # define AI_ADDRCONFIG 0 31baacf047SPaolo Bonzini #endif 323de3d698SWolfgang Bumiller #ifndef AI_V4MAPPED 333de3d698SWolfgang Bumiller # define AI_V4MAPPED 0 343de3d698SWolfgang Bumiller #endif 35baacf047SPaolo Bonzini 36e62be888SKevin Wolf /* used temporarily until all users are converted to QemuOpts */ 37e62be888SKevin Wolf QemuOptsList socket_optslist = { 38e62be888SKevin Wolf .name = "socket", 39e62be888SKevin Wolf .head = QTAILQ_HEAD_INITIALIZER(socket_optslist.head), 40baacf047SPaolo Bonzini .desc = { 41baacf047SPaolo Bonzini { 42baacf047SPaolo Bonzini .name = "path", 43baacf047SPaolo Bonzini .type = QEMU_OPT_STRING, 44baacf047SPaolo Bonzini },{ 45baacf047SPaolo Bonzini .name = "host", 46baacf047SPaolo Bonzini .type = QEMU_OPT_STRING, 47baacf047SPaolo Bonzini },{ 48baacf047SPaolo Bonzini .name = "port", 49baacf047SPaolo Bonzini .type = QEMU_OPT_STRING, 50baacf047SPaolo Bonzini },{ 51b8981dc9SPeter Krempa .name = "localaddr", 52b8981dc9SPeter Krempa .type = QEMU_OPT_STRING, 53b8981dc9SPeter Krempa },{ 54b8981dc9SPeter Krempa .name = "localport", 55b8981dc9SPeter Krempa .type = QEMU_OPT_STRING, 56b8981dc9SPeter Krempa },{ 57baacf047SPaolo Bonzini .name = "to", 58baacf047SPaolo Bonzini .type = QEMU_OPT_NUMBER, 59baacf047SPaolo Bonzini },{ 60baacf047SPaolo Bonzini .name = "ipv4", 61baacf047SPaolo Bonzini .type = QEMU_OPT_BOOL, 62baacf047SPaolo Bonzini },{ 63baacf047SPaolo Bonzini .name = "ipv6", 64baacf047SPaolo Bonzini .type = QEMU_OPT_BOOL, 65baacf047SPaolo Bonzini }, 66baacf047SPaolo Bonzini { /* end if list */ } 67baacf047SPaolo Bonzini }, 68baacf047SPaolo Bonzini }; 69baacf047SPaolo Bonzini 70baacf047SPaolo Bonzini static int inet_getport(struct addrinfo *e) 71baacf047SPaolo Bonzini { 72baacf047SPaolo Bonzini struct sockaddr_in *i4; 73baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 74baacf047SPaolo Bonzini 75baacf047SPaolo Bonzini switch (e->ai_family) { 76baacf047SPaolo Bonzini case PF_INET6: 77baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 78baacf047SPaolo Bonzini return ntohs(i6->sin6_port); 79baacf047SPaolo Bonzini case PF_INET: 80baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 81baacf047SPaolo Bonzini return ntohs(i4->sin_port); 82baacf047SPaolo Bonzini default: 83baacf047SPaolo Bonzini return 0; 84baacf047SPaolo Bonzini } 85baacf047SPaolo Bonzini } 86baacf047SPaolo Bonzini 87baacf047SPaolo Bonzini static void inet_setport(struct addrinfo *e, int port) 88baacf047SPaolo Bonzini { 89baacf047SPaolo Bonzini struct sockaddr_in *i4; 90baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 91baacf047SPaolo Bonzini 92baacf047SPaolo Bonzini switch (e->ai_family) { 93baacf047SPaolo Bonzini case PF_INET6: 94baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 95baacf047SPaolo Bonzini i6->sin6_port = htons(port); 96baacf047SPaolo Bonzini break; 97baacf047SPaolo Bonzini case PF_INET: 98baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 99baacf047SPaolo Bonzini i4->sin_port = htons(port); 100baacf047SPaolo Bonzini break; 101baacf047SPaolo Bonzini } 102baacf047SPaolo Bonzini } 103baacf047SPaolo Bonzini 104a589569fSWenchao Xia NetworkAddressFamily inet_netfamily(int family) 105a589569fSWenchao Xia { 106a589569fSWenchao Xia switch (family) { 107a589569fSWenchao Xia case PF_INET6: return NETWORK_ADDRESS_FAMILY_IPV6; 108a589569fSWenchao Xia case PF_INET: return NETWORK_ADDRESS_FAMILY_IPV4; 109a589569fSWenchao Xia case PF_UNIX: return NETWORK_ADDRESS_FAMILY_UNIX; 110a589569fSWenchao Xia } 111a589569fSWenchao Xia return NETWORK_ADDRESS_FAMILY_UNKNOWN; 112a589569fSWenchao Xia } 113a589569fSWenchao Xia 114baacf047SPaolo Bonzini int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp) 115baacf047SPaolo Bonzini { 116baacf047SPaolo Bonzini struct addrinfo ai,*res,*e; 117baacf047SPaolo Bonzini const char *addr; 118baacf047SPaolo Bonzini char port[33]; 119baacf047SPaolo Bonzini char uaddr[INET6_ADDRSTRLEN+1]; 120baacf047SPaolo Bonzini char uport[33]; 121baacf047SPaolo Bonzini int slisten, rc, to, port_min, port_max, p; 122baacf047SPaolo Bonzini 123baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 1243de3d698SWolfgang Bumiller ai.ai_flags = AI_PASSIVE; 125baacf047SPaolo Bonzini ai.ai_family = PF_UNSPEC; 126baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 127baacf047SPaolo Bonzini 128baacf047SPaolo Bonzini if ((qemu_opt_get(opts, "host") == NULL) || 129baacf047SPaolo Bonzini (qemu_opt_get(opts, "port") == NULL)) { 130baacf047SPaolo Bonzini error_setg(errp, "host and/or port not specified"); 131baacf047SPaolo Bonzini return -1; 132baacf047SPaolo Bonzini } 133baacf047SPaolo Bonzini pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port")); 134baacf047SPaolo Bonzini addr = qemu_opt_get(opts, "host"); 135baacf047SPaolo Bonzini 136baacf047SPaolo Bonzini to = qemu_opt_get_number(opts, "to", 0); 137baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv4", 0)) 138baacf047SPaolo Bonzini ai.ai_family = PF_INET; 139baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv6", 0)) 140baacf047SPaolo Bonzini ai.ai_family = PF_INET6; 141baacf047SPaolo Bonzini 142baacf047SPaolo Bonzini /* lookup */ 1438bc89127SGerd Hoffmann if (port_offset) { 1448bc89127SGerd Hoffmann unsigned long long baseport; 1458bc89127SGerd Hoffmann if (parse_uint_full(port, &baseport, 10) < 0) { 1468bc89127SGerd Hoffmann error_setg(errp, "can't convert to a number: %s", port); 1478bc89127SGerd Hoffmann return -1; 1488bc89127SGerd Hoffmann } 1498bc89127SGerd Hoffmann if (baseport > 65535 || 1508bc89127SGerd Hoffmann baseport + port_offset > 65535) { 1518bc89127SGerd Hoffmann error_setg(errp, "port %s out of range", port); 1528bc89127SGerd Hoffmann return -1; 1538bc89127SGerd Hoffmann } 1548bc89127SGerd Hoffmann snprintf(port, sizeof(port), "%d", (int)baseport + port_offset); 1558bc89127SGerd Hoffmann } 156baacf047SPaolo Bonzini rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res); 157baacf047SPaolo Bonzini if (rc != 0) { 158baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 159baacf047SPaolo Bonzini gai_strerror(rc)); 160baacf047SPaolo Bonzini return -1; 161baacf047SPaolo Bonzini } 162baacf047SPaolo Bonzini 163baacf047SPaolo Bonzini /* create socket + bind */ 164baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 165baacf047SPaolo Bonzini getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, 166baacf047SPaolo Bonzini uaddr,INET6_ADDRSTRLEN,uport,32, 167baacf047SPaolo Bonzini NI_NUMERICHOST | NI_NUMERICSERV); 168baacf047SPaolo Bonzini slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); 169baacf047SPaolo Bonzini if (slisten < 0) { 170baacf047SPaolo Bonzini if (!e->ai_next) { 171235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 172baacf047SPaolo Bonzini } 173baacf047SPaolo Bonzini continue; 174baacf047SPaolo Bonzini } 175baacf047SPaolo Bonzini 17604fd1c78SSebastian Ottlik socket_set_fast_reuse(slisten); 177baacf047SPaolo Bonzini #ifdef IPV6_V6ONLY 178baacf047SPaolo Bonzini if (e->ai_family == PF_INET6) { 179baacf047SPaolo Bonzini /* listen on both ipv4 and ipv6 */ 180f9b5426fSPeter Maydell const int off = 0; 1819957fc7fSStefan Weil qemu_setsockopt(slisten, IPPROTO_IPV6, IPV6_V6ONLY, &off, 182baacf047SPaolo Bonzini sizeof(off)); 183baacf047SPaolo Bonzini } 184baacf047SPaolo Bonzini #endif 185baacf047SPaolo Bonzini 186baacf047SPaolo Bonzini port_min = inet_getport(e); 187baacf047SPaolo Bonzini port_max = to ? to + port_offset : port_min; 188baacf047SPaolo Bonzini for (p = port_min; p <= port_max; p++) { 189baacf047SPaolo Bonzini inet_setport(e, p); 190baacf047SPaolo Bonzini if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) { 191baacf047SPaolo Bonzini goto listen; 192baacf047SPaolo Bonzini } 193baacf047SPaolo Bonzini if (p == port_max) { 194baacf047SPaolo Bonzini if (!e->ai_next) { 195235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to bind socket"); 196baacf047SPaolo Bonzini } 197baacf047SPaolo Bonzini } 198baacf047SPaolo Bonzini } 199baacf047SPaolo Bonzini closesocket(slisten); 200baacf047SPaolo Bonzini } 201baacf047SPaolo Bonzini freeaddrinfo(res); 202baacf047SPaolo Bonzini return -1; 203baacf047SPaolo Bonzini 204baacf047SPaolo Bonzini listen: 205baacf047SPaolo Bonzini if (listen(slisten,1) != 0) { 206235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to listen on socket"); 207baacf047SPaolo Bonzini closesocket(slisten); 208baacf047SPaolo Bonzini freeaddrinfo(res); 209baacf047SPaolo Bonzini return -1; 210baacf047SPaolo Bonzini } 211f43e47dbSMarkus Armbruster qemu_opt_set(opts, "host", uaddr, &error_abort); 21262b3de69SMarkus Armbruster qemu_opt_set_number(opts, "port", inet_getport(e) - port_offset, 213f43e47dbSMarkus Armbruster &error_abort); 21462b3de69SMarkus Armbruster qemu_opt_set_bool(opts, "ipv6", e->ai_family == PF_INET6, 21562b3de69SMarkus Armbruster &error_abort); 21662b3de69SMarkus Armbruster qemu_opt_set_bool(opts, "ipv4", e->ai_family != PF_INET6, 217f43e47dbSMarkus Armbruster &error_abort); 218baacf047SPaolo Bonzini freeaddrinfo(res); 219baacf047SPaolo Bonzini return slisten; 220baacf047SPaolo Bonzini } 221baacf047SPaolo Bonzini 222baacf047SPaolo Bonzini #ifdef _WIN32 223baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 224baacf047SPaolo Bonzini ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY) 225baacf047SPaolo Bonzini #else 226baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 227baacf047SPaolo Bonzini ((rc) == -EINPROGRESS) 228baacf047SPaolo Bonzini #endif 229baacf047SPaolo Bonzini 230baacf047SPaolo Bonzini /* Struct to store connect state for non blocking connect */ 231baacf047SPaolo Bonzini typedef struct ConnectState { 232baacf047SPaolo Bonzini int fd; 233baacf047SPaolo Bonzini struct addrinfo *addr_list; 234baacf047SPaolo Bonzini struct addrinfo *current_addr; 235baacf047SPaolo Bonzini NonBlockingConnectHandler *callback; 236baacf047SPaolo Bonzini void *opaque; 237baacf047SPaolo Bonzini } ConnectState; 238baacf047SPaolo Bonzini 239baacf047SPaolo Bonzini static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, 240baacf047SPaolo Bonzini ConnectState *connect_state, Error **errp); 241baacf047SPaolo Bonzini 242baacf047SPaolo Bonzini static void wait_for_connect(void *opaque) 243baacf047SPaolo Bonzini { 244baacf047SPaolo Bonzini ConnectState *s = opaque; 245baacf047SPaolo Bonzini int val = 0, rc = 0; 246baacf047SPaolo Bonzini socklen_t valsize = sizeof(val); 247baacf047SPaolo Bonzini bool in_progress; 24851795029SCorey Minyard Error *err = NULL; 249baacf047SPaolo Bonzini 25082e1cc4bSFam Zheng qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 251baacf047SPaolo Bonzini 252baacf047SPaolo Bonzini do { 2539957fc7fSStefan Weil rc = qemu_getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize); 254baacf047SPaolo Bonzini } while (rc == -1 && socket_error() == EINTR); 255baacf047SPaolo Bonzini 256baacf047SPaolo Bonzini /* update rc to contain error */ 257baacf047SPaolo Bonzini if (!rc && val) { 258baacf047SPaolo Bonzini rc = -1; 25951795029SCorey Minyard errno = val; 260baacf047SPaolo Bonzini } 261baacf047SPaolo Bonzini 262baacf047SPaolo Bonzini /* connect error */ 263baacf047SPaolo Bonzini if (rc < 0) { 26451795029SCorey Minyard error_setg_errno(&err, errno, "Error connecting to socket"); 265baacf047SPaolo Bonzini closesocket(s->fd); 266baacf047SPaolo Bonzini s->fd = rc; 267baacf047SPaolo Bonzini } 268baacf047SPaolo Bonzini 269baacf047SPaolo Bonzini /* try to connect to the next address on the list */ 270baacf047SPaolo Bonzini if (s->current_addr) { 271baacf047SPaolo Bonzini while (s->current_addr->ai_next != NULL && s->fd < 0) { 272baacf047SPaolo Bonzini s->current_addr = s->current_addr->ai_next; 273baacf047SPaolo Bonzini s->fd = inet_connect_addr(s->current_addr, &in_progress, s, NULL); 27451795029SCorey Minyard if (s->fd < 0) { 27551795029SCorey Minyard error_free(err); 27651795029SCorey Minyard err = NULL; 27751795029SCorey Minyard error_setg_errno(&err, errno, "Unable to start socket connect"); 27851795029SCorey Minyard } 279baacf047SPaolo Bonzini /* connect in progress */ 280baacf047SPaolo Bonzini if (in_progress) { 28151795029SCorey Minyard goto out; 282baacf047SPaolo Bonzini } 283baacf047SPaolo Bonzini } 284baacf047SPaolo Bonzini 285baacf047SPaolo Bonzini freeaddrinfo(s->addr_list); 286baacf047SPaolo Bonzini } 287baacf047SPaolo Bonzini 288baacf047SPaolo Bonzini if (s->callback) { 28951795029SCorey Minyard s->callback(s->fd, err, s->opaque); 290baacf047SPaolo Bonzini } 291baacf047SPaolo Bonzini g_free(s); 29251795029SCorey Minyard out: 29351795029SCorey Minyard error_free(err); 294baacf047SPaolo Bonzini } 295baacf047SPaolo Bonzini 296baacf047SPaolo Bonzini static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, 297baacf047SPaolo Bonzini ConnectState *connect_state, Error **errp) 298baacf047SPaolo Bonzini { 299baacf047SPaolo Bonzini int sock, rc; 300baacf047SPaolo Bonzini 301baacf047SPaolo Bonzini *in_progress = false; 302baacf047SPaolo Bonzini 303baacf047SPaolo Bonzini sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); 304baacf047SPaolo Bonzini if (sock < 0) { 305235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 306baacf047SPaolo Bonzini return -1; 307baacf047SPaolo Bonzini } 30804fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 309baacf047SPaolo Bonzini if (connect_state != NULL) { 310f9e8caccSStefan Hajnoczi qemu_set_nonblock(sock); 311baacf047SPaolo Bonzini } 312baacf047SPaolo Bonzini /* connect to peer */ 313baacf047SPaolo Bonzini do { 314baacf047SPaolo Bonzini rc = 0; 315baacf047SPaolo Bonzini if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) { 316baacf047SPaolo Bonzini rc = -socket_error(); 317baacf047SPaolo Bonzini } 318baacf047SPaolo Bonzini } while (rc == -EINTR); 319baacf047SPaolo Bonzini 320baacf047SPaolo Bonzini if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 321baacf047SPaolo Bonzini connect_state->fd = sock; 32282e1cc4bSFam Zheng qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state); 323baacf047SPaolo Bonzini *in_progress = true; 324baacf047SPaolo Bonzini } else if (rc < 0) { 325235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to connect socket"); 326baacf047SPaolo Bonzini closesocket(sock); 327baacf047SPaolo Bonzini return -1; 328baacf047SPaolo Bonzini } 329baacf047SPaolo Bonzini return sock; 330baacf047SPaolo Bonzini } 331baacf047SPaolo Bonzini 332baacf047SPaolo Bonzini static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp) 333baacf047SPaolo Bonzini { 334baacf047SPaolo Bonzini struct addrinfo ai, *res; 335baacf047SPaolo Bonzini int rc; 336baacf047SPaolo Bonzini const char *addr; 337baacf047SPaolo Bonzini const char *port; 338baacf047SPaolo Bonzini 339baacf047SPaolo Bonzini memset(&ai, 0, sizeof(ai)); 340baacf047SPaolo Bonzini 3413de3d698SWolfgang Bumiller ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG; 342baacf047SPaolo Bonzini ai.ai_family = PF_UNSPEC; 343baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 344baacf047SPaolo Bonzini 345baacf047SPaolo Bonzini addr = qemu_opt_get(opts, "host"); 346baacf047SPaolo Bonzini port = qemu_opt_get(opts, "port"); 347baacf047SPaolo Bonzini if (addr == NULL || port == NULL) { 348baacf047SPaolo Bonzini error_setg(errp, "host and/or port not specified"); 349baacf047SPaolo Bonzini return NULL; 350baacf047SPaolo Bonzini } 351baacf047SPaolo Bonzini 352baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv4", 0)) { 353baacf047SPaolo Bonzini ai.ai_family = PF_INET; 354baacf047SPaolo Bonzini } 355baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv6", 0)) { 356baacf047SPaolo Bonzini ai.ai_family = PF_INET6; 357baacf047SPaolo Bonzini } 358baacf047SPaolo Bonzini 359baacf047SPaolo Bonzini /* lookup */ 360baacf047SPaolo Bonzini rc = getaddrinfo(addr, port, &ai, &res); 361baacf047SPaolo Bonzini if (rc != 0) { 362baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 363baacf047SPaolo Bonzini gai_strerror(rc)); 364baacf047SPaolo Bonzini return NULL; 365baacf047SPaolo Bonzini } 366baacf047SPaolo Bonzini return res; 367baacf047SPaolo Bonzini } 368baacf047SPaolo Bonzini 369baacf047SPaolo Bonzini /** 370baacf047SPaolo Bonzini * Create a socket and connect it to an address. 371baacf047SPaolo Bonzini * 372baacf047SPaolo Bonzini * @opts: QEMU options, recognized parameters strings "host" and "port", 373baacf047SPaolo Bonzini * bools "ipv4" and "ipv6". 374baacf047SPaolo Bonzini * @errp: set on error 375baacf047SPaolo Bonzini * @callback: callback function for non-blocking connect 376baacf047SPaolo Bonzini * @opaque: opaque for callback function 377baacf047SPaolo Bonzini * 378baacf047SPaolo Bonzini * Returns: -1 on error, file descriptor on success. 379baacf047SPaolo Bonzini * 380baacf047SPaolo Bonzini * If @callback is non-null, the connect is non-blocking. If this 381baacf047SPaolo Bonzini * function succeeds, callback will be called when the connection 382baacf047SPaolo Bonzini * completes, with the file descriptor on success, or -1 on error. 383baacf047SPaolo Bonzini */ 384baacf047SPaolo Bonzini int inet_connect_opts(QemuOpts *opts, Error **errp, 385baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 386baacf047SPaolo Bonzini { 3873f9286b7SMarkus Armbruster Error *local_err = NULL; 388baacf047SPaolo Bonzini struct addrinfo *res, *e; 389baacf047SPaolo Bonzini int sock = -1; 390baacf047SPaolo Bonzini bool in_progress; 391baacf047SPaolo Bonzini ConnectState *connect_state = NULL; 392baacf047SPaolo Bonzini 393baacf047SPaolo Bonzini res = inet_parse_connect_opts(opts, errp); 394baacf047SPaolo Bonzini if (!res) { 395baacf047SPaolo Bonzini return -1; 396baacf047SPaolo Bonzini } 397baacf047SPaolo Bonzini 398baacf047SPaolo Bonzini if (callback != NULL) { 399baacf047SPaolo Bonzini connect_state = g_malloc0(sizeof(*connect_state)); 400baacf047SPaolo Bonzini connect_state->addr_list = res; 401baacf047SPaolo Bonzini connect_state->callback = callback; 402baacf047SPaolo Bonzini connect_state->opaque = opaque; 403baacf047SPaolo Bonzini } 404baacf047SPaolo Bonzini 405baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 4063f9286b7SMarkus Armbruster error_free(local_err); 4073f9286b7SMarkus Armbruster local_err = NULL; 408baacf047SPaolo Bonzini if (connect_state != NULL) { 409baacf047SPaolo Bonzini connect_state->current_addr = e; 410baacf047SPaolo Bonzini } 4113f9286b7SMarkus Armbruster sock = inet_connect_addr(e, &in_progress, connect_state, &local_err); 4123f9286b7SMarkus Armbruster if (sock >= 0) { 413baacf047SPaolo Bonzini break; 414baacf047SPaolo Bonzini } 415baacf047SPaolo Bonzini } 4163f9286b7SMarkus Armbruster 4173f9286b7SMarkus Armbruster if (sock < 0) { 4183f9286b7SMarkus Armbruster error_propagate(errp, local_err); 4193f9286b7SMarkus Armbruster } else if (in_progress) { 4203f9286b7SMarkus Armbruster /* wait_for_connect() will do the rest */ 4213f9286b7SMarkus Armbruster return sock; 4223f9286b7SMarkus Armbruster } else { 4233f9286b7SMarkus Armbruster if (callback) { 42451795029SCorey Minyard callback(sock, NULL, opaque); 4253f9286b7SMarkus Armbruster } 4263f9286b7SMarkus Armbruster } 427baacf047SPaolo Bonzini g_free(connect_state); 428baacf047SPaolo Bonzini freeaddrinfo(res); 429baacf047SPaolo Bonzini return sock; 430baacf047SPaolo Bonzini } 431baacf047SPaolo Bonzini 432baacf047SPaolo Bonzini int inet_dgram_opts(QemuOpts *opts, Error **errp) 433baacf047SPaolo Bonzini { 434baacf047SPaolo Bonzini struct addrinfo ai, *peer = NULL, *local = NULL; 435baacf047SPaolo Bonzini const char *addr; 436baacf047SPaolo Bonzini const char *port; 437baacf047SPaolo Bonzini int sock = -1, rc; 438baacf047SPaolo Bonzini 439baacf047SPaolo Bonzini /* lookup peer addr */ 440baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 4413de3d698SWolfgang Bumiller ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG; 442baacf047SPaolo Bonzini ai.ai_family = PF_UNSPEC; 443baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 444baacf047SPaolo Bonzini 445baacf047SPaolo Bonzini addr = qemu_opt_get(opts, "host"); 446baacf047SPaolo Bonzini port = qemu_opt_get(opts, "port"); 447baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 448baacf047SPaolo Bonzini addr = "localhost"; 449baacf047SPaolo Bonzini } 450baacf047SPaolo Bonzini if (port == NULL || strlen(port) == 0) { 451baacf047SPaolo Bonzini error_setg(errp, "remote port not specified"); 452baacf047SPaolo Bonzini return -1; 453baacf047SPaolo Bonzini } 454baacf047SPaolo Bonzini 455baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv4", 0)) 456baacf047SPaolo Bonzini ai.ai_family = PF_INET; 457baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv6", 0)) 458baacf047SPaolo Bonzini ai.ai_family = PF_INET6; 459baacf047SPaolo Bonzini 460baacf047SPaolo Bonzini if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) { 461baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 462baacf047SPaolo Bonzini gai_strerror(rc)); 463baacf047SPaolo Bonzini return -1; 464baacf047SPaolo Bonzini } 465baacf047SPaolo Bonzini 466baacf047SPaolo Bonzini /* lookup local addr */ 467baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 468baacf047SPaolo Bonzini ai.ai_flags = AI_PASSIVE; 469baacf047SPaolo Bonzini ai.ai_family = peer->ai_family; 470baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 471baacf047SPaolo Bonzini 472baacf047SPaolo Bonzini addr = qemu_opt_get(opts, "localaddr"); 473baacf047SPaolo Bonzini port = qemu_opt_get(opts, "localport"); 474baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 475baacf047SPaolo Bonzini addr = NULL; 476baacf047SPaolo Bonzini } 477baacf047SPaolo Bonzini if (!port || strlen(port) == 0) 478baacf047SPaolo Bonzini port = "0"; 479baacf047SPaolo Bonzini 480baacf047SPaolo Bonzini if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) { 481baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 482baacf047SPaolo Bonzini gai_strerror(rc)); 483baacf047SPaolo Bonzini goto err; 484baacf047SPaolo Bonzini } 485baacf047SPaolo Bonzini 486baacf047SPaolo Bonzini /* create socket */ 487baacf047SPaolo Bonzini sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); 488baacf047SPaolo Bonzini if (sock < 0) { 489235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 490baacf047SPaolo Bonzini goto err; 491baacf047SPaolo Bonzini } 49204fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 493baacf047SPaolo Bonzini 494baacf047SPaolo Bonzini /* bind socket */ 495baacf047SPaolo Bonzini if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { 496235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to bind socket"); 497baacf047SPaolo Bonzini goto err; 498baacf047SPaolo Bonzini } 499baacf047SPaolo Bonzini 500baacf047SPaolo Bonzini /* connect to peer */ 501baacf047SPaolo Bonzini if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { 502235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to connect socket"); 503baacf047SPaolo Bonzini goto err; 504baacf047SPaolo Bonzini } 505baacf047SPaolo Bonzini 506baacf047SPaolo Bonzini freeaddrinfo(local); 507baacf047SPaolo Bonzini freeaddrinfo(peer); 508baacf047SPaolo Bonzini return sock; 509baacf047SPaolo Bonzini 510baacf047SPaolo Bonzini err: 511baacf047SPaolo Bonzini if (-1 != sock) 512baacf047SPaolo Bonzini closesocket(sock); 513baacf047SPaolo Bonzini if (local) 514baacf047SPaolo Bonzini freeaddrinfo(local); 515baacf047SPaolo Bonzini if (peer) 516baacf047SPaolo Bonzini freeaddrinfo(peer); 517baacf047SPaolo Bonzini return -1; 518baacf047SPaolo Bonzini } 519baacf047SPaolo Bonzini 520baacf047SPaolo Bonzini /* compatibility wrapper */ 521f17c90beSKevin Wolf InetSocketAddress *inet_parse(const char *str, Error **errp) 522baacf047SPaolo Bonzini { 523baacf047SPaolo Bonzini InetSocketAddress *addr; 524baacf047SPaolo Bonzini const char *optstr, *h; 52555a10996SKevin Wolf char host[65]; 526baacf047SPaolo Bonzini char port[33]; 527baacf047SPaolo Bonzini int to; 528baacf047SPaolo Bonzini int pos; 529baacf047SPaolo Bonzini 530baacf047SPaolo Bonzini addr = g_new0(InetSocketAddress, 1); 531baacf047SPaolo Bonzini 532baacf047SPaolo Bonzini /* parse address */ 533baacf047SPaolo Bonzini if (str[0] == ':') { 534baacf047SPaolo Bonzini /* no host given */ 535baacf047SPaolo Bonzini host[0] = '\0'; 536baacf047SPaolo Bonzini if (1 != sscanf(str, ":%32[^,]%n", port, &pos)) { 537baacf047SPaolo Bonzini error_setg(errp, "error parsing port in address '%s'", str); 538baacf047SPaolo Bonzini goto fail; 539baacf047SPaolo Bonzini } 540baacf047SPaolo Bonzini } else if (str[0] == '[') { 541baacf047SPaolo Bonzini /* IPv6 addr */ 542baacf047SPaolo Bonzini if (2 != sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos)) { 543baacf047SPaolo Bonzini error_setg(errp, "error parsing IPv6 address '%s'", str); 544baacf047SPaolo Bonzini goto fail; 545baacf047SPaolo Bonzini } 546baacf047SPaolo Bonzini addr->ipv6 = addr->has_ipv6 = true; 547baacf047SPaolo Bonzini } else { 548391b7b97SJán Tomko /* hostname or IPv4 addr */ 549baacf047SPaolo Bonzini if (2 != sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos)) { 550baacf047SPaolo Bonzini error_setg(errp, "error parsing address '%s'", str); 551baacf047SPaolo Bonzini goto fail; 552baacf047SPaolo Bonzini } 553391b7b97SJán Tomko if (host[strspn(host, "0123456789.")] == '\0') { 554391b7b97SJán Tomko addr->ipv4 = addr->has_ipv4 = true; 555391b7b97SJán Tomko } 556baacf047SPaolo Bonzini } 557baacf047SPaolo Bonzini 558baacf047SPaolo Bonzini addr->host = g_strdup(host); 559baacf047SPaolo Bonzini addr->port = g_strdup(port); 560baacf047SPaolo Bonzini 561baacf047SPaolo Bonzini /* parse options */ 562baacf047SPaolo Bonzini optstr = str + pos; 563baacf047SPaolo Bonzini h = strstr(optstr, ",to="); 564baacf047SPaolo Bonzini if (h) { 565baacf047SPaolo Bonzini h += 4; 566baacf047SPaolo Bonzini if (sscanf(h, "%d%n", &to, &pos) != 1 || 567baacf047SPaolo Bonzini (h[pos] != '\0' && h[pos] != ',')) { 568baacf047SPaolo Bonzini error_setg(errp, "error parsing to= argument"); 569baacf047SPaolo Bonzini goto fail; 570baacf047SPaolo Bonzini } 571baacf047SPaolo Bonzini addr->has_to = true; 572baacf047SPaolo Bonzini addr->to = to; 573baacf047SPaolo Bonzini } 574baacf047SPaolo Bonzini if (strstr(optstr, ",ipv4")) { 575baacf047SPaolo Bonzini addr->ipv4 = addr->has_ipv4 = true; 576baacf047SPaolo Bonzini } 577baacf047SPaolo Bonzini if (strstr(optstr, ",ipv6")) { 578baacf047SPaolo Bonzini addr->ipv6 = addr->has_ipv6 = true; 579baacf047SPaolo Bonzini } 580baacf047SPaolo Bonzini return addr; 581baacf047SPaolo Bonzini 582baacf047SPaolo Bonzini fail: 583baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 584baacf047SPaolo Bonzini return NULL; 585baacf047SPaolo Bonzini } 586baacf047SPaolo Bonzini 587f17c90beSKevin Wolf static void inet_addr_to_opts(QemuOpts *opts, const InetSocketAddress *addr) 588baacf047SPaolo Bonzini { 589b77e7c8eSPaolo Bonzini bool ipv4 = addr->has_ipv4 && addr->ipv4; 590b77e7c8eSPaolo Bonzini bool ipv6 = addr->has_ipv6 && addr->ipv6; 591baacf047SPaolo Bonzini 592b77e7c8eSPaolo Bonzini if (ipv4 || ipv6) { 593cccb7967SMarkus Armbruster qemu_opt_set_bool(opts, "ipv4", ipv4, &error_abort); 594cccb7967SMarkus Armbruster qemu_opt_set_bool(opts, "ipv6", ipv6, &error_abort); 595b77e7c8eSPaolo Bonzini } else if (addr->has_ipv4 || addr->has_ipv6) { 596b77e7c8eSPaolo Bonzini qemu_opt_set_bool(opts, "ipv4", !addr->has_ipv4, &error_abort); 597b77e7c8eSPaolo Bonzini qemu_opt_set_bool(opts, "ipv6", !addr->has_ipv6, &error_abort); 598baacf047SPaolo Bonzini } 599baacf047SPaolo Bonzini if (addr->has_to) { 60062b3de69SMarkus Armbruster qemu_opt_set_number(opts, "to", addr->to, &error_abort); 601baacf047SPaolo Bonzini } 602f43e47dbSMarkus Armbruster qemu_opt_set(opts, "host", addr->host, &error_abort); 603f43e47dbSMarkus Armbruster qemu_opt_set(opts, "port", addr->port, &error_abort); 604baacf047SPaolo Bonzini } 605baacf047SPaolo Bonzini 606baacf047SPaolo Bonzini int inet_listen(const char *str, char *ostr, int olen, 607baacf047SPaolo Bonzini int socktype, int port_offset, Error **errp) 608baacf047SPaolo Bonzini { 609baacf047SPaolo Bonzini QemuOpts *opts; 610baacf047SPaolo Bonzini char *optstr; 611baacf047SPaolo Bonzini int sock = -1; 612baacf047SPaolo Bonzini InetSocketAddress *addr; 613baacf047SPaolo Bonzini 614baacf047SPaolo Bonzini addr = inet_parse(str, errp); 615baacf047SPaolo Bonzini if (addr != NULL) { 61687ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 617baacf047SPaolo Bonzini inet_addr_to_opts(opts, addr); 618baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 619baacf047SPaolo Bonzini sock = inet_listen_opts(opts, port_offset, errp); 620baacf047SPaolo Bonzini if (sock != -1 && ostr) { 621baacf047SPaolo Bonzini optstr = strchr(str, ','); 622baacf047SPaolo Bonzini if (qemu_opt_get_bool(opts, "ipv6", 0)) { 623baacf047SPaolo Bonzini snprintf(ostr, olen, "[%s]:%s%s", 624baacf047SPaolo Bonzini qemu_opt_get(opts, "host"), 625baacf047SPaolo Bonzini qemu_opt_get(opts, "port"), 626baacf047SPaolo Bonzini optstr ? optstr : ""); 627baacf047SPaolo Bonzini } else { 628baacf047SPaolo Bonzini snprintf(ostr, olen, "%s:%s%s", 629baacf047SPaolo Bonzini qemu_opt_get(opts, "host"), 630baacf047SPaolo Bonzini qemu_opt_get(opts, "port"), 631baacf047SPaolo Bonzini optstr ? optstr : ""); 632baacf047SPaolo Bonzini } 633baacf047SPaolo Bonzini } 634baacf047SPaolo Bonzini qemu_opts_del(opts); 635baacf047SPaolo Bonzini } 636baacf047SPaolo Bonzini return sock; 637baacf047SPaolo Bonzini } 638baacf047SPaolo Bonzini 639baacf047SPaolo Bonzini /** 640baacf047SPaolo Bonzini * Create a blocking socket and connect it to an address. 641baacf047SPaolo Bonzini * 642baacf047SPaolo Bonzini * @str: address string 643baacf047SPaolo Bonzini * @errp: set in case of an error 644baacf047SPaolo Bonzini * 645baacf047SPaolo Bonzini * Returns -1 in case of error, file descriptor on success 646baacf047SPaolo Bonzini **/ 647baacf047SPaolo Bonzini int inet_connect(const char *str, Error **errp) 648baacf047SPaolo Bonzini { 649baacf047SPaolo Bonzini QemuOpts *opts; 650baacf047SPaolo Bonzini int sock = -1; 651baacf047SPaolo Bonzini InetSocketAddress *addr; 652baacf047SPaolo Bonzini 653baacf047SPaolo Bonzini addr = inet_parse(str, errp); 654baacf047SPaolo Bonzini if (addr != NULL) { 65587ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 656baacf047SPaolo Bonzini inet_addr_to_opts(opts, addr); 657baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 658baacf047SPaolo Bonzini sock = inet_connect_opts(opts, errp, NULL, NULL); 659baacf047SPaolo Bonzini qemu_opts_del(opts); 660baacf047SPaolo Bonzini } 661baacf047SPaolo Bonzini return sock; 662baacf047SPaolo Bonzini } 663baacf047SPaolo Bonzini 664baacf047SPaolo Bonzini /** 665baacf047SPaolo Bonzini * Create a non-blocking socket and connect it to an address. 666baacf047SPaolo Bonzini * Calls the callback function with fd in case of success or -1 in case of 667baacf047SPaolo Bonzini * error. 668baacf047SPaolo Bonzini * 669baacf047SPaolo Bonzini * @str: address string 670baacf047SPaolo Bonzini * @callback: callback function that is called when connect completes, 671baacf047SPaolo Bonzini * cannot be NULL. 672baacf047SPaolo Bonzini * @opaque: opaque for callback function 673baacf047SPaolo Bonzini * @errp: set in case of an error 674baacf047SPaolo Bonzini * 675baacf047SPaolo Bonzini * Returns: -1 on immediate error, file descriptor on success. 676baacf047SPaolo Bonzini **/ 677baacf047SPaolo Bonzini int inet_nonblocking_connect(const char *str, 678baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, 679baacf047SPaolo Bonzini void *opaque, Error **errp) 680baacf047SPaolo Bonzini { 681baacf047SPaolo Bonzini QemuOpts *opts; 682baacf047SPaolo Bonzini int sock = -1; 683baacf047SPaolo Bonzini InetSocketAddress *addr; 684baacf047SPaolo Bonzini 685baacf047SPaolo Bonzini g_assert(callback != NULL); 686baacf047SPaolo Bonzini 687baacf047SPaolo Bonzini addr = inet_parse(str, errp); 688baacf047SPaolo Bonzini if (addr != NULL) { 68987ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 690baacf047SPaolo Bonzini inet_addr_to_opts(opts, addr); 691baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 692baacf047SPaolo Bonzini sock = inet_connect_opts(opts, errp, callback, opaque); 693baacf047SPaolo Bonzini qemu_opts_del(opts); 694baacf047SPaolo Bonzini } 695baacf047SPaolo Bonzini return sock; 696baacf047SPaolo Bonzini } 697baacf047SPaolo Bonzini 698baacf047SPaolo Bonzini #ifndef _WIN32 699baacf047SPaolo Bonzini 700baacf047SPaolo Bonzini int unix_listen_opts(QemuOpts *opts, Error **errp) 701baacf047SPaolo Bonzini { 702baacf047SPaolo Bonzini struct sockaddr_un un; 703baacf047SPaolo Bonzini const char *path = qemu_opt_get(opts, "path"); 704baacf047SPaolo Bonzini int sock, fd; 705baacf047SPaolo Bonzini 706baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 707baacf047SPaolo Bonzini if (sock < 0) { 708b658c53dSPaolo Bonzini error_setg_errno(errp, errno, "Failed to create Unix socket"); 709baacf047SPaolo Bonzini return -1; 710baacf047SPaolo Bonzini } 711baacf047SPaolo Bonzini 712baacf047SPaolo Bonzini memset(&un, 0, sizeof(un)); 713baacf047SPaolo Bonzini un.sun_family = AF_UNIX; 714baacf047SPaolo Bonzini if (path && strlen(path)) { 715baacf047SPaolo Bonzini snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); 716baacf047SPaolo Bonzini } else { 717b658c53dSPaolo Bonzini const char *tmpdir = getenv("TMPDIR"); 718b658c53dSPaolo Bonzini tmpdir = tmpdir ? tmpdir : "/tmp"; 719b658c53dSPaolo Bonzini if (snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX", 720b658c53dSPaolo Bonzini tmpdir) >= sizeof(un.sun_path)) { 721b658c53dSPaolo Bonzini error_setg_errno(errp, errno, 722b658c53dSPaolo Bonzini "TMPDIR environment variable (%s) too large", tmpdir); 723b658c53dSPaolo Bonzini goto err; 724b658c53dSPaolo Bonzini } 725b658c53dSPaolo Bonzini 726baacf047SPaolo Bonzini /* 727baacf047SPaolo Bonzini * This dummy fd usage silences the mktemp() unsecure warning. 728baacf047SPaolo Bonzini * Using mkstemp() doesn't make things more secure here 729baacf047SPaolo Bonzini * though. bind() complains about existing files, so we have 730baacf047SPaolo Bonzini * to unlink first and thus re-open the race window. The 731baacf047SPaolo Bonzini * worst case possible is bind() failing, i.e. a DoS attack. 732baacf047SPaolo Bonzini */ 733b658c53dSPaolo Bonzini fd = mkstemp(un.sun_path); 734b658c53dSPaolo Bonzini if (fd < 0) { 735b658c53dSPaolo Bonzini error_setg_errno(errp, errno, 736b658c53dSPaolo Bonzini "Failed to make a temporary socket name in %s", tmpdir); 737b658c53dSPaolo Bonzini goto err; 738b658c53dSPaolo Bonzini } 739b658c53dSPaolo Bonzini close(fd); 740f43e47dbSMarkus Armbruster qemu_opt_set(opts, "path", un.sun_path, &error_abort); 741baacf047SPaolo Bonzini } 742baacf047SPaolo Bonzini 7430ef705a2SCole Robinson if ((access(un.sun_path, F_OK) == 0) && 7440ef705a2SCole Robinson unlink(un.sun_path) < 0) { 7450ef705a2SCole Robinson error_setg_errno(errp, errno, 7460ef705a2SCole Robinson "Failed to unlink socket %s", un.sun_path); 7470ef705a2SCole Robinson goto err; 7480ef705a2SCole Robinson } 749baacf047SPaolo Bonzini if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { 750b658c53dSPaolo Bonzini error_setg_errno(errp, errno, "Failed to bind socket to %s", un.sun_path); 751baacf047SPaolo Bonzini goto err; 752baacf047SPaolo Bonzini } 753baacf047SPaolo Bonzini if (listen(sock, 1) < 0) { 754235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to listen on socket"); 755baacf047SPaolo Bonzini goto err; 756baacf047SPaolo Bonzini } 757baacf047SPaolo Bonzini 758baacf047SPaolo Bonzini return sock; 759baacf047SPaolo Bonzini 760baacf047SPaolo Bonzini err: 761baacf047SPaolo Bonzini closesocket(sock); 762baacf047SPaolo Bonzini return -1; 763baacf047SPaolo Bonzini } 764baacf047SPaolo Bonzini 765baacf047SPaolo Bonzini int unix_connect_opts(QemuOpts *opts, Error **errp, 766baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 767baacf047SPaolo Bonzini { 768baacf047SPaolo Bonzini struct sockaddr_un un; 769baacf047SPaolo Bonzini const char *path = qemu_opt_get(opts, "path"); 770baacf047SPaolo Bonzini ConnectState *connect_state = NULL; 771baacf047SPaolo Bonzini int sock, rc; 772baacf047SPaolo Bonzini 7738108fd3eSGonglei if (path == NULL) { 774312fd5f2SMarkus Armbruster error_setg(errp, "unix connect: no path specified"); 775baacf047SPaolo Bonzini return -1; 776baacf047SPaolo Bonzini } 777baacf047SPaolo Bonzini 778baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 779baacf047SPaolo Bonzini if (sock < 0) { 780235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 781baacf047SPaolo Bonzini return -1; 782baacf047SPaolo Bonzini } 783baacf047SPaolo Bonzini if (callback != NULL) { 784baacf047SPaolo Bonzini connect_state = g_malloc0(sizeof(*connect_state)); 785baacf047SPaolo Bonzini connect_state->callback = callback; 786baacf047SPaolo Bonzini connect_state->opaque = opaque; 787f9e8caccSStefan Hajnoczi qemu_set_nonblock(sock); 788baacf047SPaolo Bonzini } 789baacf047SPaolo Bonzini 790baacf047SPaolo Bonzini memset(&un, 0, sizeof(un)); 791baacf047SPaolo Bonzini un.sun_family = AF_UNIX; 792baacf047SPaolo Bonzini snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); 793baacf047SPaolo Bonzini 794baacf047SPaolo Bonzini /* connect to peer */ 795baacf047SPaolo Bonzini do { 796baacf047SPaolo Bonzini rc = 0; 797baacf047SPaolo Bonzini if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { 798baacf047SPaolo Bonzini rc = -socket_error(); 799baacf047SPaolo Bonzini } 800baacf047SPaolo Bonzini } while (rc == -EINTR); 801baacf047SPaolo Bonzini 802baacf047SPaolo Bonzini if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 803baacf047SPaolo Bonzini connect_state->fd = sock; 80482e1cc4bSFam Zheng qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state); 805baacf047SPaolo Bonzini return sock; 806baacf047SPaolo Bonzini } else if (rc >= 0) { 807baacf047SPaolo Bonzini /* non blocking socket immediate success, call callback */ 808baacf047SPaolo Bonzini if (callback != NULL) { 80951795029SCorey Minyard callback(sock, NULL, opaque); 810baacf047SPaolo Bonzini } 811baacf047SPaolo Bonzini } 812baacf047SPaolo Bonzini 813baacf047SPaolo Bonzini if (rc < 0) { 814235256a2SMarkus Armbruster error_setg_errno(errp, -rc, "Failed to connect socket"); 815baacf047SPaolo Bonzini close(sock); 816baacf047SPaolo Bonzini sock = -1; 817baacf047SPaolo Bonzini } 818baacf047SPaolo Bonzini 819baacf047SPaolo Bonzini g_free(connect_state); 820baacf047SPaolo Bonzini return sock; 821baacf047SPaolo Bonzini } 822baacf047SPaolo Bonzini 823baacf047SPaolo Bonzini #else 824baacf047SPaolo Bonzini 825baacf047SPaolo Bonzini int unix_listen_opts(QemuOpts *opts, Error **errp) 826baacf047SPaolo Bonzini { 827baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 828baacf047SPaolo Bonzini errno = ENOTSUP; 829baacf047SPaolo Bonzini return -1; 830baacf047SPaolo Bonzini } 831baacf047SPaolo Bonzini 832baacf047SPaolo Bonzini int unix_connect_opts(QemuOpts *opts, Error **errp, 833baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 834baacf047SPaolo Bonzini { 835baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 836baacf047SPaolo Bonzini errno = ENOTSUP; 837baacf047SPaolo Bonzini return -1; 838baacf047SPaolo Bonzini } 839baacf047SPaolo Bonzini #endif 840baacf047SPaolo Bonzini 841baacf047SPaolo Bonzini /* compatibility wrapper */ 842baacf047SPaolo Bonzini int unix_listen(const char *str, char *ostr, int olen, Error **errp) 843baacf047SPaolo Bonzini { 844baacf047SPaolo Bonzini QemuOpts *opts; 845baacf047SPaolo Bonzini char *path, *optstr; 846baacf047SPaolo Bonzini int sock, len; 847baacf047SPaolo Bonzini 84887ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 849baacf047SPaolo Bonzini 850baacf047SPaolo Bonzini optstr = strchr(str, ','); 851baacf047SPaolo Bonzini if (optstr) { 852baacf047SPaolo Bonzini len = optstr - str; 853baacf047SPaolo Bonzini if (len) { 854baacf047SPaolo Bonzini path = g_malloc(len+1); 855baacf047SPaolo Bonzini snprintf(path, len+1, "%.*s", len, str); 856f43e47dbSMarkus Armbruster qemu_opt_set(opts, "path", path, &error_abort); 857baacf047SPaolo Bonzini g_free(path); 858baacf047SPaolo Bonzini } 859baacf047SPaolo Bonzini } else { 860f43e47dbSMarkus Armbruster qemu_opt_set(opts, "path", str, &error_abort); 861baacf047SPaolo Bonzini } 862baacf047SPaolo Bonzini 863baacf047SPaolo Bonzini sock = unix_listen_opts(opts, errp); 864baacf047SPaolo Bonzini 865baacf047SPaolo Bonzini if (sock != -1 && ostr) 866baacf047SPaolo Bonzini snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : ""); 867baacf047SPaolo Bonzini qemu_opts_del(opts); 868baacf047SPaolo Bonzini return sock; 869baacf047SPaolo Bonzini } 870baacf047SPaolo Bonzini 871baacf047SPaolo Bonzini int unix_connect(const char *path, Error **errp) 872baacf047SPaolo Bonzini { 873baacf047SPaolo Bonzini QemuOpts *opts; 874baacf047SPaolo Bonzini int sock; 875baacf047SPaolo Bonzini 87687ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 877f43e47dbSMarkus Armbruster qemu_opt_set(opts, "path", path, &error_abort); 878baacf047SPaolo Bonzini sock = unix_connect_opts(opts, errp, NULL, NULL); 879baacf047SPaolo Bonzini qemu_opts_del(opts); 880baacf047SPaolo Bonzini return sock; 881baacf047SPaolo Bonzini } 882baacf047SPaolo Bonzini 883baacf047SPaolo Bonzini 884baacf047SPaolo Bonzini int unix_nonblocking_connect(const char *path, 885baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, 886baacf047SPaolo Bonzini void *opaque, Error **errp) 887baacf047SPaolo Bonzini { 888baacf047SPaolo Bonzini QemuOpts *opts; 889baacf047SPaolo Bonzini int sock = -1; 890baacf047SPaolo Bonzini 891baacf047SPaolo Bonzini g_assert(callback != NULL); 892baacf047SPaolo Bonzini 89387ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 894f43e47dbSMarkus Armbruster qemu_opt_set(opts, "path", path, &error_abort); 895baacf047SPaolo Bonzini sock = unix_connect_opts(opts, errp, callback, opaque); 896baacf047SPaolo Bonzini qemu_opts_del(opts); 897baacf047SPaolo Bonzini return sock; 898baacf047SPaolo Bonzini } 899baacf047SPaolo Bonzini 900baacf047SPaolo Bonzini SocketAddress *socket_parse(const char *str, Error **errp) 901baacf047SPaolo Bonzini { 902afde3f8bSGerd Hoffmann SocketAddress *addr; 903baacf047SPaolo Bonzini 904afde3f8bSGerd Hoffmann addr = g_new0(SocketAddress, 1); 905baacf047SPaolo Bonzini if (strstart(str, "unix:", NULL)) { 906baacf047SPaolo Bonzini if (str[5] == '\0') { 907312fd5f2SMarkus Armbruster error_setg(errp, "invalid Unix socket address"); 908baacf047SPaolo Bonzini goto fail; 909baacf047SPaolo Bonzini } else { 910baacf047SPaolo Bonzini addr->kind = SOCKET_ADDRESS_KIND_UNIX; 911baacf047SPaolo Bonzini addr->q_unix = g_new(UnixSocketAddress, 1); 912baacf047SPaolo Bonzini addr->q_unix->path = g_strdup(str + 5); 913baacf047SPaolo Bonzini } 914baacf047SPaolo Bonzini } else if (strstart(str, "fd:", NULL)) { 915baacf047SPaolo Bonzini if (str[3] == '\0') { 916312fd5f2SMarkus Armbruster error_setg(errp, "invalid file descriptor address"); 917baacf047SPaolo Bonzini goto fail; 918baacf047SPaolo Bonzini } else { 919baacf047SPaolo Bonzini addr->kind = SOCKET_ADDRESS_KIND_FD; 920baacf047SPaolo Bonzini addr->fd = g_new(String, 1); 921baacf047SPaolo Bonzini addr->fd->str = g_strdup(str + 3); 922baacf047SPaolo Bonzini } 923baacf047SPaolo Bonzini } else { 924baacf047SPaolo Bonzini addr->kind = SOCKET_ADDRESS_KIND_INET; 925baacf047SPaolo Bonzini addr->inet = inet_parse(str, errp); 926baacf047SPaolo Bonzini if (addr->inet == NULL) { 927baacf047SPaolo Bonzini goto fail; 928baacf047SPaolo Bonzini } 929baacf047SPaolo Bonzini } 930baacf047SPaolo Bonzini return addr; 931baacf047SPaolo Bonzini 932baacf047SPaolo Bonzini fail: 933baacf047SPaolo Bonzini qapi_free_SocketAddress(addr); 934baacf047SPaolo Bonzini return NULL; 935baacf047SPaolo Bonzini } 936baacf047SPaolo Bonzini 937baacf047SPaolo Bonzini int socket_connect(SocketAddress *addr, Error **errp, 938baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 939baacf047SPaolo Bonzini { 940baacf047SPaolo Bonzini QemuOpts *opts; 941baacf047SPaolo Bonzini int fd; 942baacf047SPaolo Bonzini 94387ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 944baacf047SPaolo Bonzini switch (addr->kind) { 945baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_INET: 946baacf047SPaolo Bonzini inet_addr_to_opts(opts, addr->inet); 947baacf047SPaolo Bonzini fd = inet_connect_opts(opts, errp, callback, opaque); 948baacf047SPaolo Bonzini break; 949baacf047SPaolo Bonzini 950baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_UNIX: 951f43e47dbSMarkus Armbruster qemu_opt_set(opts, "path", addr->q_unix->path, &error_abort); 952baacf047SPaolo Bonzini fd = unix_connect_opts(opts, errp, callback, opaque); 953baacf047SPaolo Bonzini break; 954baacf047SPaolo Bonzini 955baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_FD: 956baacf047SPaolo Bonzini fd = monitor_get_fd(cur_mon, addr->fd->str, errp); 957d1ec72a4SGerd Hoffmann if (fd >= 0 && callback) { 9581a751ebfSStefan Hajnoczi qemu_set_nonblock(fd); 95951795029SCorey Minyard callback(fd, NULL, opaque); 960baacf047SPaolo Bonzini } 961baacf047SPaolo Bonzini break; 962baacf047SPaolo Bonzini 963baacf047SPaolo Bonzini default: 964baacf047SPaolo Bonzini abort(); 965baacf047SPaolo Bonzini } 966baacf047SPaolo Bonzini qemu_opts_del(opts); 967baacf047SPaolo Bonzini return fd; 968baacf047SPaolo Bonzini } 969baacf047SPaolo Bonzini 970baacf047SPaolo Bonzini int socket_listen(SocketAddress *addr, Error **errp) 971baacf047SPaolo Bonzini { 972baacf047SPaolo Bonzini QemuOpts *opts; 973baacf047SPaolo Bonzini int fd; 974baacf047SPaolo Bonzini 97587ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 976baacf047SPaolo Bonzini switch (addr->kind) { 977baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_INET: 978baacf047SPaolo Bonzini inet_addr_to_opts(opts, addr->inet); 979baacf047SPaolo Bonzini fd = inet_listen_opts(opts, 0, errp); 980baacf047SPaolo Bonzini break; 981baacf047SPaolo Bonzini 982baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_UNIX: 983f43e47dbSMarkus Armbruster qemu_opt_set(opts, "path", addr->q_unix->path, &error_abort); 984baacf047SPaolo Bonzini fd = unix_listen_opts(opts, errp); 985baacf047SPaolo Bonzini break; 986baacf047SPaolo Bonzini 987baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_FD: 988baacf047SPaolo Bonzini fd = monitor_get_fd(cur_mon, addr->fd->str, errp); 989baacf047SPaolo Bonzini break; 990baacf047SPaolo Bonzini 991baacf047SPaolo Bonzini default: 992baacf047SPaolo Bonzini abort(); 993baacf047SPaolo Bonzini } 994baacf047SPaolo Bonzini qemu_opts_del(opts); 995baacf047SPaolo Bonzini return fd; 996baacf047SPaolo Bonzini } 997baacf047SPaolo Bonzini 9983ecc059dSGerd Hoffmann int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp) 9993ecc059dSGerd Hoffmann { 10003ecc059dSGerd Hoffmann QemuOpts *opts; 10013ecc059dSGerd Hoffmann int fd; 10023ecc059dSGerd Hoffmann 100387ea75d5SPeter Crosthwaite opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 10043ecc059dSGerd Hoffmann switch (remote->kind) { 10053ecc059dSGerd Hoffmann case SOCKET_ADDRESS_KIND_INET: 10068287fea3SPeter Maydell inet_addr_to_opts(opts, remote->inet); 10073ecc059dSGerd Hoffmann if (local) { 1008f43e47dbSMarkus Armbruster qemu_opt_set(opts, "localaddr", local->inet->host, &error_abort); 1009f43e47dbSMarkus Armbruster qemu_opt_set(opts, "localport", local->inet->port, &error_abort); 10103ecc059dSGerd Hoffmann } 10113ecc059dSGerd Hoffmann fd = inet_dgram_opts(opts, errp); 10123ecc059dSGerd Hoffmann break; 10133ecc059dSGerd Hoffmann 10143ecc059dSGerd Hoffmann default: 10153ecc059dSGerd Hoffmann error_setg(errp, "socket type unsupported for datagram"); 10167a5b6af1SGerd Hoffmann fd = -1; 10173ecc059dSGerd Hoffmann } 10183ecc059dSGerd Hoffmann qemu_opts_del(opts); 10193ecc059dSGerd Hoffmann return fd; 10203ecc059dSGerd Hoffmann } 1021*17c55decSDaniel P. Berrange 1022*17c55decSDaniel P. Berrange 1023*17c55decSDaniel P. Berrange static SocketAddress * 1024*17c55decSDaniel P. Berrange socket_sockaddr_to_address_inet(struct sockaddr_storage *sa, 1025*17c55decSDaniel P. Berrange socklen_t salen, 1026*17c55decSDaniel P. Berrange Error **errp) 1027*17c55decSDaniel P. Berrange { 1028*17c55decSDaniel P. Berrange char host[NI_MAXHOST]; 1029*17c55decSDaniel P. Berrange char serv[NI_MAXSERV]; 1030*17c55decSDaniel P. Berrange SocketAddress *addr; 1031*17c55decSDaniel P. Berrange int ret; 1032*17c55decSDaniel P. Berrange 1033*17c55decSDaniel P. Berrange ret = getnameinfo((struct sockaddr *)sa, salen, 1034*17c55decSDaniel P. Berrange host, sizeof(host), 1035*17c55decSDaniel P. Berrange serv, sizeof(serv), 1036*17c55decSDaniel P. Berrange NI_NUMERICHOST | NI_NUMERICSERV); 1037*17c55decSDaniel P. Berrange if (ret != 0) { 1038*17c55decSDaniel P. Berrange error_setg(errp, "Cannot format numeric socket address: %s", 1039*17c55decSDaniel P. Berrange gai_strerror(ret)); 1040*17c55decSDaniel P. Berrange return NULL; 1041*17c55decSDaniel P. Berrange } 1042*17c55decSDaniel P. Berrange 1043*17c55decSDaniel P. Berrange addr = g_new0(SocketAddress, 1); 1044*17c55decSDaniel P. Berrange addr->kind = SOCKET_ADDRESS_KIND_INET; 1045*17c55decSDaniel P. Berrange addr->inet = g_new0(InetSocketAddress, 1); 1046*17c55decSDaniel P. Berrange addr->inet->host = g_strdup(host); 1047*17c55decSDaniel P. Berrange addr->inet->port = g_strdup(serv); 1048*17c55decSDaniel P. Berrange if (sa->ss_family == AF_INET) { 1049*17c55decSDaniel P. Berrange addr->inet->has_ipv4 = addr->inet->ipv4 = true; 1050*17c55decSDaniel P. Berrange } else { 1051*17c55decSDaniel P. Berrange addr->inet->has_ipv6 = addr->inet->ipv6 = true; 1052*17c55decSDaniel P. Berrange } 1053*17c55decSDaniel P. Berrange 1054*17c55decSDaniel P. Berrange return addr; 1055*17c55decSDaniel P. Berrange } 1056*17c55decSDaniel P. Berrange 1057*17c55decSDaniel P. Berrange 1058*17c55decSDaniel P. Berrange #ifndef WIN32 1059*17c55decSDaniel P. Berrange static SocketAddress * 1060*17c55decSDaniel P. Berrange socket_sockaddr_to_address_unix(struct sockaddr_storage *sa, 1061*17c55decSDaniel P. Berrange socklen_t salen, 1062*17c55decSDaniel P. Berrange Error **errp) 1063*17c55decSDaniel P. Berrange { 1064*17c55decSDaniel P. Berrange SocketAddress *addr; 1065*17c55decSDaniel P. Berrange struct sockaddr_un *su = (struct sockaddr_un *)sa; 1066*17c55decSDaniel P. Berrange 1067*17c55decSDaniel P. Berrange addr = g_new0(SocketAddress, 1); 1068*17c55decSDaniel P. Berrange addr->kind = SOCKET_ADDRESS_KIND_UNIX; 1069*17c55decSDaniel P. Berrange addr->q_unix = g_new0(UnixSocketAddress, 1); 1070*17c55decSDaniel P. Berrange if (su->sun_path[0]) { 1071*17c55decSDaniel P. Berrange addr->q_unix->path = g_strndup(su->sun_path, 1072*17c55decSDaniel P. Berrange sizeof(su->sun_path)); 1073*17c55decSDaniel P. Berrange } 1074*17c55decSDaniel P. Berrange 1075*17c55decSDaniel P. Berrange return addr; 1076*17c55decSDaniel P. Berrange } 1077*17c55decSDaniel P. Berrange #endif /* WIN32 */ 1078*17c55decSDaniel P. Berrange 1079*17c55decSDaniel P. Berrange static SocketAddress * 1080*17c55decSDaniel P. Berrange socket_sockaddr_to_address(struct sockaddr_storage *sa, 1081*17c55decSDaniel P. Berrange socklen_t salen, 1082*17c55decSDaniel P. Berrange Error **errp) 1083*17c55decSDaniel P. Berrange { 1084*17c55decSDaniel P. Berrange switch (sa->ss_family) { 1085*17c55decSDaniel P. Berrange case AF_INET: 1086*17c55decSDaniel P. Berrange case AF_INET6: 1087*17c55decSDaniel P. Berrange return socket_sockaddr_to_address_inet(sa, salen, errp); 1088*17c55decSDaniel P. Berrange 1089*17c55decSDaniel P. Berrange #ifndef WIN32 1090*17c55decSDaniel P. Berrange case AF_UNIX: 1091*17c55decSDaniel P. Berrange return socket_sockaddr_to_address_unix(sa, salen, errp); 1092*17c55decSDaniel P. Berrange #endif /* WIN32 */ 1093*17c55decSDaniel P. Berrange 1094*17c55decSDaniel P. Berrange default: 1095*17c55decSDaniel P. Berrange error_setg(errp, "socket family %d unsupported", 1096*17c55decSDaniel P. Berrange sa->ss_family); 1097*17c55decSDaniel P. Berrange return NULL; 1098*17c55decSDaniel P. Berrange } 1099*17c55decSDaniel P. Berrange return 0; 1100*17c55decSDaniel P. Berrange } 1101*17c55decSDaniel P. Berrange 1102*17c55decSDaniel P. Berrange 1103*17c55decSDaniel P. Berrange SocketAddress *socket_local_address(int fd, Error **errp) 1104*17c55decSDaniel P. Berrange { 1105*17c55decSDaniel P. Berrange struct sockaddr_storage ss; 1106*17c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 1107*17c55decSDaniel P. Berrange 1108*17c55decSDaniel P. Berrange if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) { 1109*17c55decSDaniel P. Berrange error_setg_errno(errp, socket_error(), "%s", 1110*17c55decSDaniel P. Berrange "Unable to query local socket address"); 1111*17c55decSDaniel P. Berrange return NULL; 1112*17c55decSDaniel P. Berrange } 1113*17c55decSDaniel P. Berrange 1114*17c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 1115*17c55decSDaniel P. Berrange } 1116*17c55decSDaniel P. Berrange 1117*17c55decSDaniel P. Berrange 1118*17c55decSDaniel P. Berrange SocketAddress *socket_remote_address(int fd, Error **errp) 1119*17c55decSDaniel P. Berrange { 1120*17c55decSDaniel P. Berrange struct sockaddr_storage ss; 1121*17c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 1122*17c55decSDaniel P. Berrange 1123*17c55decSDaniel P. Berrange if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) { 1124*17c55decSDaniel P. Berrange error_setg_errno(errp, socket_error(), "%s", 1125*17c55decSDaniel P. Berrange "Unable to query remote socket address"); 1126*17c55decSDaniel P. Berrange return NULL; 1127*17c55decSDaniel P. Berrange } 1128*17c55decSDaniel P. Berrange 1129*17c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 1130*17c55decSDaniel P. Berrange } 1131