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 */ 18aafd7584SPeter Maydell #include "qemu/osdep.h" 19baacf047SPaolo Bonzini 20*6a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 21*6a02c806SStefan Hajnoczi #include <linux/vm_sockets.h> 22*6a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 23*6a02c806SStefan Hajnoczi 24baacf047SPaolo Bonzini #include "monitor/monitor.h" 25da34e65cSMarkus Armbruster #include "qapi/error.h" 26baacf047SPaolo Bonzini #include "qemu/sockets.h" 27baacf047SPaolo Bonzini #include "qemu/main-loop.h" 28b3db211fSDaniel P. Berrange #include "qapi/qobject-input-visitor.h" 29b3db211fSDaniel P. Berrange #include "qapi/qobject-output-visitor.h" 302a8e21c7SDaniel P. Berrange #include "qapi-visit.h" 31f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 32baacf047SPaolo Bonzini 33baacf047SPaolo Bonzini #ifndef AI_ADDRCONFIG 34baacf047SPaolo Bonzini # define AI_ADDRCONFIG 0 35baacf047SPaolo Bonzini #endif 36340849a9SDaniel P. Berrange 373de3d698SWolfgang Bumiller #ifndef AI_V4MAPPED 383de3d698SWolfgang Bumiller # define AI_V4MAPPED 0 393de3d698SWolfgang Bumiller #endif 40baacf047SPaolo Bonzini 41baacf047SPaolo Bonzini 42baacf047SPaolo Bonzini static int inet_getport(struct addrinfo *e) 43baacf047SPaolo Bonzini { 44baacf047SPaolo Bonzini struct sockaddr_in *i4; 45baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 46baacf047SPaolo Bonzini 47baacf047SPaolo Bonzini switch (e->ai_family) { 48baacf047SPaolo Bonzini case PF_INET6: 49baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 50baacf047SPaolo Bonzini return ntohs(i6->sin6_port); 51baacf047SPaolo Bonzini case PF_INET: 52baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 53baacf047SPaolo Bonzini return ntohs(i4->sin_port); 54baacf047SPaolo Bonzini default: 55baacf047SPaolo Bonzini return 0; 56baacf047SPaolo Bonzini } 57baacf047SPaolo Bonzini } 58baacf047SPaolo Bonzini 59baacf047SPaolo Bonzini static void inet_setport(struct addrinfo *e, int port) 60baacf047SPaolo Bonzini { 61baacf047SPaolo Bonzini struct sockaddr_in *i4; 62baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 63baacf047SPaolo Bonzini 64baacf047SPaolo Bonzini switch (e->ai_family) { 65baacf047SPaolo Bonzini case PF_INET6: 66baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 67baacf047SPaolo Bonzini i6->sin6_port = htons(port); 68baacf047SPaolo Bonzini break; 69baacf047SPaolo Bonzini case PF_INET: 70baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 71baacf047SPaolo Bonzini i4->sin_port = htons(port); 72baacf047SPaolo Bonzini break; 73baacf047SPaolo Bonzini } 74baacf047SPaolo Bonzini } 75baacf047SPaolo Bonzini 76a589569fSWenchao Xia NetworkAddressFamily inet_netfamily(int family) 77a589569fSWenchao Xia { 78a589569fSWenchao Xia switch (family) { 79a589569fSWenchao Xia case PF_INET6: return NETWORK_ADDRESS_FAMILY_IPV6; 80a589569fSWenchao Xia case PF_INET: return NETWORK_ADDRESS_FAMILY_IPV4; 81a589569fSWenchao Xia case PF_UNIX: return NETWORK_ADDRESS_FAMILY_UNIX; 82*6a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 83*6a02c806SStefan Hajnoczi case PF_VSOCK: return NETWORK_ADDRESS_FAMILY_VSOCK; 84*6a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 85a589569fSWenchao Xia } 86a589569fSWenchao Xia return NETWORK_ADDRESS_FAMILY_UNKNOWN; 87a589569fSWenchao Xia } 88a589569fSWenchao Xia 891856835dSDaniel P. Berrange /* 901856835dSDaniel P. Berrange * Matrix we're trying to apply 911856835dSDaniel P. Berrange * 921856835dSDaniel P. Berrange * ipv4 ipv6 family 931856835dSDaniel P. Berrange * - - PF_UNSPEC 941856835dSDaniel P. Berrange * - f PF_INET 951856835dSDaniel P. Berrange * - t PF_INET6 961856835dSDaniel P. Berrange * f - PF_INET6 971856835dSDaniel P. Berrange * f f <error> 981856835dSDaniel P. Berrange * f t PF_INET6 991856835dSDaniel P. Berrange * t - PF_INET 1001856835dSDaniel P. Berrange * t f PF_INET 1011856835dSDaniel P. Berrange * t t PF_INET6 1021856835dSDaniel P. Berrange * 103d43eda3dSWei Jiangang * NB, this matrix is only about getting the necessary results 1041856835dSDaniel P. Berrange * from getaddrinfo(). Some of the cases require further work 1051856835dSDaniel P. Berrange * after reading results from getaddrinfo in order to fully 1061856835dSDaniel P. Berrange * apply the logic the end user wants. eg with the last case 1071856835dSDaniel P. Berrange * ipv4=t + ipv6=t + PF_INET6, getaddrinfo alone can only 1081856835dSDaniel P. Berrange * guarantee the ipv6=t part of the request - we need more 1091856835dSDaniel P. Berrange * checks to provide ipv4=t part of the guarantee. This is 1101856835dSDaniel P. Berrange * outside scope of this method and not currently handled by 1111856835dSDaniel P. Berrange * callers at all. 1121856835dSDaniel P. Berrange */ 1131856835dSDaniel P. Berrange static int inet_ai_family_from_address(InetSocketAddress *addr, 1141856835dSDaniel P. Berrange Error **errp) 1151856835dSDaniel P. Berrange { 1161856835dSDaniel P. Berrange if (addr->has_ipv6 && addr->has_ipv4 && 1171856835dSDaniel P. Berrange !addr->ipv6 && !addr->ipv4) { 1181856835dSDaniel P. Berrange error_setg(errp, "Cannot disable IPv4 and IPv6 at same time"); 1191856835dSDaniel P. Berrange return PF_UNSPEC; 1201856835dSDaniel P. Berrange } 1211856835dSDaniel P. Berrange if ((addr->has_ipv6 && addr->ipv6) || (addr->has_ipv4 && !addr->ipv4)) { 1221856835dSDaniel P. Berrange return PF_INET6; 1231856835dSDaniel P. Berrange } 1241856835dSDaniel P. Berrange if ((addr->has_ipv4 && addr->ipv4) || (addr->has_ipv6 && !addr->ipv6)) { 1251856835dSDaniel P. Berrange return PF_INET; 1261856835dSDaniel P. Berrange } 1271856835dSDaniel P. Berrange return PF_UNSPEC; 1281856835dSDaniel P. Berrange } 1291856835dSDaniel P. Berrange 1301856835dSDaniel P. Berrange static int inet_listen_saddr(InetSocketAddress *saddr, 1311856835dSDaniel P. Berrange int port_offset, 1321856835dSDaniel P. Berrange bool update_addr, 1331856835dSDaniel P. Berrange Error **errp) 134baacf047SPaolo Bonzini { 135baacf047SPaolo Bonzini struct addrinfo ai,*res,*e; 136baacf047SPaolo Bonzini char port[33]; 137baacf047SPaolo Bonzini char uaddr[INET6_ADDRSTRLEN+1]; 138baacf047SPaolo Bonzini char uport[33]; 1391856835dSDaniel P. Berrange int slisten, rc, port_min, port_max, p; 1401856835dSDaniel P. Berrange Error *err = NULL; 141baacf047SPaolo Bonzini 142baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 1433de3d698SWolfgang Bumiller ai.ai_flags = AI_PASSIVE; 1441856835dSDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(saddr, &err); 145baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 146baacf047SPaolo Bonzini 1471856835dSDaniel P. Berrange if (err) { 1481856835dSDaniel P. Berrange error_propagate(errp, err); 1491856835dSDaniel P. Berrange return -1; 1501856835dSDaniel P. Berrange } 1511856835dSDaniel P. Berrange 1521856835dSDaniel P. Berrange if (saddr->host == NULL) { 1530983f5e6SDaniel P. Berrange error_setg(errp, "host not specified"); 154baacf047SPaolo Bonzini return -1; 155baacf047SPaolo Bonzini } 1561856835dSDaniel P. Berrange if (saddr->port != NULL) { 1571856835dSDaniel P. Berrange pstrcpy(port, sizeof(port), saddr->port); 1580983f5e6SDaniel P. Berrange } else { 1590983f5e6SDaniel P. Berrange port[0] = '\0'; 1600983f5e6SDaniel P. Berrange } 161baacf047SPaolo Bonzini 162baacf047SPaolo Bonzini /* lookup */ 1638bc89127SGerd Hoffmann if (port_offset) { 1648bc89127SGerd Hoffmann unsigned long long baseport; 1650983f5e6SDaniel P. Berrange if (strlen(port) == 0) { 1660983f5e6SDaniel P. Berrange error_setg(errp, "port not specified"); 1670983f5e6SDaniel P. Berrange return -1; 1680983f5e6SDaniel P. Berrange } 1698bc89127SGerd Hoffmann if (parse_uint_full(port, &baseport, 10) < 0) { 1708bc89127SGerd Hoffmann error_setg(errp, "can't convert to a number: %s", port); 1718bc89127SGerd Hoffmann return -1; 1728bc89127SGerd Hoffmann } 1738bc89127SGerd Hoffmann if (baseport > 65535 || 1748bc89127SGerd Hoffmann baseport + port_offset > 65535) { 1758bc89127SGerd Hoffmann error_setg(errp, "port %s out of range", port); 1768bc89127SGerd Hoffmann return -1; 1778bc89127SGerd Hoffmann } 1788bc89127SGerd Hoffmann snprintf(port, sizeof(port), "%d", (int)baseport + port_offset); 1798bc89127SGerd Hoffmann } 1801856835dSDaniel P. Berrange rc = getaddrinfo(strlen(saddr->host) ? saddr->host : NULL, 1810983f5e6SDaniel P. Berrange strlen(port) ? port : NULL, &ai, &res); 182baacf047SPaolo Bonzini if (rc != 0) { 1831856835dSDaniel P. Berrange error_setg(errp, "address resolution failed for %s:%s: %s", 1841856835dSDaniel P. Berrange saddr->host, port, gai_strerror(rc)); 185baacf047SPaolo Bonzini return -1; 186baacf047SPaolo Bonzini } 187baacf047SPaolo Bonzini 188baacf047SPaolo Bonzini /* create socket + bind */ 189baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 190baacf047SPaolo Bonzini getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, 191baacf047SPaolo Bonzini uaddr,INET6_ADDRSTRLEN,uport,32, 192baacf047SPaolo Bonzini NI_NUMERICHOST | NI_NUMERICSERV); 193baacf047SPaolo Bonzini slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); 194baacf047SPaolo Bonzini if (slisten < 0) { 195baacf047SPaolo Bonzini if (!e->ai_next) { 196235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 197baacf047SPaolo Bonzini } 198baacf047SPaolo Bonzini continue; 199baacf047SPaolo Bonzini } 200baacf047SPaolo Bonzini 20104fd1c78SSebastian Ottlik socket_set_fast_reuse(slisten); 202baacf047SPaolo Bonzini #ifdef IPV6_V6ONLY 203baacf047SPaolo Bonzini if (e->ai_family == PF_INET6) { 204baacf047SPaolo Bonzini /* listen on both ipv4 and ipv6 */ 205f9b5426fSPeter Maydell const int off = 0; 2069957fc7fSStefan Weil qemu_setsockopt(slisten, IPPROTO_IPV6, IPV6_V6ONLY, &off, 207baacf047SPaolo Bonzini sizeof(off)); 208baacf047SPaolo Bonzini } 209baacf047SPaolo Bonzini #endif 210baacf047SPaolo Bonzini 211baacf047SPaolo Bonzini port_min = inet_getport(e); 2121856835dSDaniel P. Berrange port_max = saddr->has_to ? saddr->to + port_offset : port_min; 213baacf047SPaolo Bonzini for (p = port_min; p <= port_max; p++) { 214baacf047SPaolo Bonzini inet_setport(e, p); 215baacf047SPaolo Bonzini if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) { 216baacf047SPaolo Bonzini goto listen; 217baacf047SPaolo Bonzini } 218baacf047SPaolo Bonzini if (p == port_max) { 219baacf047SPaolo Bonzini if (!e->ai_next) { 220235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to bind socket"); 221baacf047SPaolo Bonzini } 222baacf047SPaolo Bonzini } 223baacf047SPaolo Bonzini } 224baacf047SPaolo Bonzini closesocket(slisten); 225baacf047SPaolo Bonzini } 226baacf047SPaolo Bonzini freeaddrinfo(res); 227baacf047SPaolo Bonzini return -1; 228baacf047SPaolo Bonzini 229baacf047SPaolo Bonzini listen: 230baacf047SPaolo Bonzini if (listen(slisten,1) != 0) { 231235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to listen on socket"); 232baacf047SPaolo Bonzini closesocket(slisten); 233baacf047SPaolo Bonzini freeaddrinfo(res); 234baacf047SPaolo Bonzini return -1; 235baacf047SPaolo Bonzini } 2361856835dSDaniel P. Berrange if (update_addr) { 2371856835dSDaniel P. Berrange g_free(saddr->host); 2381856835dSDaniel P. Berrange saddr->host = g_strdup(uaddr); 2391856835dSDaniel P. Berrange g_free(saddr->port); 2401856835dSDaniel P. Berrange saddr->port = g_strdup_printf("%d", 2411856835dSDaniel P. Berrange inet_getport(e) - port_offset); 2421856835dSDaniel P. Berrange saddr->has_ipv6 = saddr->ipv6 = e->ai_family == PF_INET6; 2431856835dSDaniel P. Berrange saddr->has_ipv4 = saddr->ipv4 = e->ai_family != PF_INET6; 2441856835dSDaniel P. Berrange } 245baacf047SPaolo Bonzini freeaddrinfo(res); 246baacf047SPaolo Bonzini return slisten; 247baacf047SPaolo Bonzini } 248baacf047SPaolo Bonzini 249baacf047SPaolo Bonzini #ifdef _WIN32 250baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 251baacf047SPaolo Bonzini ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY) 252baacf047SPaolo Bonzini #else 253baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 254baacf047SPaolo Bonzini ((rc) == -EINPROGRESS) 255baacf047SPaolo Bonzini #endif 256baacf047SPaolo Bonzini 257baacf047SPaolo Bonzini /* Struct to store connect state for non blocking connect */ 258baacf047SPaolo Bonzini typedef struct ConnectState { 259baacf047SPaolo Bonzini int fd; 260baacf047SPaolo Bonzini struct addrinfo *addr_list; 261baacf047SPaolo Bonzini struct addrinfo *current_addr; 262baacf047SPaolo Bonzini NonBlockingConnectHandler *callback; 263baacf047SPaolo Bonzini void *opaque; 264baacf047SPaolo Bonzini } ConnectState; 265baacf047SPaolo Bonzini 266baacf047SPaolo Bonzini static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, 267baacf047SPaolo Bonzini ConnectState *connect_state, Error **errp); 268baacf047SPaolo Bonzini 269baacf047SPaolo Bonzini static void wait_for_connect(void *opaque) 270baacf047SPaolo Bonzini { 271baacf047SPaolo Bonzini ConnectState *s = opaque; 272baacf047SPaolo Bonzini int val = 0, rc = 0; 273baacf047SPaolo Bonzini socklen_t valsize = sizeof(val); 274baacf047SPaolo Bonzini bool in_progress; 27551795029SCorey Minyard Error *err = NULL; 276baacf047SPaolo Bonzini 27782e1cc4bSFam Zheng qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 278baacf047SPaolo Bonzini 279baacf047SPaolo Bonzini do { 2809957fc7fSStefan Weil rc = qemu_getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize); 281b16a44e1SDaniel P. Berrange } while (rc == -1 && errno == EINTR); 282baacf047SPaolo Bonzini 283baacf047SPaolo Bonzini /* update rc to contain error */ 284baacf047SPaolo Bonzini if (!rc && val) { 285baacf047SPaolo Bonzini rc = -1; 28651795029SCorey Minyard errno = val; 287baacf047SPaolo Bonzini } 288baacf047SPaolo Bonzini 289baacf047SPaolo Bonzini /* connect error */ 290baacf047SPaolo Bonzini if (rc < 0) { 29151795029SCorey Minyard error_setg_errno(&err, errno, "Error connecting to socket"); 292baacf047SPaolo Bonzini closesocket(s->fd); 293baacf047SPaolo Bonzini s->fd = rc; 294baacf047SPaolo Bonzini } 295baacf047SPaolo Bonzini 296baacf047SPaolo Bonzini /* try to connect to the next address on the list */ 297baacf047SPaolo Bonzini if (s->current_addr) { 298baacf047SPaolo Bonzini while (s->current_addr->ai_next != NULL && s->fd < 0) { 299baacf047SPaolo Bonzini s->current_addr = s->current_addr->ai_next; 300baacf047SPaolo Bonzini s->fd = inet_connect_addr(s->current_addr, &in_progress, s, NULL); 30151795029SCorey Minyard if (s->fd < 0) { 30251795029SCorey Minyard error_free(err); 30351795029SCorey Minyard err = NULL; 30451795029SCorey Minyard error_setg_errno(&err, errno, "Unable to start socket connect"); 30551795029SCorey Minyard } 306baacf047SPaolo Bonzini /* connect in progress */ 307baacf047SPaolo Bonzini if (in_progress) { 30851795029SCorey Minyard goto out; 309baacf047SPaolo Bonzini } 310baacf047SPaolo Bonzini } 311baacf047SPaolo Bonzini 312baacf047SPaolo Bonzini freeaddrinfo(s->addr_list); 313baacf047SPaolo Bonzini } 314baacf047SPaolo Bonzini 315baacf047SPaolo Bonzini if (s->callback) { 31651795029SCorey Minyard s->callback(s->fd, err, s->opaque); 317baacf047SPaolo Bonzini } 318baacf047SPaolo Bonzini g_free(s); 31951795029SCorey Minyard out: 32051795029SCorey Minyard error_free(err); 321baacf047SPaolo Bonzini } 322baacf047SPaolo Bonzini 323baacf047SPaolo Bonzini static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, 324baacf047SPaolo Bonzini ConnectState *connect_state, Error **errp) 325baacf047SPaolo Bonzini { 326baacf047SPaolo Bonzini int sock, rc; 327baacf047SPaolo Bonzini 328baacf047SPaolo Bonzini *in_progress = false; 329baacf047SPaolo Bonzini 330baacf047SPaolo Bonzini sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); 331baacf047SPaolo Bonzini if (sock < 0) { 332235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 333baacf047SPaolo Bonzini return -1; 334baacf047SPaolo Bonzini } 33504fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 336baacf047SPaolo Bonzini if (connect_state != NULL) { 337f9e8caccSStefan Hajnoczi qemu_set_nonblock(sock); 338baacf047SPaolo Bonzini } 339baacf047SPaolo Bonzini /* connect to peer */ 340baacf047SPaolo Bonzini do { 341baacf047SPaolo Bonzini rc = 0; 342baacf047SPaolo Bonzini if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) { 343b16a44e1SDaniel P. Berrange rc = -errno; 344baacf047SPaolo Bonzini } 345baacf047SPaolo Bonzini } while (rc == -EINTR); 346baacf047SPaolo Bonzini 347baacf047SPaolo Bonzini if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 348baacf047SPaolo Bonzini connect_state->fd = sock; 34982e1cc4bSFam Zheng qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state); 350baacf047SPaolo Bonzini *in_progress = true; 351baacf047SPaolo Bonzini } else if (rc < 0) { 352235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to connect socket"); 353baacf047SPaolo Bonzini closesocket(sock); 354baacf047SPaolo Bonzini return -1; 355baacf047SPaolo Bonzini } 356baacf047SPaolo Bonzini return sock; 357baacf047SPaolo Bonzini } 358baacf047SPaolo Bonzini 3592942e420SDaniel P. Berrange static struct addrinfo *inet_parse_connect_saddr(InetSocketAddress *saddr, 3602942e420SDaniel P. Berrange Error **errp) 361baacf047SPaolo Bonzini { 362baacf047SPaolo Bonzini struct addrinfo ai, *res; 363baacf047SPaolo Bonzini int rc; 3642942e420SDaniel P. Berrange Error *err = NULL; 365340849a9SDaniel P. Berrange static int useV4Mapped = 1; 366baacf047SPaolo Bonzini 367baacf047SPaolo Bonzini memset(&ai, 0, sizeof(ai)); 368baacf047SPaolo Bonzini 369340849a9SDaniel P. Berrange ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; 370340849a9SDaniel P. Berrange if (atomic_read(&useV4Mapped)) { 371340849a9SDaniel P. Berrange ai.ai_flags |= AI_V4MAPPED; 372340849a9SDaniel P. Berrange } 3732942e420SDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(saddr, &err); 374baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 375baacf047SPaolo Bonzini 3762942e420SDaniel P. Berrange if (err) { 3772942e420SDaniel P. Berrange error_propagate(errp, err); 3782942e420SDaniel P. Berrange return NULL; 3792942e420SDaniel P. Berrange } 3802942e420SDaniel P. Berrange 3812942e420SDaniel P. Berrange if (saddr->host == NULL || saddr->port == NULL) { 382baacf047SPaolo Bonzini error_setg(errp, "host and/or port not specified"); 383baacf047SPaolo Bonzini return NULL; 384baacf047SPaolo Bonzini } 385baacf047SPaolo Bonzini 386baacf047SPaolo Bonzini /* lookup */ 3872942e420SDaniel P. Berrange rc = getaddrinfo(saddr->host, saddr->port, &ai, &res); 388340849a9SDaniel P. Berrange 389340849a9SDaniel P. Berrange /* At least FreeBSD and OS-X 10.6 declare AI_V4MAPPED but 390340849a9SDaniel P. Berrange * then don't implement it in their getaddrinfo(). Detect 391340849a9SDaniel P. Berrange * this and retry without the flag since that's preferrable 392340849a9SDaniel P. Berrange * to a fatal error 393340849a9SDaniel P. Berrange */ 394340849a9SDaniel P. Berrange if (rc == EAI_BADFLAGS && 395340849a9SDaniel P. Berrange (ai.ai_flags & AI_V4MAPPED)) { 396340849a9SDaniel P. Berrange atomic_set(&useV4Mapped, 0); 397340849a9SDaniel P. Berrange ai.ai_flags &= ~AI_V4MAPPED; 398340849a9SDaniel P. Berrange rc = getaddrinfo(saddr->host, saddr->port, &ai, &res); 399340849a9SDaniel P. Berrange } 400baacf047SPaolo Bonzini if (rc != 0) { 4012942e420SDaniel P. Berrange error_setg(errp, "address resolution failed for %s:%s: %s", 4022942e420SDaniel P. Berrange saddr->host, saddr->port, gai_strerror(rc)); 403baacf047SPaolo Bonzini return NULL; 404baacf047SPaolo Bonzini } 405baacf047SPaolo Bonzini return res; 406baacf047SPaolo Bonzini } 407baacf047SPaolo Bonzini 408baacf047SPaolo Bonzini /** 409baacf047SPaolo Bonzini * Create a socket and connect it to an address. 410baacf047SPaolo Bonzini * 4112942e420SDaniel P. Berrange * @saddr: Inet socket address specification 412baacf047SPaolo Bonzini * @errp: set on error 413baacf047SPaolo Bonzini * @callback: callback function for non-blocking connect 414baacf047SPaolo Bonzini * @opaque: opaque for callback function 415baacf047SPaolo Bonzini * 416baacf047SPaolo Bonzini * Returns: -1 on error, file descriptor on success. 417baacf047SPaolo Bonzini * 418baacf047SPaolo Bonzini * If @callback is non-null, the connect is non-blocking. If this 419baacf047SPaolo Bonzini * function succeeds, callback will be called when the connection 420baacf047SPaolo Bonzini * completes, with the file descriptor on success, or -1 on error. 421baacf047SPaolo Bonzini */ 42289cadc9dSAshijeet Acharya int inet_connect_saddr(InetSocketAddress *saddr, Error **errp, 423baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 424baacf047SPaolo Bonzini { 4253f9286b7SMarkus Armbruster Error *local_err = NULL; 426baacf047SPaolo Bonzini struct addrinfo *res, *e; 427baacf047SPaolo Bonzini int sock = -1; 428baacf047SPaolo Bonzini bool in_progress; 429baacf047SPaolo Bonzini ConnectState *connect_state = NULL; 430baacf047SPaolo Bonzini 4312942e420SDaniel P. Berrange res = inet_parse_connect_saddr(saddr, errp); 432baacf047SPaolo Bonzini if (!res) { 433baacf047SPaolo Bonzini return -1; 434baacf047SPaolo Bonzini } 435baacf047SPaolo Bonzini 436baacf047SPaolo Bonzini if (callback != NULL) { 437baacf047SPaolo Bonzini connect_state = g_malloc0(sizeof(*connect_state)); 438baacf047SPaolo Bonzini connect_state->addr_list = res; 439baacf047SPaolo Bonzini connect_state->callback = callback; 440baacf047SPaolo Bonzini connect_state->opaque = opaque; 441baacf047SPaolo Bonzini } 442baacf047SPaolo Bonzini 443baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 4443f9286b7SMarkus Armbruster error_free(local_err); 4453f9286b7SMarkus Armbruster local_err = NULL; 446baacf047SPaolo Bonzini if (connect_state != NULL) { 447baacf047SPaolo Bonzini connect_state->current_addr = e; 448baacf047SPaolo Bonzini } 4493f9286b7SMarkus Armbruster sock = inet_connect_addr(e, &in_progress, connect_state, &local_err); 4503f9286b7SMarkus Armbruster if (sock >= 0) { 451baacf047SPaolo Bonzini break; 452baacf047SPaolo Bonzini } 453baacf047SPaolo Bonzini } 4543f9286b7SMarkus Armbruster 4553f9286b7SMarkus Armbruster if (sock < 0) { 4563f9286b7SMarkus Armbruster error_propagate(errp, local_err); 4573f9286b7SMarkus Armbruster } else if (in_progress) { 4583f9286b7SMarkus Armbruster /* wait_for_connect() will do the rest */ 4593f9286b7SMarkus Armbruster return sock; 4603f9286b7SMarkus Armbruster } else { 4613f9286b7SMarkus Armbruster if (callback) { 46251795029SCorey Minyard callback(sock, NULL, opaque); 4633f9286b7SMarkus Armbruster } 4643f9286b7SMarkus Armbruster } 465baacf047SPaolo Bonzini g_free(connect_state); 466baacf047SPaolo Bonzini freeaddrinfo(res); 467baacf047SPaolo Bonzini return sock; 468baacf047SPaolo Bonzini } 469baacf047SPaolo Bonzini 4708b39910eSDaniel P. Berrange static int inet_dgram_saddr(InetSocketAddress *sraddr, 4718b39910eSDaniel P. Berrange InetSocketAddress *sladdr, 4728b39910eSDaniel P. Berrange Error **errp) 473baacf047SPaolo Bonzini { 474baacf047SPaolo Bonzini struct addrinfo ai, *peer = NULL, *local = NULL; 475baacf047SPaolo Bonzini const char *addr; 476baacf047SPaolo Bonzini const char *port; 477baacf047SPaolo Bonzini int sock = -1, rc; 4788b39910eSDaniel P. Berrange Error *err = NULL; 479baacf047SPaolo Bonzini 480baacf047SPaolo Bonzini /* lookup peer addr */ 481baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 4823de3d698SWolfgang Bumiller ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG; 4838b39910eSDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(sraddr, &err); 484baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 485baacf047SPaolo Bonzini 4868b39910eSDaniel P. Berrange if (err) { 4878b39910eSDaniel P. Berrange error_propagate(errp, err); 48858c652c0SPaolo Bonzini goto err; 4898b39910eSDaniel P. Berrange } 4908b39910eSDaniel P. Berrange 4918b39910eSDaniel P. Berrange addr = sraddr->host; 4928b39910eSDaniel P. Berrange port = sraddr->port; 493baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 494baacf047SPaolo Bonzini addr = "localhost"; 495baacf047SPaolo Bonzini } 496baacf047SPaolo Bonzini if (port == NULL || strlen(port) == 0) { 497baacf047SPaolo Bonzini error_setg(errp, "remote port not specified"); 49858c652c0SPaolo Bonzini goto err; 499baacf047SPaolo Bonzini } 500baacf047SPaolo Bonzini 5019cd1883cSCao jin if ((rc = getaddrinfo(addr, port, &ai, &peer)) != 0) { 502baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 503baacf047SPaolo Bonzini gai_strerror(rc)); 50458c652c0SPaolo Bonzini goto err; 505baacf047SPaolo Bonzini } 506baacf047SPaolo Bonzini 507baacf047SPaolo Bonzini /* lookup local addr */ 508baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 509baacf047SPaolo Bonzini ai.ai_flags = AI_PASSIVE; 510baacf047SPaolo Bonzini ai.ai_family = peer->ai_family; 511baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 512baacf047SPaolo Bonzini 5138b39910eSDaniel P. Berrange if (sladdr) { 5148b39910eSDaniel P. Berrange addr = sladdr->host; 5158b39910eSDaniel P. Berrange port = sladdr->port; 516baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 517baacf047SPaolo Bonzini addr = NULL; 518baacf047SPaolo Bonzini } 5198b39910eSDaniel P. Berrange if (!port || strlen(port) == 0) { 520baacf047SPaolo Bonzini port = "0"; 5218b39910eSDaniel P. Berrange } 5228b39910eSDaniel P. Berrange } else { 5238b39910eSDaniel P. Berrange addr = NULL; 5248b39910eSDaniel P. Berrange port = "0"; 5258b39910eSDaniel P. Berrange } 526baacf047SPaolo Bonzini 5279cd1883cSCao jin if ((rc = getaddrinfo(addr, port, &ai, &local)) != 0) { 528baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 529baacf047SPaolo Bonzini gai_strerror(rc)); 530baacf047SPaolo Bonzini goto err; 531baacf047SPaolo Bonzini } 532baacf047SPaolo Bonzini 533baacf047SPaolo Bonzini /* create socket */ 534baacf047SPaolo Bonzini sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); 535baacf047SPaolo Bonzini if (sock < 0) { 536235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 537baacf047SPaolo Bonzini goto err; 538baacf047SPaolo Bonzini } 53904fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 540baacf047SPaolo Bonzini 541baacf047SPaolo Bonzini /* bind socket */ 542baacf047SPaolo Bonzini if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { 543235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to bind socket"); 544baacf047SPaolo Bonzini goto err; 545baacf047SPaolo Bonzini } 546baacf047SPaolo Bonzini 547baacf047SPaolo Bonzini /* connect to peer */ 548baacf047SPaolo Bonzini if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { 549235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to connect socket"); 550baacf047SPaolo Bonzini goto err; 551baacf047SPaolo Bonzini } 552baacf047SPaolo Bonzini 553baacf047SPaolo Bonzini freeaddrinfo(local); 554baacf047SPaolo Bonzini freeaddrinfo(peer); 555baacf047SPaolo Bonzini return sock; 556baacf047SPaolo Bonzini 557baacf047SPaolo Bonzini err: 55826015051SCao jin if (sock != -1) { 559baacf047SPaolo Bonzini closesocket(sock); 56026015051SCao jin } 56126015051SCao jin if (local) { 562baacf047SPaolo Bonzini freeaddrinfo(local); 56326015051SCao jin } 56426015051SCao jin if (peer) { 565baacf047SPaolo Bonzini freeaddrinfo(peer); 56626015051SCao jin } 56726015051SCao jin 568baacf047SPaolo Bonzini return -1; 569baacf047SPaolo Bonzini } 570baacf047SPaolo Bonzini 571baacf047SPaolo Bonzini /* compatibility wrapper */ 572f17c90beSKevin Wolf InetSocketAddress *inet_parse(const char *str, Error **errp) 573baacf047SPaolo Bonzini { 574baacf047SPaolo Bonzini InetSocketAddress *addr; 575baacf047SPaolo Bonzini const char *optstr, *h; 57655a10996SKevin Wolf char host[65]; 577baacf047SPaolo Bonzini char port[33]; 578baacf047SPaolo Bonzini int to; 579baacf047SPaolo Bonzini int pos; 580baacf047SPaolo Bonzini 581baacf047SPaolo Bonzini addr = g_new0(InetSocketAddress, 1); 582baacf047SPaolo Bonzini 583baacf047SPaolo Bonzini /* parse address */ 584baacf047SPaolo Bonzini if (str[0] == ':') { 585baacf047SPaolo Bonzini /* no host given */ 586baacf047SPaolo Bonzini host[0] = '\0'; 5879cd1883cSCao jin if (sscanf(str, ":%32[^,]%n", port, &pos) != 1) { 588baacf047SPaolo Bonzini error_setg(errp, "error parsing port in address '%s'", str); 589baacf047SPaolo Bonzini goto fail; 590baacf047SPaolo Bonzini } 591baacf047SPaolo Bonzini } else if (str[0] == '[') { 592baacf047SPaolo Bonzini /* IPv6 addr */ 5939cd1883cSCao jin if (sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos) != 2) { 594baacf047SPaolo Bonzini error_setg(errp, "error parsing IPv6 address '%s'", str); 595baacf047SPaolo Bonzini goto fail; 596baacf047SPaolo Bonzini } 597baacf047SPaolo Bonzini addr->ipv6 = addr->has_ipv6 = true; 598baacf047SPaolo Bonzini } else { 599391b7b97SJán Tomko /* hostname or IPv4 addr */ 6009cd1883cSCao jin if (sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos) != 2) { 601baacf047SPaolo Bonzini error_setg(errp, "error parsing address '%s'", str); 602baacf047SPaolo Bonzini goto fail; 603baacf047SPaolo Bonzini } 604391b7b97SJán Tomko if (host[strspn(host, "0123456789.")] == '\0') { 605391b7b97SJán Tomko addr->ipv4 = addr->has_ipv4 = true; 606391b7b97SJán Tomko } 607baacf047SPaolo Bonzini } 608baacf047SPaolo Bonzini 609baacf047SPaolo Bonzini addr->host = g_strdup(host); 610baacf047SPaolo Bonzini addr->port = g_strdup(port); 611baacf047SPaolo Bonzini 612baacf047SPaolo Bonzini /* parse options */ 613baacf047SPaolo Bonzini optstr = str + pos; 614baacf047SPaolo Bonzini h = strstr(optstr, ",to="); 615baacf047SPaolo Bonzini if (h) { 616baacf047SPaolo Bonzini h += 4; 617baacf047SPaolo Bonzini if (sscanf(h, "%d%n", &to, &pos) != 1 || 618baacf047SPaolo Bonzini (h[pos] != '\0' && h[pos] != ',')) { 619baacf047SPaolo Bonzini error_setg(errp, "error parsing to= argument"); 620baacf047SPaolo Bonzini goto fail; 621baacf047SPaolo Bonzini } 622baacf047SPaolo Bonzini addr->has_to = true; 623baacf047SPaolo Bonzini addr->to = to; 624baacf047SPaolo Bonzini } 625baacf047SPaolo Bonzini if (strstr(optstr, ",ipv4")) { 626baacf047SPaolo Bonzini addr->ipv4 = addr->has_ipv4 = true; 627baacf047SPaolo Bonzini } 628baacf047SPaolo Bonzini if (strstr(optstr, ",ipv6")) { 629baacf047SPaolo Bonzini addr->ipv6 = addr->has_ipv6 = true; 630baacf047SPaolo Bonzini } 631baacf047SPaolo Bonzini return addr; 632baacf047SPaolo Bonzini 633baacf047SPaolo Bonzini fail: 634baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 635baacf047SPaolo Bonzini return NULL; 636baacf047SPaolo Bonzini } 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 int sock = -1; 650baacf047SPaolo Bonzini InetSocketAddress *addr; 651baacf047SPaolo Bonzini 652baacf047SPaolo Bonzini addr = inet_parse(str, errp); 653baacf047SPaolo Bonzini if (addr != NULL) { 6542942e420SDaniel P. Berrange sock = inet_connect_saddr(addr, errp, NULL, NULL); 655baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 656baacf047SPaolo Bonzini } 657baacf047SPaolo Bonzini return sock; 658baacf047SPaolo Bonzini } 659baacf047SPaolo Bonzini 660*6a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 661*6a02c806SStefan Hajnoczi static bool vsock_parse_vaddr_to_sockaddr(const VsockSocketAddress *vaddr, 662*6a02c806SStefan Hajnoczi struct sockaddr_vm *svm, 663*6a02c806SStefan Hajnoczi Error **errp) 664*6a02c806SStefan Hajnoczi { 665*6a02c806SStefan Hajnoczi unsigned long long val; 666*6a02c806SStefan Hajnoczi 667*6a02c806SStefan Hajnoczi memset(svm, 0, sizeof(*svm)); 668*6a02c806SStefan Hajnoczi svm->svm_family = AF_VSOCK; 669*6a02c806SStefan Hajnoczi 670*6a02c806SStefan Hajnoczi if (parse_uint_full(vaddr->cid, &val, 10) < 0 || 671*6a02c806SStefan Hajnoczi val > UINT32_MAX) { 672*6a02c806SStefan Hajnoczi error_setg(errp, "Failed to parse cid '%s'", vaddr->cid); 673*6a02c806SStefan Hajnoczi return false; 674*6a02c806SStefan Hajnoczi } 675*6a02c806SStefan Hajnoczi svm->svm_cid = val; 676*6a02c806SStefan Hajnoczi 677*6a02c806SStefan Hajnoczi if (parse_uint_full(vaddr->port, &val, 10) < 0 || 678*6a02c806SStefan Hajnoczi val > UINT32_MAX) { 679*6a02c806SStefan Hajnoczi error_setg(errp, "Failed to parse port '%s'", vaddr->port); 680*6a02c806SStefan Hajnoczi return false; 681*6a02c806SStefan Hajnoczi } 682*6a02c806SStefan Hajnoczi svm->svm_port = val; 683*6a02c806SStefan Hajnoczi 684*6a02c806SStefan Hajnoczi return true; 685*6a02c806SStefan Hajnoczi } 686*6a02c806SStefan Hajnoczi 687*6a02c806SStefan Hajnoczi static int vsock_connect_addr(const struct sockaddr_vm *svm, bool *in_progress, 688*6a02c806SStefan Hajnoczi ConnectState *connect_state, Error **errp) 689*6a02c806SStefan Hajnoczi { 690*6a02c806SStefan Hajnoczi int sock, rc; 691*6a02c806SStefan Hajnoczi 692*6a02c806SStefan Hajnoczi *in_progress = false; 693*6a02c806SStefan Hajnoczi 694*6a02c806SStefan Hajnoczi sock = qemu_socket(AF_VSOCK, SOCK_STREAM, 0); 695*6a02c806SStefan Hajnoczi if (sock < 0) { 696*6a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to create socket"); 697*6a02c806SStefan Hajnoczi return -1; 698*6a02c806SStefan Hajnoczi } 699*6a02c806SStefan Hajnoczi if (connect_state != NULL) { 700*6a02c806SStefan Hajnoczi qemu_set_nonblock(sock); 701*6a02c806SStefan Hajnoczi } 702*6a02c806SStefan Hajnoczi /* connect to peer */ 703*6a02c806SStefan Hajnoczi do { 704*6a02c806SStefan Hajnoczi rc = 0; 705*6a02c806SStefan Hajnoczi if (connect(sock, (const struct sockaddr *)svm, sizeof(*svm)) < 0) { 706*6a02c806SStefan Hajnoczi rc = -errno; 707*6a02c806SStefan Hajnoczi } 708*6a02c806SStefan Hajnoczi } while (rc == -EINTR); 709*6a02c806SStefan Hajnoczi 710*6a02c806SStefan Hajnoczi if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 711*6a02c806SStefan Hajnoczi connect_state->fd = sock; 712*6a02c806SStefan Hajnoczi qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state); 713*6a02c806SStefan Hajnoczi *in_progress = true; 714*6a02c806SStefan Hajnoczi } else if (rc < 0) { 715*6a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to connect socket"); 716*6a02c806SStefan Hajnoczi closesocket(sock); 717*6a02c806SStefan Hajnoczi return -1; 718*6a02c806SStefan Hajnoczi } 719*6a02c806SStefan Hajnoczi return sock; 720*6a02c806SStefan Hajnoczi } 721*6a02c806SStefan Hajnoczi 722*6a02c806SStefan Hajnoczi static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp, 723*6a02c806SStefan Hajnoczi NonBlockingConnectHandler *callback, 724*6a02c806SStefan Hajnoczi void *opaque) 725*6a02c806SStefan Hajnoczi { 726*6a02c806SStefan Hajnoczi struct sockaddr_vm svm; 727*6a02c806SStefan Hajnoczi int sock = -1; 728*6a02c806SStefan Hajnoczi bool in_progress; 729*6a02c806SStefan Hajnoczi ConnectState *connect_state = NULL; 730*6a02c806SStefan Hajnoczi 731*6a02c806SStefan Hajnoczi if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) { 732*6a02c806SStefan Hajnoczi return -1; 733*6a02c806SStefan Hajnoczi } 734*6a02c806SStefan Hajnoczi 735*6a02c806SStefan Hajnoczi if (callback != NULL) { 736*6a02c806SStefan Hajnoczi connect_state = g_malloc0(sizeof(*connect_state)); 737*6a02c806SStefan Hajnoczi connect_state->callback = callback; 738*6a02c806SStefan Hajnoczi connect_state->opaque = opaque; 739*6a02c806SStefan Hajnoczi } 740*6a02c806SStefan Hajnoczi 741*6a02c806SStefan Hajnoczi sock = vsock_connect_addr(&svm, &in_progress, connect_state, errp); 742*6a02c806SStefan Hajnoczi if (sock < 0) { 743*6a02c806SStefan Hajnoczi /* do nothing */ 744*6a02c806SStefan Hajnoczi } else if (in_progress) { 745*6a02c806SStefan Hajnoczi /* wait_for_connect() will do the rest */ 746*6a02c806SStefan Hajnoczi return sock; 747*6a02c806SStefan Hajnoczi } else { 748*6a02c806SStefan Hajnoczi if (callback) { 749*6a02c806SStefan Hajnoczi callback(sock, NULL, opaque); 750*6a02c806SStefan Hajnoczi } 751*6a02c806SStefan Hajnoczi } 752*6a02c806SStefan Hajnoczi g_free(connect_state); 753*6a02c806SStefan Hajnoczi return sock; 754*6a02c806SStefan Hajnoczi } 755*6a02c806SStefan Hajnoczi 756*6a02c806SStefan Hajnoczi static int vsock_listen_saddr(VsockSocketAddress *vaddr, 757*6a02c806SStefan Hajnoczi Error **errp) 758*6a02c806SStefan Hajnoczi { 759*6a02c806SStefan Hajnoczi struct sockaddr_vm svm; 760*6a02c806SStefan Hajnoczi int slisten; 761*6a02c806SStefan Hajnoczi 762*6a02c806SStefan Hajnoczi if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) { 763*6a02c806SStefan Hajnoczi return -1; 764*6a02c806SStefan Hajnoczi } 765*6a02c806SStefan Hajnoczi 766*6a02c806SStefan Hajnoczi slisten = qemu_socket(AF_VSOCK, SOCK_STREAM, 0); 767*6a02c806SStefan Hajnoczi if (slisten < 0) { 768*6a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to create socket"); 769*6a02c806SStefan Hajnoczi return -1; 770*6a02c806SStefan Hajnoczi } 771*6a02c806SStefan Hajnoczi 772*6a02c806SStefan Hajnoczi if (bind(slisten, (const struct sockaddr *)&svm, sizeof(svm)) != 0) { 773*6a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to bind socket"); 774*6a02c806SStefan Hajnoczi closesocket(slisten); 775*6a02c806SStefan Hajnoczi return -1; 776*6a02c806SStefan Hajnoczi } 777*6a02c806SStefan Hajnoczi 778*6a02c806SStefan Hajnoczi if (listen(slisten, 1) != 0) { 779*6a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to listen on socket"); 780*6a02c806SStefan Hajnoczi closesocket(slisten); 781*6a02c806SStefan Hajnoczi return -1; 782*6a02c806SStefan Hajnoczi } 783*6a02c806SStefan Hajnoczi return slisten; 784*6a02c806SStefan Hajnoczi } 785*6a02c806SStefan Hajnoczi 786*6a02c806SStefan Hajnoczi static VsockSocketAddress *vsock_parse(const char *str, Error **errp) 787*6a02c806SStefan Hajnoczi { 788*6a02c806SStefan Hajnoczi VsockSocketAddress *addr = NULL; 789*6a02c806SStefan Hajnoczi char cid[33]; 790*6a02c806SStefan Hajnoczi char port[33]; 791*6a02c806SStefan Hajnoczi int n; 792*6a02c806SStefan Hajnoczi 793*6a02c806SStefan Hajnoczi if (sscanf(str, "%32[^:]:%32[^,]%n", cid, port, &n) != 2) { 794*6a02c806SStefan Hajnoczi error_setg(errp, "error parsing address '%s'", str); 795*6a02c806SStefan Hajnoczi return NULL; 796*6a02c806SStefan Hajnoczi } 797*6a02c806SStefan Hajnoczi if (str[n] != '\0') { 798*6a02c806SStefan Hajnoczi error_setg(errp, "trailing characters in address '%s'", str); 799*6a02c806SStefan Hajnoczi return NULL; 800*6a02c806SStefan Hajnoczi } 801*6a02c806SStefan Hajnoczi 802*6a02c806SStefan Hajnoczi addr = g_new0(VsockSocketAddress, 1); 803*6a02c806SStefan Hajnoczi addr->cid = g_strdup(cid); 804*6a02c806SStefan Hajnoczi addr->port = g_strdup(port); 805*6a02c806SStefan Hajnoczi return addr; 806*6a02c806SStefan Hajnoczi } 807*6a02c806SStefan Hajnoczi #else 808*6a02c806SStefan Hajnoczi static void vsock_unsupported(Error **errp) 809*6a02c806SStefan Hajnoczi { 810*6a02c806SStefan Hajnoczi error_setg(errp, "socket family AF_VSOCK unsupported"); 811*6a02c806SStefan Hajnoczi } 812*6a02c806SStefan Hajnoczi 813*6a02c806SStefan Hajnoczi static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp, 814*6a02c806SStefan Hajnoczi NonBlockingConnectHandler *callback, 815*6a02c806SStefan Hajnoczi void *opaque) 816*6a02c806SStefan Hajnoczi { 817*6a02c806SStefan Hajnoczi vsock_unsupported(errp); 818*6a02c806SStefan Hajnoczi return -1; 819*6a02c806SStefan Hajnoczi } 820*6a02c806SStefan Hajnoczi 821*6a02c806SStefan Hajnoczi static int vsock_listen_saddr(VsockSocketAddress *vaddr, 822*6a02c806SStefan Hajnoczi Error **errp) 823*6a02c806SStefan Hajnoczi { 824*6a02c806SStefan Hajnoczi vsock_unsupported(errp); 825*6a02c806SStefan Hajnoczi return -1; 826*6a02c806SStefan Hajnoczi } 827*6a02c806SStefan Hajnoczi 828*6a02c806SStefan Hajnoczi static VsockSocketAddress *vsock_parse(const char *str, Error **errp) 829*6a02c806SStefan Hajnoczi { 830*6a02c806SStefan Hajnoczi vsock_unsupported(errp); 831*6a02c806SStefan Hajnoczi return NULL; 832*6a02c806SStefan Hajnoczi } 833*6a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 834*6a02c806SStefan Hajnoczi 835baacf047SPaolo Bonzini #ifndef _WIN32 836baacf047SPaolo Bonzini 8371856835dSDaniel P. Berrange static int unix_listen_saddr(UnixSocketAddress *saddr, 8381856835dSDaniel P. Berrange bool update_addr, 8391856835dSDaniel P. Berrange Error **errp) 840baacf047SPaolo Bonzini { 841baacf047SPaolo Bonzini struct sockaddr_un un; 842baacf047SPaolo Bonzini int sock, fd; 843baacf047SPaolo Bonzini 844baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 845baacf047SPaolo Bonzini if (sock < 0) { 846b658c53dSPaolo Bonzini error_setg_errno(errp, errno, "Failed to create Unix socket"); 847baacf047SPaolo Bonzini return -1; 848baacf047SPaolo Bonzini } 849baacf047SPaolo Bonzini 850baacf047SPaolo Bonzini memset(&un, 0, sizeof(un)); 851baacf047SPaolo Bonzini un.sun_family = AF_UNIX; 8521856835dSDaniel P. Berrange if (saddr->path && strlen(saddr->path)) { 8531856835dSDaniel P. Berrange snprintf(un.sun_path, sizeof(un.sun_path), "%s", saddr->path); 854baacf047SPaolo Bonzini } else { 855b658c53dSPaolo Bonzini const char *tmpdir = getenv("TMPDIR"); 856b658c53dSPaolo Bonzini tmpdir = tmpdir ? tmpdir : "/tmp"; 857b658c53dSPaolo Bonzini if (snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX", 858b658c53dSPaolo Bonzini tmpdir) >= sizeof(un.sun_path)) { 859b658c53dSPaolo Bonzini error_setg_errno(errp, errno, 860b658c53dSPaolo Bonzini "TMPDIR environment variable (%s) too large", tmpdir); 861b658c53dSPaolo Bonzini goto err; 862b658c53dSPaolo Bonzini } 863b658c53dSPaolo Bonzini 864baacf047SPaolo Bonzini /* 865baacf047SPaolo Bonzini * This dummy fd usage silences the mktemp() unsecure warning. 866baacf047SPaolo Bonzini * Using mkstemp() doesn't make things more secure here 867baacf047SPaolo Bonzini * though. bind() complains about existing files, so we have 868baacf047SPaolo Bonzini * to unlink first and thus re-open the race window. The 869baacf047SPaolo Bonzini * worst case possible is bind() failing, i.e. a DoS attack. 870baacf047SPaolo Bonzini */ 871b658c53dSPaolo Bonzini fd = mkstemp(un.sun_path); 872b658c53dSPaolo Bonzini if (fd < 0) { 873b658c53dSPaolo Bonzini error_setg_errno(errp, errno, 874b658c53dSPaolo Bonzini "Failed to make a temporary socket name in %s", tmpdir); 875b658c53dSPaolo Bonzini goto err; 876b658c53dSPaolo Bonzini } 877b658c53dSPaolo Bonzini close(fd); 8781856835dSDaniel P. Berrange if (update_addr) { 8791856835dSDaniel P. Berrange g_free(saddr->path); 8801856835dSDaniel P. Berrange saddr->path = g_strdup(un.sun_path); 8811856835dSDaniel P. Berrange } 882baacf047SPaolo Bonzini } 883baacf047SPaolo Bonzini 884a2f31f18SPaolo Bonzini if (unlink(un.sun_path) < 0 && errno != ENOENT) { 8850ef705a2SCole Robinson error_setg_errno(errp, errno, 8860ef705a2SCole Robinson "Failed to unlink socket %s", un.sun_path); 8870ef705a2SCole Robinson goto err; 8880ef705a2SCole Robinson } 889baacf047SPaolo Bonzini if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { 890b658c53dSPaolo Bonzini error_setg_errno(errp, errno, "Failed to bind socket to %s", un.sun_path); 891baacf047SPaolo Bonzini goto err; 892baacf047SPaolo Bonzini } 893baacf047SPaolo Bonzini if (listen(sock, 1) < 0) { 894235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to listen on socket"); 895baacf047SPaolo Bonzini goto err; 896baacf047SPaolo Bonzini } 897baacf047SPaolo Bonzini 898baacf047SPaolo Bonzini return sock; 899baacf047SPaolo Bonzini 900baacf047SPaolo Bonzini err: 901baacf047SPaolo Bonzini closesocket(sock); 902baacf047SPaolo Bonzini return -1; 903baacf047SPaolo Bonzini } 904baacf047SPaolo Bonzini 9052942e420SDaniel P. Berrange static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp, 906baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 907baacf047SPaolo Bonzini { 908baacf047SPaolo Bonzini struct sockaddr_un un; 909baacf047SPaolo Bonzini ConnectState *connect_state = NULL; 910baacf047SPaolo Bonzini int sock, rc; 911baacf047SPaolo Bonzini 9122942e420SDaniel P. Berrange if (saddr->path == NULL) { 913312fd5f2SMarkus Armbruster error_setg(errp, "unix connect: no path specified"); 914baacf047SPaolo Bonzini return -1; 915baacf047SPaolo Bonzini } 916baacf047SPaolo Bonzini 917baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 918baacf047SPaolo Bonzini if (sock < 0) { 919235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 920baacf047SPaolo Bonzini return -1; 921baacf047SPaolo Bonzini } 922baacf047SPaolo Bonzini if (callback != NULL) { 923baacf047SPaolo Bonzini connect_state = g_malloc0(sizeof(*connect_state)); 924baacf047SPaolo Bonzini connect_state->callback = callback; 925baacf047SPaolo Bonzini connect_state->opaque = opaque; 926f9e8caccSStefan Hajnoczi qemu_set_nonblock(sock); 927baacf047SPaolo Bonzini } 928baacf047SPaolo Bonzini 929baacf047SPaolo Bonzini memset(&un, 0, sizeof(un)); 930baacf047SPaolo Bonzini un.sun_family = AF_UNIX; 9312942e420SDaniel P. Berrange snprintf(un.sun_path, sizeof(un.sun_path), "%s", saddr->path); 932baacf047SPaolo Bonzini 933baacf047SPaolo Bonzini /* connect to peer */ 934baacf047SPaolo Bonzini do { 935baacf047SPaolo Bonzini rc = 0; 936baacf047SPaolo Bonzini if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { 937b16a44e1SDaniel P. Berrange rc = -errno; 938baacf047SPaolo Bonzini } 939baacf047SPaolo Bonzini } while (rc == -EINTR); 940baacf047SPaolo Bonzini 941baacf047SPaolo Bonzini if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 942baacf047SPaolo Bonzini connect_state->fd = sock; 94382e1cc4bSFam Zheng qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state); 944baacf047SPaolo Bonzini return sock; 945baacf047SPaolo Bonzini } else if (rc >= 0) { 946baacf047SPaolo Bonzini /* non blocking socket immediate success, call callback */ 947baacf047SPaolo Bonzini if (callback != NULL) { 94851795029SCorey Minyard callback(sock, NULL, opaque); 949baacf047SPaolo Bonzini } 950baacf047SPaolo Bonzini } 951baacf047SPaolo Bonzini 952baacf047SPaolo Bonzini if (rc < 0) { 953235256a2SMarkus Armbruster error_setg_errno(errp, -rc, "Failed to connect socket"); 954baacf047SPaolo Bonzini close(sock); 955baacf047SPaolo Bonzini sock = -1; 956baacf047SPaolo Bonzini } 957baacf047SPaolo Bonzini 958baacf047SPaolo Bonzini g_free(connect_state); 959baacf047SPaolo Bonzini return sock; 960baacf047SPaolo Bonzini } 961baacf047SPaolo Bonzini 962baacf047SPaolo Bonzini #else 963baacf047SPaolo Bonzini 9641856835dSDaniel P. Berrange static int unix_listen_saddr(UnixSocketAddress *saddr, 9651856835dSDaniel P. Berrange bool update_addr, 9661856835dSDaniel P. Berrange Error **errp) 967baacf047SPaolo Bonzini { 968baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 969baacf047SPaolo Bonzini errno = ENOTSUP; 970baacf047SPaolo Bonzini return -1; 971baacf047SPaolo Bonzini } 972baacf047SPaolo Bonzini 9732942e420SDaniel P. Berrange static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp, 974baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 975baacf047SPaolo Bonzini { 976baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 977baacf047SPaolo Bonzini errno = ENOTSUP; 978baacf047SPaolo Bonzini return -1; 979baacf047SPaolo Bonzini } 980baacf047SPaolo Bonzini #endif 981baacf047SPaolo Bonzini 982baacf047SPaolo Bonzini /* compatibility wrapper */ 983baacf047SPaolo Bonzini int unix_listen(const char *str, char *ostr, int olen, Error **errp) 984baacf047SPaolo Bonzini { 985baacf047SPaolo Bonzini char *path, *optstr; 986baacf047SPaolo Bonzini int sock, len; 9871856835dSDaniel P. Berrange UnixSocketAddress *saddr; 988baacf047SPaolo Bonzini 9891856835dSDaniel P. Berrange saddr = g_new0(UnixSocketAddress, 1); 990baacf047SPaolo Bonzini 991baacf047SPaolo Bonzini optstr = strchr(str, ','); 992baacf047SPaolo Bonzini if (optstr) { 993baacf047SPaolo Bonzini len = optstr - str; 994baacf047SPaolo Bonzini if (len) { 995baacf047SPaolo Bonzini path = g_malloc(len+1); 996baacf047SPaolo Bonzini snprintf(path, len+1, "%.*s", len, str); 9971856835dSDaniel P. Berrange saddr->path = path; 998baacf047SPaolo Bonzini } 999baacf047SPaolo Bonzini } else { 10001856835dSDaniel P. Berrange saddr->path = g_strdup(str); 1001baacf047SPaolo Bonzini } 1002baacf047SPaolo Bonzini 10031856835dSDaniel P. Berrange sock = unix_listen_saddr(saddr, true, errp); 1004baacf047SPaolo Bonzini 100526015051SCao jin if (sock != -1 && ostr) { 10061856835dSDaniel P. Berrange snprintf(ostr, olen, "%s%s", saddr->path, optstr ? optstr : ""); 100726015051SCao jin } 100826015051SCao jin 10091856835dSDaniel P. Berrange qapi_free_UnixSocketAddress(saddr); 1010baacf047SPaolo Bonzini return sock; 1011baacf047SPaolo Bonzini } 1012baacf047SPaolo Bonzini 1013baacf047SPaolo Bonzini int unix_connect(const char *path, Error **errp) 1014baacf047SPaolo Bonzini { 10152942e420SDaniel P. Berrange UnixSocketAddress *saddr; 1016baacf047SPaolo Bonzini int sock; 1017baacf047SPaolo Bonzini 10182942e420SDaniel P. Berrange saddr = g_new0(UnixSocketAddress, 1); 10192942e420SDaniel P. Berrange saddr->path = g_strdup(path); 10202942e420SDaniel P. Berrange sock = unix_connect_saddr(saddr, errp, NULL, NULL); 10212942e420SDaniel P. Berrange qapi_free_UnixSocketAddress(saddr); 1022baacf047SPaolo Bonzini return sock; 1023baacf047SPaolo Bonzini } 1024baacf047SPaolo Bonzini 1025baacf047SPaolo Bonzini 1026baacf047SPaolo Bonzini SocketAddress *socket_parse(const char *str, Error **errp) 1027baacf047SPaolo Bonzini { 1028afde3f8bSGerd Hoffmann SocketAddress *addr; 1029baacf047SPaolo Bonzini 1030afde3f8bSGerd Hoffmann addr = g_new0(SocketAddress, 1); 1031baacf047SPaolo Bonzini if (strstart(str, "unix:", NULL)) { 1032baacf047SPaolo Bonzini if (str[5] == '\0') { 1033312fd5f2SMarkus Armbruster error_setg(errp, "invalid Unix socket address"); 1034baacf047SPaolo Bonzini goto fail; 1035baacf047SPaolo Bonzini } else { 10362d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_UNIX; 103732bafa8fSEric Blake addr->u.q_unix.data = g_new(UnixSocketAddress, 1); 103832bafa8fSEric Blake addr->u.q_unix.data->path = g_strdup(str + 5); 1039baacf047SPaolo Bonzini } 1040baacf047SPaolo Bonzini } else if (strstart(str, "fd:", NULL)) { 1041baacf047SPaolo Bonzini if (str[3] == '\0') { 1042312fd5f2SMarkus Armbruster error_setg(errp, "invalid file descriptor address"); 1043baacf047SPaolo Bonzini goto fail; 1044baacf047SPaolo Bonzini } else { 10452d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_FD; 104632bafa8fSEric Blake addr->u.fd.data = g_new(String, 1); 104732bafa8fSEric Blake addr->u.fd.data->str = g_strdup(str + 3); 1048baacf047SPaolo Bonzini } 1049*6a02c806SStefan Hajnoczi } else if (strstart(str, "vsock:", NULL)) { 1050*6a02c806SStefan Hajnoczi addr->type = SOCKET_ADDRESS_KIND_VSOCK; 1051*6a02c806SStefan Hajnoczi addr->u.vsock.data = vsock_parse(str + strlen("vsock:"), errp); 1052*6a02c806SStefan Hajnoczi if (addr->u.vsock.data == NULL) { 1053*6a02c806SStefan Hajnoczi goto fail; 1054*6a02c806SStefan Hajnoczi } 1055baacf047SPaolo Bonzini } else { 10562d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_INET; 105732bafa8fSEric Blake addr->u.inet.data = inet_parse(str, errp); 105832bafa8fSEric Blake if (addr->u.inet.data == NULL) { 1059baacf047SPaolo Bonzini goto fail; 1060baacf047SPaolo Bonzini } 1061baacf047SPaolo Bonzini } 1062baacf047SPaolo Bonzini return addr; 1063baacf047SPaolo Bonzini 1064baacf047SPaolo Bonzini fail: 1065baacf047SPaolo Bonzini qapi_free_SocketAddress(addr); 1066baacf047SPaolo Bonzini return NULL; 1067baacf047SPaolo Bonzini } 1068baacf047SPaolo Bonzini 1069baacf047SPaolo Bonzini int socket_connect(SocketAddress *addr, Error **errp, 1070baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 1071baacf047SPaolo Bonzini { 1072baacf047SPaolo Bonzini int fd; 1073baacf047SPaolo Bonzini 10742d32addaSEric Blake switch (addr->type) { 1075baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_INET: 107632bafa8fSEric Blake fd = inet_connect_saddr(addr->u.inet.data, errp, callback, opaque); 1077baacf047SPaolo Bonzini break; 1078baacf047SPaolo Bonzini 1079baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_UNIX: 108032bafa8fSEric Blake fd = unix_connect_saddr(addr->u.q_unix.data, errp, callback, opaque); 1081baacf047SPaolo Bonzini break; 1082baacf047SPaolo Bonzini 1083baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_FD: 108432bafa8fSEric Blake fd = monitor_get_fd(cur_mon, addr->u.fd.data->str, errp); 1085d1ec72a4SGerd Hoffmann if (fd >= 0 && callback) { 10861a751ebfSStefan Hajnoczi qemu_set_nonblock(fd); 108751795029SCorey Minyard callback(fd, NULL, opaque); 1088baacf047SPaolo Bonzini } 1089baacf047SPaolo Bonzini break; 1090baacf047SPaolo Bonzini 1091*6a02c806SStefan Hajnoczi case SOCKET_ADDRESS_KIND_VSOCK: 1092*6a02c806SStefan Hajnoczi fd = vsock_connect_saddr(addr->u.vsock.data, errp, callback, opaque); 1093*6a02c806SStefan Hajnoczi break; 1094*6a02c806SStefan Hajnoczi 1095baacf047SPaolo Bonzini default: 1096baacf047SPaolo Bonzini abort(); 1097baacf047SPaolo Bonzini } 1098baacf047SPaolo Bonzini return fd; 1099baacf047SPaolo Bonzini } 1100baacf047SPaolo Bonzini 1101baacf047SPaolo Bonzini int socket_listen(SocketAddress *addr, Error **errp) 1102baacf047SPaolo Bonzini { 1103baacf047SPaolo Bonzini int fd; 1104baacf047SPaolo Bonzini 11052d32addaSEric Blake switch (addr->type) { 1106baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_INET: 110732bafa8fSEric Blake fd = inet_listen_saddr(addr->u.inet.data, 0, false, errp); 1108baacf047SPaolo Bonzini break; 1109baacf047SPaolo Bonzini 1110baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_UNIX: 111132bafa8fSEric Blake fd = unix_listen_saddr(addr->u.q_unix.data, false, errp); 1112baacf047SPaolo Bonzini break; 1113baacf047SPaolo Bonzini 1114baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_FD: 111532bafa8fSEric Blake fd = monitor_get_fd(cur_mon, addr->u.fd.data->str, errp); 1116baacf047SPaolo Bonzini break; 1117baacf047SPaolo Bonzini 1118*6a02c806SStefan Hajnoczi case SOCKET_ADDRESS_KIND_VSOCK: 1119*6a02c806SStefan Hajnoczi fd = vsock_listen_saddr(addr->u.vsock.data, errp); 1120*6a02c806SStefan Hajnoczi break; 1121*6a02c806SStefan Hajnoczi 1122baacf047SPaolo Bonzini default: 1123baacf047SPaolo Bonzini abort(); 1124baacf047SPaolo Bonzini } 1125baacf047SPaolo Bonzini return fd; 1126baacf047SPaolo Bonzini } 1127baacf047SPaolo Bonzini 112874b6ce43SMarc-André Lureau void socket_listen_cleanup(int fd, Error **errp) 112974b6ce43SMarc-André Lureau { 113074b6ce43SMarc-André Lureau SocketAddress *addr; 113174b6ce43SMarc-André Lureau 113274b6ce43SMarc-André Lureau addr = socket_local_address(fd, errp); 113374b6ce43SMarc-André Lureau 113474b6ce43SMarc-André Lureau if (addr->type == SOCKET_ADDRESS_KIND_UNIX 113574b6ce43SMarc-André Lureau && addr->u.q_unix.data->path) { 113674b6ce43SMarc-André Lureau if (unlink(addr->u.q_unix.data->path) < 0 && errno != ENOENT) { 113774b6ce43SMarc-André Lureau error_setg_errno(errp, errno, 113874b6ce43SMarc-André Lureau "Failed to unlink socket %s", 113974b6ce43SMarc-André Lureau addr->u.q_unix.data->path); 114074b6ce43SMarc-André Lureau } 114174b6ce43SMarc-André Lureau } 114274b6ce43SMarc-André Lureau 114373f40c18SMarc-André Lureau qapi_free_SocketAddress(addr); 114474b6ce43SMarc-André Lureau } 114574b6ce43SMarc-André Lureau 11463ecc059dSGerd Hoffmann int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp) 11473ecc059dSGerd Hoffmann { 11483ecc059dSGerd Hoffmann int fd; 11493ecc059dSGerd Hoffmann 11502d32addaSEric Blake switch (remote->type) { 11513ecc059dSGerd Hoffmann case SOCKET_ADDRESS_KIND_INET: 115232bafa8fSEric Blake fd = inet_dgram_saddr(remote->u.inet.data, 115332bafa8fSEric Blake local ? local->u.inet.data : NULL, errp); 11543ecc059dSGerd Hoffmann break; 11553ecc059dSGerd Hoffmann 11563ecc059dSGerd Hoffmann default: 11573ecc059dSGerd Hoffmann error_setg(errp, "socket type unsupported for datagram"); 11587a5b6af1SGerd Hoffmann fd = -1; 11593ecc059dSGerd Hoffmann } 11603ecc059dSGerd Hoffmann return fd; 11613ecc059dSGerd Hoffmann } 116217c55decSDaniel P. Berrange 116317c55decSDaniel P. Berrange 116417c55decSDaniel P. Berrange static SocketAddress * 116517c55decSDaniel P. Berrange socket_sockaddr_to_address_inet(struct sockaddr_storage *sa, 116617c55decSDaniel P. Berrange socklen_t salen, 116717c55decSDaniel P. Berrange Error **errp) 116817c55decSDaniel P. Berrange { 116917c55decSDaniel P. Berrange char host[NI_MAXHOST]; 117017c55decSDaniel P. Berrange char serv[NI_MAXSERV]; 117117c55decSDaniel P. Berrange SocketAddress *addr; 11720399293eSEric Blake InetSocketAddress *inet; 117317c55decSDaniel P. Berrange int ret; 117417c55decSDaniel P. Berrange 117517c55decSDaniel P. Berrange ret = getnameinfo((struct sockaddr *)sa, salen, 117617c55decSDaniel P. Berrange host, sizeof(host), 117717c55decSDaniel P. Berrange serv, sizeof(serv), 117817c55decSDaniel P. Berrange NI_NUMERICHOST | NI_NUMERICSERV); 117917c55decSDaniel P. Berrange if (ret != 0) { 118017c55decSDaniel P. Berrange error_setg(errp, "Cannot format numeric socket address: %s", 118117c55decSDaniel P. Berrange gai_strerror(ret)); 118217c55decSDaniel P. Berrange return NULL; 118317c55decSDaniel P. Berrange } 118417c55decSDaniel P. Berrange 118517c55decSDaniel P. Berrange addr = g_new0(SocketAddress, 1); 11862d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_INET; 118732bafa8fSEric Blake inet = addr->u.inet.data = g_new0(InetSocketAddress, 1); 11880399293eSEric Blake inet->host = g_strdup(host); 11890399293eSEric Blake inet->port = g_strdup(serv); 119017c55decSDaniel P. Berrange if (sa->ss_family == AF_INET) { 11910399293eSEric Blake inet->has_ipv4 = inet->ipv4 = true; 119217c55decSDaniel P. Berrange } else { 11930399293eSEric Blake inet->has_ipv6 = inet->ipv6 = true; 119417c55decSDaniel P. Berrange } 119517c55decSDaniel P. Berrange 119617c55decSDaniel P. Berrange return addr; 119717c55decSDaniel P. Berrange } 119817c55decSDaniel P. Berrange 119917c55decSDaniel P. Berrange 120017c55decSDaniel P. Berrange #ifndef WIN32 120117c55decSDaniel P. Berrange static SocketAddress * 120217c55decSDaniel P. Berrange socket_sockaddr_to_address_unix(struct sockaddr_storage *sa, 120317c55decSDaniel P. Berrange socklen_t salen, 120417c55decSDaniel P. Berrange Error **errp) 120517c55decSDaniel P. Berrange { 120617c55decSDaniel P. Berrange SocketAddress *addr; 120717c55decSDaniel P. Berrange struct sockaddr_un *su = (struct sockaddr_un *)sa; 120817c55decSDaniel P. Berrange 120917c55decSDaniel P. Berrange addr = g_new0(SocketAddress, 1); 12102d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_UNIX; 121132bafa8fSEric Blake addr->u.q_unix.data = g_new0(UnixSocketAddress, 1); 121217c55decSDaniel P. Berrange if (su->sun_path[0]) { 121332bafa8fSEric Blake addr->u.q_unix.data->path = g_strndup(su->sun_path, 121417c55decSDaniel P. Berrange sizeof(su->sun_path)); 121517c55decSDaniel P. Berrange } 121617c55decSDaniel P. Berrange 121717c55decSDaniel P. Berrange return addr; 121817c55decSDaniel P. Berrange } 121917c55decSDaniel P. Berrange #endif /* WIN32 */ 122017c55decSDaniel P. Berrange 1221*6a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 1222*6a02c806SStefan Hajnoczi static SocketAddress * 1223*6a02c806SStefan Hajnoczi socket_sockaddr_to_address_vsock(struct sockaddr_storage *sa, 1224*6a02c806SStefan Hajnoczi socklen_t salen, 1225*6a02c806SStefan Hajnoczi Error **errp) 1226*6a02c806SStefan Hajnoczi { 1227*6a02c806SStefan Hajnoczi SocketAddress *addr; 1228*6a02c806SStefan Hajnoczi VsockSocketAddress *vaddr; 1229*6a02c806SStefan Hajnoczi struct sockaddr_vm *svm = (struct sockaddr_vm *)sa; 1230*6a02c806SStefan Hajnoczi 1231*6a02c806SStefan Hajnoczi addr = g_new0(SocketAddress, 1); 1232*6a02c806SStefan Hajnoczi addr->type = SOCKET_ADDRESS_KIND_VSOCK; 1233*6a02c806SStefan Hajnoczi addr->u.vsock.data = vaddr = g_new0(VsockSocketAddress, 1); 1234*6a02c806SStefan Hajnoczi vaddr->cid = g_strdup_printf("%u", svm->svm_cid); 1235*6a02c806SStefan Hajnoczi vaddr->port = g_strdup_printf("%u", svm->svm_port); 1236*6a02c806SStefan Hajnoczi 1237*6a02c806SStefan Hajnoczi return addr; 1238*6a02c806SStefan Hajnoczi } 1239*6a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 1240*6a02c806SStefan Hajnoczi 1241559607eaSDaniel P. Berrange SocketAddress * 124217c55decSDaniel P. Berrange socket_sockaddr_to_address(struct sockaddr_storage *sa, 124317c55decSDaniel P. Berrange socklen_t salen, 124417c55decSDaniel P. Berrange Error **errp) 124517c55decSDaniel P. Berrange { 124617c55decSDaniel P. Berrange switch (sa->ss_family) { 124717c55decSDaniel P. Berrange case AF_INET: 124817c55decSDaniel P. Berrange case AF_INET6: 124917c55decSDaniel P. Berrange return socket_sockaddr_to_address_inet(sa, salen, errp); 125017c55decSDaniel P. Berrange 125117c55decSDaniel P. Berrange #ifndef WIN32 125217c55decSDaniel P. Berrange case AF_UNIX: 125317c55decSDaniel P. Berrange return socket_sockaddr_to_address_unix(sa, salen, errp); 125417c55decSDaniel P. Berrange #endif /* WIN32 */ 125517c55decSDaniel P. Berrange 1256*6a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 1257*6a02c806SStefan Hajnoczi case AF_VSOCK: 1258*6a02c806SStefan Hajnoczi return socket_sockaddr_to_address_vsock(sa, salen, errp); 1259*6a02c806SStefan Hajnoczi #endif 1260*6a02c806SStefan Hajnoczi 126117c55decSDaniel P. Berrange default: 126217c55decSDaniel P. Berrange error_setg(errp, "socket family %d unsupported", 126317c55decSDaniel P. Berrange sa->ss_family); 126417c55decSDaniel P. Berrange return NULL; 126517c55decSDaniel P. Berrange } 126617c55decSDaniel P. Berrange return 0; 126717c55decSDaniel P. Berrange } 126817c55decSDaniel P. Berrange 126917c55decSDaniel P. Berrange 127017c55decSDaniel P. Berrange SocketAddress *socket_local_address(int fd, Error **errp) 127117c55decSDaniel P. Berrange { 127217c55decSDaniel P. Berrange struct sockaddr_storage ss; 127317c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 127417c55decSDaniel P. Berrange 127517c55decSDaniel P. Berrange if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) { 1276b16a44e1SDaniel P. Berrange error_setg_errno(errp, errno, "%s", 127717c55decSDaniel P. Berrange "Unable to query local socket address"); 127817c55decSDaniel P. Berrange return NULL; 127917c55decSDaniel P. Berrange } 128017c55decSDaniel P. Berrange 128117c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 128217c55decSDaniel P. Berrange } 128317c55decSDaniel P. Berrange 128417c55decSDaniel P. Berrange 128517c55decSDaniel P. Berrange SocketAddress *socket_remote_address(int fd, Error **errp) 128617c55decSDaniel P. Berrange { 128717c55decSDaniel P. Berrange struct sockaddr_storage ss; 128817c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 128917c55decSDaniel P. Berrange 129017c55decSDaniel P. Berrange if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) { 1291b16a44e1SDaniel P. Berrange error_setg_errno(errp, errno, "%s", 129217c55decSDaniel P. Berrange "Unable to query remote socket address"); 129317c55decSDaniel P. Berrange return NULL; 129417c55decSDaniel P. Berrange } 129517c55decSDaniel P. Berrange 129617c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 129717c55decSDaniel P. Berrange } 12982a8e21c7SDaniel P. Berrange 12997e844959SAshijeet Acharya char *socket_address_to_string(struct SocketAddress *addr, Error **errp) 13007e844959SAshijeet Acharya { 13017e844959SAshijeet Acharya char *buf; 13027e844959SAshijeet Acharya InetSocketAddress *inet; 13037e844959SAshijeet Acharya char host_port[INET6_ADDRSTRLEN + 5 + 4]; 13047e844959SAshijeet Acharya 13057e844959SAshijeet Acharya switch (addr->type) { 13067e844959SAshijeet Acharya case SOCKET_ADDRESS_KIND_INET: 13077e844959SAshijeet Acharya inet = addr->u.inet.data; 13087e844959SAshijeet Acharya if (strchr(inet->host, ':') == NULL) { 13097e844959SAshijeet Acharya snprintf(host_port, sizeof(host_port), "%s:%s", inet->host, 13107e844959SAshijeet Acharya inet->port); 13117e844959SAshijeet Acharya buf = g_strdup(host_port); 13127e844959SAshijeet Acharya } else { 13137e844959SAshijeet Acharya snprintf(host_port, sizeof(host_port), "[%s]:%s", inet->host, 13147e844959SAshijeet Acharya inet->port); 13157e844959SAshijeet Acharya buf = g_strdup(host_port); 13167e844959SAshijeet Acharya } 13177e844959SAshijeet Acharya break; 13187e844959SAshijeet Acharya 13197e844959SAshijeet Acharya case SOCKET_ADDRESS_KIND_UNIX: 13207e844959SAshijeet Acharya buf = g_strdup(addr->u.q_unix.data->path); 13217e844959SAshijeet Acharya break; 13227e844959SAshijeet Acharya 13237e844959SAshijeet Acharya case SOCKET_ADDRESS_KIND_FD: 13247e844959SAshijeet Acharya buf = g_strdup(addr->u.fd.data->str); 13257e844959SAshijeet Acharya break; 13267e844959SAshijeet Acharya 1327*6a02c806SStefan Hajnoczi case SOCKET_ADDRESS_KIND_VSOCK: 1328*6a02c806SStefan Hajnoczi buf = g_strdup_printf("%s:%s", 1329*6a02c806SStefan Hajnoczi addr->u.vsock.data->cid, 1330*6a02c806SStefan Hajnoczi addr->u.vsock.data->port); 1331*6a02c806SStefan Hajnoczi break; 1332*6a02c806SStefan Hajnoczi 13337e844959SAshijeet Acharya default: 13347e844959SAshijeet Acharya error_setg(errp, "socket family %d unsupported", 13357e844959SAshijeet Acharya addr->type); 13367e844959SAshijeet Acharya return NULL; 13377e844959SAshijeet Acharya } 13387e844959SAshijeet Acharya return buf; 13397e844959SAshijeet Acharya } 1340