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 206a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 216a02c806SStefan Hajnoczi #include <linux/vm_sockets.h> 226a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 236a02c806SStefan Hajnoczi 24baacf047SPaolo Bonzini #include "monitor/monitor.h" 25bd269ebcSMarkus Armbruster #include "qapi/clone-visitor.h" 26da34e65cSMarkus Armbruster #include "qapi/error.h" 27baacf047SPaolo Bonzini #include "qemu/sockets.h" 28baacf047SPaolo Bonzini #include "qemu/main-loop.h" 29216411b8SMarkus Armbruster #include "qapi/clone-visitor.h" 30b3db211fSDaniel P. Berrange #include "qapi/qobject-input-visitor.h" 31b3db211fSDaniel P. Berrange #include "qapi/qobject-output-visitor.h" 322a8e21c7SDaniel P. Berrange #include "qapi-visit.h" 33f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 34baacf047SPaolo Bonzini 35baacf047SPaolo Bonzini #ifndef AI_ADDRCONFIG 36baacf047SPaolo Bonzini # define AI_ADDRCONFIG 0 37baacf047SPaolo Bonzini #endif 38340849a9SDaniel P. Berrange 393de3d698SWolfgang Bumiller #ifndef AI_V4MAPPED 403de3d698SWolfgang Bumiller # define AI_V4MAPPED 0 413de3d698SWolfgang Bumiller #endif 42baacf047SPaolo Bonzini 436979a813SDaniel P. Berrange #ifndef AI_NUMERICSERV 446979a813SDaniel P. Berrange # define AI_NUMERICSERV 0 456979a813SDaniel P. Berrange #endif 466979a813SDaniel P. Berrange 47baacf047SPaolo Bonzini 48baacf047SPaolo Bonzini static int inet_getport(struct addrinfo *e) 49baacf047SPaolo Bonzini { 50baacf047SPaolo Bonzini struct sockaddr_in *i4; 51baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 52baacf047SPaolo Bonzini 53baacf047SPaolo Bonzini switch (e->ai_family) { 54baacf047SPaolo Bonzini case PF_INET6: 55baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 56baacf047SPaolo Bonzini return ntohs(i6->sin6_port); 57baacf047SPaolo Bonzini case PF_INET: 58baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 59baacf047SPaolo Bonzini return ntohs(i4->sin_port); 60baacf047SPaolo Bonzini default: 61baacf047SPaolo Bonzini return 0; 62baacf047SPaolo Bonzini } 63baacf047SPaolo Bonzini } 64baacf047SPaolo Bonzini 65baacf047SPaolo Bonzini static void inet_setport(struct addrinfo *e, int port) 66baacf047SPaolo Bonzini { 67baacf047SPaolo Bonzini struct sockaddr_in *i4; 68baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 69baacf047SPaolo Bonzini 70baacf047SPaolo Bonzini switch (e->ai_family) { 71baacf047SPaolo Bonzini case PF_INET6: 72baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 73baacf047SPaolo Bonzini i6->sin6_port = htons(port); 74baacf047SPaolo Bonzini break; 75baacf047SPaolo Bonzini case PF_INET: 76baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 77baacf047SPaolo Bonzini i4->sin_port = htons(port); 78baacf047SPaolo Bonzini break; 79baacf047SPaolo Bonzini } 80baacf047SPaolo Bonzini } 81baacf047SPaolo Bonzini 82a589569fSWenchao Xia NetworkAddressFamily inet_netfamily(int family) 83a589569fSWenchao Xia { 84a589569fSWenchao Xia switch (family) { 85a589569fSWenchao Xia case PF_INET6: return NETWORK_ADDRESS_FAMILY_IPV6; 86a589569fSWenchao Xia case PF_INET: return NETWORK_ADDRESS_FAMILY_IPV4; 87a589569fSWenchao Xia case PF_UNIX: return NETWORK_ADDRESS_FAMILY_UNIX; 886a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 896a02c806SStefan Hajnoczi case PF_VSOCK: return NETWORK_ADDRESS_FAMILY_VSOCK; 906a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 91a589569fSWenchao Xia } 92a589569fSWenchao Xia return NETWORK_ADDRESS_FAMILY_UNKNOWN; 93a589569fSWenchao Xia } 94a589569fSWenchao Xia 951856835dSDaniel P. Berrange /* 961856835dSDaniel P. Berrange * Matrix we're trying to apply 971856835dSDaniel P. Berrange * 981856835dSDaniel P. Berrange * ipv4 ipv6 family 991856835dSDaniel P. Berrange * - - PF_UNSPEC 1001856835dSDaniel P. Berrange * - f PF_INET 1011856835dSDaniel P. Berrange * - t PF_INET6 1021856835dSDaniel P. Berrange * f - PF_INET6 1031856835dSDaniel P. Berrange * f f <error> 1041856835dSDaniel P. Berrange * f t PF_INET6 1051856835dSDaniel P. Berrange * t - PF_INET 1061856835dSDaniel P. Berrange * t f PF_INET 10794bc0d19SDaniel P. Berrange * t t PF_INET6/PF_UNSPEC 1081856835dSDaniel P. Berrange * 109d43eda3dSWei Jiangang * NB, this matrix is only about getting the necessary results 1101856835dSDaniel P. Berrange * from getaddrinfo(). Some of the cases require further work 1111856835dSDaniel P. Berrange * after reading results from getaddrinfo in order to fully 11294bc0d19SDaniel P. Berrange * apply the logic the end user wants. 11394bc0d19SDaniel P. Berrange * 11494bc0d19SDaniel P. Berrange * In the first and last cases, we must set IPV6_V6ONLY=0 11594bc0d19SDaniel P. Berrange * when binding, to allow a single listener to potentially 11694bc0d19SDaniel P. Berrange * accept both IPv4+6 addresses. 1171856835dSDaniel P. Berrange */ 118c1b412f1SDaniel P. Berrange int inet_ai_family_from_address(InetSocketAddress *addr, 1191856835dSDaniel P. Berrange Error **errp) 1201856835dSDaniel P. Berrange { 1211856835dSDaniel P. Berrange if (addr->has_ipv6 && addr->has_ipv4 && 1221856835dSDaniel P. Berrange !addr->ipv6 && !addr->ipv4) { 1231856835dSDaniel P. Berrange error_setg(errp, "Cannot disable IPv4 and IPv6 at same time"); 1241856835dSDaniel P. Berrange return PF_UNSPEC; 1251856835dSDaniel P. Berrange } 12694bc0d19SDaniel P. Berrange if ((addr->has_ipv6 && addr->ipv6) && (addr->has_ipv4 && addr->ipv4)) { 12794bc0d19SDaniel P. Berrange /* 12894bc0d19SDaniel P. Berrange * Some backends can only do a single listener. In that case 12994bc0d19SDaniel P. Berrange * we want empty hostname to resolve to "::" and then use the 13094bc0d19SDaniel P. Berrange * flag IPV6_V6ONLY==0 to get both protocols on 1 socket. This 13194bc0d19SDaniel P. Berrange * doesn't work for addresses other than "", so they're just 13294bc0d19SDaniel P. Berrange * inevitably broken until multiple listeners can be used, 13394bc0d19SDaniel P. Berrange * and thus we honour getaddrinfo automatic protocol detection 13494bc0d19SDaniel P. Berrange * Once all backends do multi-listener, remove the PF_INET6 13594bc0d19SDaniel P. Berrange * branch entirely. 13694bc0d19SDaniel P. Berrange */ 13794bc0d19SDaniel P. Berrange if (!addr->host || g_str_equal(addr->host, "")) { 13894bc0d19SDaniel P. Berrange return PF_INET6; 13994bc0d19SDaniel P. Berrange } else { 14094bc0d19SDaniel P. Berrange return PF_UNSPEC; 14194bc0d19SDaniel P. Berrange } 14294bc0d19SDaniel P. Berrange } 1431856835dSDaniel P. Berrange if ((addr->has_ipv6 && addr->ipv6) || (addr->has_ipv4 && !addr->ipv4)) { 1441856835dSDaniel P. Berrange return PF_INET6; 1451856835dSDaniel P. Berrange } 1461856835dSDaniel P. Berrange if ((addr->has_ipv4 && addr->ipv4) || (addr->has_ipv6 && !addr->ipv6)) { 1471856835dSDaniel P. Berrange return PF_INET; 1481856835dSDaniel P. Berrange } 1491856835dSDaniel P. Berrange return PF_UNSPEC; 1501856835dSDaniel P. Berrange } 1511856835dSDaniel P. Berrange 152*89382c3dSKnut Omang static int try_bind(int socket, InetSocketAddress *saddr, struct addrinfo *e) 153*89382c3dSKnut Omang { 154*89382c3dSKnut Omang #ifndef IPV6_V6ONLY 155*89382c3dSKnut Omang return bind(socket, e->ai_addr, e->ai_addrlen); 156*89382c3dSKnut Omang #else 157*89382c3dSKnut Omang /* 158*89382c3dSKnut Omang * Deals with first & last cases in matrix in comment 159*89382c3dSKnut Omang * for inet_ai_family_from_address(). 160*89382c3dSKnut Omang */ 161*89382c3dSKnut Omang int v6only = 162*89382c3dSKnut Omang ((!saddr->has_ipv4 && !saddr->has_ipv6) || 163*89382c3dSKnut Omang (saddr->has_ipv4 && saddr->ipv4 && 164*89382c3dSKnut Omang saddr->has_ipv6 && saddr->ipv6)) ? 0 : 1; 165*89382c3dSKnut Omang int stat; 166*89382c3dSKnut Omang 167*89382c3dSKnut Omang rebind: 168*89382c3dSKnut Omang if (e->ai_family == PF_INET6) { 169*89382c3dSKnut Omang qemu_setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, 170*89382c3dSKnut Omang sizeof(v6only)); 171*89382c3dSKnut Omang } 172*89382c3dSKnut Omang 173*89382c3dSKnut Omang stat = bind(socket, e->ai_addr, e->ai_addrlen); 174*89382c3dSKnut Omang if (!stat) { 175*89382c3dSKnut Omang return 0; 176*89382c3dSKnut Omang } 177*89382c3dSKnut Omang 178*89382c3dSKnut Omang /* If we got EADDRINUSE from an IPv6 bind & v6only is unset, 179*89382c3dSKnut Omang * it could be that the IPv4 port is already claimed, so retry 180*89382c3dSKnut Omang * with v6only set 181*89382c3dSKnut Omang */ 182*89382c3dSKnut Omang if (e->ai_family == PF_INET6 && errno == EADDRINUSE && !v6only) { 183*89382c3dSKnut Omang v6only = 1; 184*89382c3dSKnut Omang goto rebind; 185*89382c3dSKnut Omang } 186*89382c3dSKnut Omang return stat; 187*89382c3dSKnut Omang #endif 188*89382c3dSKnut Omang } 189*89382c3dSKnut Omang 1901856835dSDaniel P. Berrange static int inet_listen_saddr(InetSocketAddress *saddr, 1911856835dSDaniel P. Berrange int port_offset, 1921856835dSDaniel P. Berrange bool update_addr, 1931856835dSDaniel P. Berrange Error **errp) 194baacf047SPaolo Bonzini { 195baacf047SPaolo Bonzini struct addrinfo ai,*res,*e; 196baacf047SPaolo Bonzini char port[33]; 197baacf047SPaolo Bonzini char uaddr[INET6_ADDRSTRLEN+1]; 198baacf047SPaolo Bonzini char uport[33]; 1991856835dSDaniel P. Berrange int slisten, rc, port_min, port_max, p; 2001856835dSDaniel P. Berrange Error *err = NULL; 201baacf047SPaolo Bonzini 202baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 2033de3d698SWolfgang Bumiller ai.ai_flags = AI_PASSIVE; 2046979a813SDaniel P. Berrange if (saddr->has_numeric && saddr->numeric) { 2056979a813SDaniel P. Berrange ai.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV; 2066979a813SDaniel P. Berrange } 2071856835dSDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(saddr, &err); 208baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 209baacf047SPaolo Bonzini 2101856835dSDaniel P. Berrange if (err) { 2111856835dSDaniel P. Berrange error_propagate(errp, err); 2121856835dSDaniel P. Berrange return -1; 2131856835dSDaniel P. Berrange } 2141856835dSDaniel P. Berrange 2151856835dSDaniel P. Berrange if (saddr->host == NULL) { 2160983f5e6SDaniel P. Berrange error_setg(errp, "host not specified"); 217baacf047SPaolo Bonzini return -1; 218baacf047SPaolo Bonzini } 2191856835dSDaniel P. Berrange if (saddr->port != NULL) { 2201856835dSDaniel P. Berrange pstrcpy(port, sizeof(port), saddr->port); 2210983f5e6SDaniel P. Berrange } else { 2220983f5e6SDaniel P. Berrange port[0] = '\0'; 2230983f5e6SDaniel P. Berrange } 224baacf047SPaolo Bonzini 225baacf047SPaolo Bonzini /* lookup */ 2268bc89127SGerd Hoffmann if (port_offset) { 2278bc89127SGerd Hoffmann unsigned long long baseport; 2280983f5e6SDaniel P. Berrange if (strlen(port) == 0) { 2290983f5e6SDaniel P. Berrange error_setg(errp, "port not specified"); 2300983f5e6SDaniel P. Berrange return -1; 2310983f5e6SDaniel P. Berrange } 2328bc89127SGerd Hoffmann if (parse_uint_full(port, &baseport, 10) < 0) { 2338bc89127SGerd Hoffmann error_setg(errp, "can't convert to a number: %s", port); 2348bc89127SGerd Hoffmann return -1; 2358bc89127SGerd Hoffmann } 2368bc89127SGerd Hoffmann if (baseport > 65535 || 2378bc89127SGerd Hoffmann baseport + port_offset > 65535) { 2388bc89127SGerd Hoffmann error_setg(errp, "port %s out of range", port); 2398bc89127SGerd Hoffmann return -1; 2408bc89127SGerd Hoffmann } 2418bc89127SGerd Hoffmann snprintf(port, sizeof(port), "%d", (int)baseport + port_offset); 2428bc89127SGerd Hoffmann } 2431856835dSDaniel P. Berrange rc = getaddrinfo(strlen(saddr->host) ? saddr->host : NULL, 2440983f5e6SDaniel P. Berrange strlen(port) ? port : NULL, &ai, &res); 245baacf047SPaolo Bonzini if (rc != 0) { 2461856835dSDaniel P. Berrange error_setg(errp, "address resolution failed for %s:%s: %s", 2471856835dSDaniel P. Berrange saddr->host, port, gai_strerror(rc)); 248baacf047SPaolo Bonzini return -1; 249baacf047SPaolo Bonzini } 250baacf047SPaolo Bonzini 251baacf047SPaolo Bonzini /* create socket + bind */ 252baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 253baacf047SPaolo Bonzini getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, 254baacf047SPaolo Bonzini uaddr,INET6_ADDRSTRLEN,uport,32, 255baacf047SPaolo Bonzini NI_NUMERICHOST | NI_NUMERICSERV); 256baacf047SPaolo Bonzini slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); 257baacf047SPaolo Bonzini if (slisten < 0) { 258baacf047SPaolo Bonzini if (!e->ai_next) { 259235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 260baacf047SPaolo Bonzini } 261baacf047SPaolo Bonzini continue; 262baacf047SPaolo Bonzini } 263baacf047SPaolo Bonzini 26404fd1c78SSebastian Ottlik socket_set_fast_reuse(slisten); 265baacf047SPaolo Bonzini 266baacf047SPaolo Bonzini port_min = inet_getport(e); 2671856835dSDaniel P. Berrange port_max = saddr->has_to ? saddr->to + port_offset : port_min; 268baacf047SPaolo Bonzini for (p = port_min; p <= port_max; p++) { 269baacf047SPaolo Bonzini inet_setport(e, p); 270*89382c3dSKnut Omang if (try_bind(slisten, saddr, e) >= 0) { 271baacf047SPaolo Bonzini goto listen; 272baacf047SPaolo Bonzini } 273baacf047SPaolo Bonzini if (p == port_max) { 274baacf047SPaolo Bonzini if (!e->ai_next) { 275235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to bind socket"); 276baacf047SPaolo Bonzini } 277baacf047SPaolo Bonzini } 278baacf047SPaolo Bonzini } 279baacf047SPaolo Bonzini closesocket(slisten); 280baacf047SPaolo Bonzini } 281baacf047SPaolo Bonzini freeaddrinfo(res); 282baacf047SPaolo Bonzini return -1; 283baacf047SPaolo Bonzini 284baacf047SPaolo Bonzini listen: 285baacf047SPaolo Bonzini if (listen(slisten,1) != 0) { 286235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to listen on socket"); 287baacf047SPaolo Bonzini closesocket(slisten); 288baacf047SPaolo Bonzini freeaddrinfo(res); 289baacf047SPaolo Bonzini return -1; 290baacf047SPaolo Bonzini } 2911856835dSDaniel P. Berrange if (update_addr) { 2921856835dSDaniel P. Berrange g_free(saddr->host); 2931856835dSDaniel P. Berrange saddr->host = g_strdup(uaddr); 2941856835dSDaniel P. Berrange g_free(saddr->port); 2951856835dSDaniel P. Berrange saddr->port = g_strdup_printf("%d", 2961856835dSDaniel P. Berrange inet_getport(e) - port_offset); 2971856835dSDaniel P. Berrange saddr->has_ipv6 = saddr->ipv6 = e->ai_family == PF_INET6; 2981856835dSDaniel P. Berrange saddr->has_ipv4 = saddr->ipv4 = e->ai_family != PF_INET6; 2991856835dSDaniel P. Berrange } 300baacf047SPaolo Bonzini freeaddrinfo(res); 301baacf047SPaolo Bonzini return slisten; 302baacf047SPaolo Bonzini } 303baacf047SPaolo Bonzini 304baacf047SPaolo Bonzini #ifdef _WIN32 305baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 306baacf047SPaolo Bonzini ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY) 307baacf047SPaolo Bonzini #else 308baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 309baacf047SPaolo Bonzini ((rc) == -EINPROGRESS) 310baacf047SPaolo Bonzini #endif 311baacf047SPaolo Bonzini 312b2587932SCao jin static int inet_connect_addr(struct addrinfo *addr, Error **errp); 313baacf047SPaolo Bonzini 314b2587932SCao jin static int inet_connect_addr(struct addrinfo *addr, Error **errp) 315baacf047SPaolo Bonzini { 316baacf047SPaolo Bonzini int sock, rc; 317baacf047SPaolo Bonzini 318baacf047SPaolo Bonzini sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); 319baacf047SPaolo Bonzini if (sock < 0) { 320235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 321baacf047SPaolo Bonzini return -1; 322baacf047SPaolo Bonzini } 32304fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 324b2587932SCao jin 325baacf047SPaolo Bonzini /* connect to peer */ 326baacf047SPaolo Bonzini do { 327baacf047SPaolo Bonzini rc = 0; 328baacf047SPaolo Bonzini if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) { 329b16a44e1SDaniel P. Berrange rc = -errno; 330baacf047SPaolo Bonzini } 331baacf047SPaolo Bonzini } while (rc == -EINTR); 332baacf047SPaolo Bonzini 333b2587932SCao jin if (rc < 0) { 334235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to connect socket"); 335baacf047SPaolo Bonzini closesocket(sock); 336baacf047SPaolo Bonzini return -1; 337baacf047SPaolo Bonzini } 338b2587932SCao jin 339baacf047SPaolo Bonzini return sock; 340baacf047SPaolo Bonzini } 341baacf047SPaolo Bonzini 3422942e420SDaniel P. Berrange static struct addrinfo *inet_parse_connect_saddr(InetSocketAddress *saddr, 3432942e420SDaniel P. Berrange Error **errp) 344baacf047SPaolo Bonzini { 345baacf047SPaolo Bonzini struct addrinfo ai, *res; 346baacf047SPaolo Bonzini int rc; 3472942e420SDaniel P. Berrange Error *err = NULL; 348340849a9SDaniel P. Berrange static int useV4Mapped = 1; 349baacf047SPaolo Bonzini 350baacf047SPaolo Bonzini memset(&ai, 0, sizeof(ai)); 351baacf047SPaolo Bonzini 352340849a9SDaniel P. Berrange ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; 353340849a9SDaniel P. Berrange if (atomic_read(&useV4Mapped)) { 354340849a9SDaniel P. Berrange ai.ai_flags |= AI_V4MAPPED; 355340849a9SDaniel P. Berrange } 3562942e420SDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(saddr, &err); 357baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 358baacf047SPaolo Bonzini 3592942e420SDaniel P. Berrange if (err) { 3602942e420SDaniel P. Berrange error_propagate(errp, err); 3612942e420SDaniel P. Berrange return NULL; 3622942e420SDaniel P. Berrange } 3632942e420SDaniel P. Berrange 3642942e420SDaniel P. Berrange if (saddr->host == NULL || saddr->port == NULL) { 365baacf047SPaolo Bonzini error_setg(errp, "host and/or port not specified"); 366baacf047SPaolo Bonzini return NULL; 367baacf047SPaolo Bonzini } 368baacf047SPaolo Bonzini 369baacf047SPaolo Bonzini /* lookup */ 3702942e420SDaniel P. Berrange rc = getaddrinfo(saddr->host, saddr->port, &ai, &res); 371340849a9SDaniel P. Berrange 372340849a9SDaniel P. Berrange /* At least FreeBSD and OS-X 10.6 declare AI_V4MAPPED but 373340849a9SDaniel P. Berrange * then don't implement it in their getaddrinfo(). Detect 374340849a9SDaniel P. Berrange * this and retry without the flag since that's preferrable 375340849a9SDaniel P. Berrange * to a fatal error 376340849a9SDaniel P. Berrange */ 377340849a9SDaniel P. Berrange if (rc == EAI_BADFLAGS && 378340849a9SDaniel P. Berrange (ai.ai_flags & AI_V4MAPPED)) { 379340849a9SDaniel P. Berrange atomic_set(&useV4Mapped, 0); 380340849a9SDaniel P. Berrange ai.ai_flags &= ~AI_V4MAPPED; 381340849a9SDaniel P. Berrange rc = getaddrinfo(saddr->host, saddr->port, &ai, &res); 382340849a9SDaniel P. Berrange } 383baacf047SPaolo Bonzini if (rc != 0) { 3842942e420SDaniel P. Berrange error_setg(errp, "address resolution failed for %s:%s: %s", 3852942e420SDaniel P. Berrange saddr->host, saddr->port, gai_strerror(rc)); 386baacf047SPaolo Bonzini return NULL; 387baacf047SPaolo Bonzini } 388baacf047SPaolo Bonzini return res; 389baacf047SPaolo Bonzini } 390baacf047SPaolo Bonzini 391baacf047SPaolo Bonzini /** 392baacf047SPaolo Bonzini * Create a socket and connect it to an address. 393baacf047SPaolo Bonzini * 3942942e420SDaniel P. Berrange * @saddr: Inet socket address specification 395baacf047SPaolo Bonzini * @errp: set on error 396baacf047SPaolo Bonzini * 397baacf047SPaolo Bonzini * Returns: -1 on error, file descriptor on success. 398baacf047SPaolo Bonzini */ 399b2587932SCao jin int inet_connect_saddr(InetSocketAddress *saddr, Error **errp) 400baacf047SPaolo Bonzini { 4013f9286b7SMarkus Armbruster Error *local_err = NULL; 402baacf047SPaolo Bonzini struct addrinfo *res, *e; 403baacf047SPaolo Bonzini int sock = -1; 404baacf047SPaolo Bonzini 4052942e420SDaniel P. Berrange res = inet_parse_connect_saddr(saddr, errp); 406baacf047SPaolo Bonzini if (!res) { 407baacf047SPaolo Bonzini return -1; 408baacf047SPaolo Bonzini } 409baacf047SPaolo Bonzini 410baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 4113f9286b7SMarkus Armbruster error_free(local_err); 4123f9286b7SMarkus Armbruster local_err = NULL; 413b2587932SCao jin sock = inet_connect_addr(e, &local_err); 4143f9286b7SMarkus Armbruster if (sock >= 0) { 415baacf047SPaolo Bonzini break; 416baacf047SPaolo Bonzini } 417baacf047SPaolo Bonzini } 4183f9286b7SMarkus Armbruster 4193f9286b7SMarkus Armbruster if (sock < 0) { 4203f9286b7SMarkus Armbruster error_propagate(errp, local_err); 4213f9286b7SMarkus Armbruster } 422b2587932SCao jin 423baacf047SPaolo Bonzini freeaddrinfo(res); 424baacf047SPaolo Bonzini return sock; 425baacf047SPaolo Bonzini } 426baacf047SPaolo Bonzini 4278b39910eSDaniel P. Berrange static int inet_dgram_saddr(InetSocketAddress *sraddr, 4288b39910eSDaniel P. Berrange InetSocketAddress *sladdr, 4298b39910eSDaniel P. Berrange Error **errp) 430baacf047SPaolo Bonzini { 431baacf047SPaolo Bonzini struct addrinfo ai, *peer = NULL, *local = NULL; 432baacf047SPaolo Bonzini const char *addr; 433baacf047SPaolo Bonzini const char *port; 434baacf047SPaolo Bonzini int sock = -1, rc; 4358b39910eSDaniel P. Berrange Error *err = NULL; 436baacf047SPaolo Bonzini 437baacf047SPaolo Bonzini /* lookup peer addr */ 438baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 4393de3d698SWolfgang Bumiller ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG; 4408b39910eSDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(sraddr, &err); 441baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 442baacf047SPaolo Bonzini 4438b39910eSDaniel P. Berrange if (err) { 4448b39910eSDaniel P. Berrange error_propagate(errp, err); 44558c652c0SPaolo Bonzini goto err; 4468b39910eSDaniel P. Berrange } 4478b39910eSDaniel P. Berrange 4488b39910eSDaniel P. Berrange addr = sraddr->host; 4498b39910eSDaniel P. Berrange port = sraddr->port; 450baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 451baacf047SPaolo Bonzini addr = "localhost"; 452baacf047SPaolo Bonzini } 453baacf047SPaolo Bonzini if (port == NULL || strlen(port) == 0) { 454baacf047SPaolo Bonzini error_setg(errp, "remote port not specified"); 45558c652c0SPaolo Bonzini goto err; 456baacf047SPaolo Bonzini } 457baacf047SPaolo Bonzini 4589cd1883cSCao jin if ((rc = getaddrinfo(addr, port, &ai, &peer)) != 0) { 459baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 460baacf047SPaolo Bonzini gai_strerror(rc)); 46158c652c0SPaolo Bonzini goto err; 462baacf047SPaolo Bonzini } 463baacf047SPaolo Bonzini 464baacf047SPaolo Bonzini /* lookup local addr */ 465baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 466baacf047SPaolo Bonzini ai.ai_flags = AI_PASSIVE; 467baacf047SPaolo Bonzini ai.ai_family = peer->ai_family; 468baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 469baacf047SPaolo Bonzini 4708b39910eSDaniel P. Berrange if (sladdr) { 4718b39910eSDaniel P. Berrange addr = sladdr->host; 4728b39910eSDaniel P. Berrange port = sladdr->port; 473baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 474baacf047SPaolo Bonzini addr = NULL; 475baacf047SPaolo Bonzini } 4768b39910eSDaniel P. Berrange if (!port || strlen(port) == 0) { 477baacf047SPaolo Bonzini port = "0"; 4788b39910eSDaniel P. Berrange } 4798b39910eSDaniel P. Berrange } else { 4808b39910eSDaniel P. Berrange addr = NULL; 4818b39910eSDaniel P. Berrange port = "0"; 4828b39910eSDaniel P. Berrange } 483baacf047SPaolo Bonzini 4849cd1883cSCao jin if ((rc = getaddrinfo(addr, port, &ai, &local)) != 0) { 485baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 486baacf047SPaolo Bonzini gai_strerror(rc)); 487baacf047SPaolo Bonzini goto err; 488baacf047SPaolo Bonzini } 489baacf047SPaolo Bonzini 490baacf047SPaolo Bonzini /* create socket */ 491baacf047SPaolo Bonzini sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); 492baacf047SPaolo Bonzini if (sock < 0) { 493235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 494baacf047SPaolo Bonzini goto err; 495baacf047SPaolo Bonzini } 49604fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 497baacf047SPaolo Bonzini 498baacf047SPaolo Bonzini /* bind socket */ 499baacf047SPaolo Bonzini if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { 500235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to bind socket"); 501baacf047SPaolo Bonzini goto err; 502baacf047SPaolo Bonzini } 503baacf047SPaolo Bonzini 504baacf047SPaolo Bonzini /* connect to peer */ 505baacf047SPaolo Bonzini if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { 506235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to connect socket"); 507baacf047SPaolo Bonzini goto err; 508baacf047SPaolo Bonzini } 509baacf047SPaolo Bonzini 510baacf047SPaolo Bonzini freeaddrinfo(local); 511baacf047SPaolo Bonzini freeaddrinfo(peer); 512baacf047SPaolo Bonzini return sock; 513baacf047SPaolo Bonzini 514baacf047SPaolo Bonzini err: 51526015051SCao jin if (sock != -1) { 516baacf047SPaolo Bonzini closesocket(sock); 51726015051SCao jin } 51826015051SCao jin if (local) { 519baacf047SPaolo Bonzini freeaddrinfo(local); 52026015051SCao jin } 52126015051SCao jin if (peer) { 522baacf047SPaolo Bonzini freeaddrinfo(peer); 52326015051SCao jin } 52426015051SCao jin 525baacf047SPaolo Bonzini return -1; 526baacf047SPaolo Bonzini } 527baacf047SPaolo Bonzini 528baacf047SPaolo Bonzini /* compatibility wrapper */ 5290785bd7aSMarkus Armbruster int inet_parse(InetSocketAddress *addr, const char *str, Error **errp) 530baacf047SPaolo Bonzini { 531baacf047SPaolo Bonzini const char *optstr, *h; 53255a10996SKevin Wolf char host[65]; 533baacf047SPaolo Bonzini char port[33]; 534baacf047SPaolo Bonzini int to; 535baacf047SPaolo Bonzini int pos; 536baacf047SPaolo Bonzini 5370785bd7aSMarkus Armbruster memset(addr, 0, sizeof(*addr)); 538baacf047SPaolo Bonzini 539baacf047SPaolo Bonzini /* parse address */ 540baacf047SPaolo Bonzini if (str[0] == ':') { 541baacf047SPaolo Bonzini /* no host given */ 542baacf047SPaolo Bonzini host[0] = '\0'; 5439cd1883cSCao jin if (sscanf(str, ":%32[^,]%n", port, &pos) != 1) { 544baacf047SPaolo Bonzini error_setg(errp, "error parsing port in address '%s'", str); 5450785bd7aSMarkus Armbruster return -1; 546baacf047SPaolo Bonzini } 547baacf047SPaolo Bonzini } else if (str[0] == '[') { 548baacf047SPaolo Bonzini /* IPv6 addr */ 5499cd1883cSCao jin if (sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos) != 2) { 550baacf047SPaolo Bonzini error_setg(errp, "error parsing IPv6 address '%s'", str); 5510785bd7aSMarkus Armbruster return -1; 552baacf047SPaolo Bonzini } 553baacf047SPaolo Bonzini } else { 554391b7b97SJán Tomko /* hostname or IPv4 addr */ 5559cd1883cSCao jin if (sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos) != 2) { 556baacf047SPaolo Bonzini error_setg(errp, "error parsing address '%s'", str); 5570785bd7aSMarkus Armbruster return -1; 558baacf047SPaolo Bonzini } 559baacf047SPaolo Bonzini } 560baacf047SPaolo Bonzini 561baacf047SPaolo Bonzini addr->host = g_strdup(host); 562baacf047SPaolo Bonzini addr->port = g_strdup(port); 563baacf047SPaolo Bonzini 564baacf047SPaolo Bonzini /* parse options */ 565baacf047SPaolo Bonzini optstr = str + pos; 566baacf047SPaolo Bonzini h = strstr(optstr, ",to="); 567baacf047SPaolo Bonzini if (h) { 568baacf047SPaolo Bonzini h += 4; 569baacf047SPaolo Bonzini if (sscanf(h, "%d%n", &to, &pos) != 1 || 570baacf047SPaolo Bonzini (h[pos] != '\0' && h[pos] != ',')) { 571baacf047SPaolo Bonzini error_setg(errp, "error parsing to= argument"); 5720785bd7aSMarkus Armbruster return -1; 573baacf047SPaolo Bonzini } 574baacf047SPaolo Bonzini addr->has_to = true; 575baacf047SPaolo Bonzini addr->to = to; 576baacf047SPaolo Bonzini } 577baacf047SPaolo Bonzini if (strstr(optstr, ",ipv4")) { 578baacf047SPaolo Bonzini addr->ipv4 = addr->has_ipv4 = true; 579baacf047SPaolo Bonzini } 580baacf047SPaolo Bonzini if (strstr(optstr, ",ipv6")) { 581baacf047SPaolo Bonzini addr->ipv6 = addr->has_ipv6 = true; 582baacf047SPaolo Bonzini } 5830785bd7aSMarkus Armbruster return 0; 584baacf047SPaolo Bonzini } 585baacf047SPaolo Bonzini 586baacf047SPaolo Bonzini 587baacf047SPaolo Bonzini /** 588baacf047SPaolo Bonzini * Create a blocking socket and connect it to an address. 589baacf047SPaolo Bonzini * 590baacf047SPaolo Bonzini * @str: address string 591baacf047SPaolo Bonzini * @errp: set in case of an error 592baacf047SPaolo Bonzini * 593baacf047SPaolo Bonzini * Returns -1 in case of error, file descriptor on success 594baacf047SPaolo Bonzini **/ 595baacf047SPaolo Bonzini int inet_connect(const char *str, Error **errp) 596baacf047SPaolo Bonzini { 597baacf047SPaolo Bonzini int sock = -1; 5980785bd7aSMarkus Armbruster InetSocketAddress *addr = g_new(InetSocketAddress, 1); 599baacf047SPaolo Bonzini 6000785bd7aSMarkus Armbruster if (!inet_parse(addr, str, errp)) { 601b2587932SCao jin sock = inet_connect_saddr(addr, errp); 602baacf047SPaolo Bonzini } 6030785bd7aSMarkus Armbruster qapi_free_InetSocketAddress(addr); 604baacf047SPaolo Bonzini return sock; 605baacf047SPaolo Bonzini } 606baacf047SPaolo Bonzini 6076a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 6086a02c806SStefan Hajnoczi static bool vsock_parse_vaddr_to_sockaddr(const VsockSocketAddress *vaddr, 6096a02c806SStefan Hajnoczi struct sockaddr_vm *svm, 6106a02c806SStefan Hajnoczi Error **errp) 6116a02c806SStefan Hajnoczi { 6126a02c806SStefan Hajnoczi unsigned long long val; 6136a02c806SStefan Hajnoczi 6146a02c806SStefan Hajnoczi memset(svm, 0, sizeof(*svm)); 6156a02c806SStefan Hajnoczi svm->svm_family = AF_VSOCK; 6166a02c806SStefan Hajnoczi 6176a02c806SStefan Hajnoczi if (parse_uint_full(vaddr->cid, &val, 10) < 0 || 6186a02c806SStefan Hajnoczi val > UINT32_MAX) { 6196a02c806SStefan Hajnoczi error_setg(errp, "Failed to parse cid '%s'", vaddr->cid); 6206a02c806SStefan Hajnoczi return false; 6216a02c806SStefan Hajnoczi } 6226a02c806SStefan Hajnoczi svm->svm_cid = val; 6236a02c806SStefan Hajnoczi 6246a02c806SStefan Hajnoczi if (parse_uint_full(vaddr->port, &val, 10) < 0 || 6256a02c806SStefan Hajnoczi val > UINT32_MAX) { 6266a02c806SStefan Hajnoczi error_setg(errp, "Failed to parse port '%s'", vaddr->port); 6276a02c806SStefan Hajnoczi return false; 6286a02c806SStefan Hajnoczi } 6296a02c806SStefan Hajnoczi svm->svm_port = val; 6306a02c806SStefan Hajnoczi 6316a02c806SStefan Hajnoczi return true; 6326a02c806SStefan Hajnoczi } 6336a02c806SStefan Hajnoczi 634b2587932SCao jin static int vsock_connect_addr(const struct sockaddr_vm *svm, Error **errp) 6356a02c806SStefan Hajnoczi { 6366a02c806SStefan Hajnoczi int sock, rc; 6376a02c806SStefan Hajnoczi 6386a02c806SStefan Hajnoczi sock = qemu_socket(AF_VSOCK, SOCK_STREAM, 0); 6396a02c806SStefan Hajnoczi if (sock < 0) { 6406a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to create socket"); 6416a02c806SStefan Hajnoczi return -1; 6426a02c806SStefan Hajnoczi } 643b2587932SCao jin 6446a02c806SStefan Hajnoczi /* connect to peer */ 6456a02c806SStefan Hajnoczi do { 6466a02c806SStefan Hajnoczi rc = 0; 6476a02c806SStefan Hajnoczi if (connect(sock, (const struct sockaddr *)svm, sizeof(*svm)) < 0) { 6486a02c806SStefan Hajnoczi rc = -errno; 6496a02c806SStefan Hajnoczi } 6506a02c806SStefan Hajnoczi } while (rc == -EINTR); 6516a02c806SStefan Hajnoczi 652b2587932SCao jin if (rc < 0) { 6536a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to connect socket"); 6546a02c806SStefan Hajnoczi closesocket(sock); 6556a02c806SStefan Hajnoczi return -1; 6566a02c806SStefan Hajnoczi } 657b2587932SCao jin 6586a02c806SStefan Hajnoczi return sock; 6596a02c806SStefan Hajnoczi } 6606a02c806SStefan Hajnoczi 661b2587932SCao jin static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp) 6626a02c806SStefan Hajnoczi { 6636a02c806SStefan Hajnoczi struct sockaddr_vm svm; 6646a02c806SStefan Hajnoczi int sock = -1; 6656a02c806SStefan Hajnoczi 6666a02c806SStefan Hajnoczi if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) { 6676a02c806SStefan Hajnoczi return -1; 6686a02c806SStefan Hajnoczi } 6696a02c806SStefan Hajnoczi 670b2587932SCao jin sock = vsock_connect_addr(&svm, errp); 6716a02c806SStefan Hajnoczi 6726a02c806SStefan Hajnoczi return sock; 6736a02c806SStefan Hajnoczi } 6746a02c806SStefan Hajnoczi 6756a02c806SStefan Hajnoczi static int vsock_listen_saddr(VsockSocketAddress *vaddr, 6766a02c806SStefan Hajnoczi Error **errp) 6776a02c806SStefan Hajnoczi { 6786a02c806SStefan Hajnoczi struct sockaddr_vm svm; 6796a02c806SStefan Hajnoczi int slisten; 6806a02c806SStefan Hajnoczi 6816a02c806SStefan Hajnoczi if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) { 6826a02c806SStefan Hajnoczi return -1; 6836a02c806SStefan Hajnoczi } 6846a02c806SStefan Hajnoczi 6856a02c806SStefan Hajnoczi slisten = qemu_socket(AF_VSOCK, SOCK_STREAM, 0); 6866a02c806SStefan Hajnoczi if (slisten < 0) { 6876a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to create socket"); 6886a02c806SStefan Hajnoczi return -1; 6896a02c806SStefan Hajnoczi } 6906a02c806SStefan Hajnoczi 6916a02c806SStefan Hajnoczi if (bind(slisten, (const struct sockaddr *)&svm, sizeof(svm)) != 0) { 6926a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to bind socket"); 6936a02c806SStefan Hajnoczi closesocket(slisten); 6946a02c806SStefan Hajnoczi return -1; 6956a02c806SStefan Hajnoczi } 6966a02c806SStefan Hajnoczi 6976a02c806SStefan Hajnoczi if (listen(slisten, 1) != 0) { 6986a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to listen on socket"); 6996a02c806SStefan Hajnoczi closesocket(slisten); 7006a02c806SStefan Hajnoczi return -1; 7016a02c806SStefan Hajnoczi } 7026a02c806SStefan Hajnoczi return slisten; 7036a02c806SStefan Hajnoczi } 7046a02c806SStefan Hajnoczi 7054db5c619SMarkus Armbruster static int vsock_parse(VsockSocketAddress *addr, const char *str, 7064db5c619SMarkus Armbruster Error **errp) 7076a02c806SStefan Hajnoczi { 7086a02c806SStefan Hajnoczi char cid[33]; 7096a02c806SStefan Hajnoczi char port[33]; 7106a02c806SStefan Hajnoczi int n; 7116a02c806SStefan Hajnoczi 7126a02c806SStefan Hajnoczi if (sscanf(str, "%32[^:]:%32[^,]%n", cid, port, &n) != 2) { 7136a02c806SStefan Hajnoczi error_setg(errp, "error parsing address '%s'", str); 7144db5c619SMarkus Armbruster return -1; 7156a02c806SStefan Hajnoczi } 7166a02c806SStefan Hajnoczi if (str[n] != '\0') { 7176a02c806SStefan Hajnoczi error_setg(errp, "trailing characters in address '%s'", str); 7184db5c619SMarkus Armbruster return -1; 7196a02c806SStefan Hajnoczi } 7206a02c806SStefan Hajnoczi 7216a02c806SStefan Hajnoczi addr->cid = g_strdup(cid); 7226a02c806SStefan Hajnoczi addr->port = g_strdup(port); 7234db5c619SMarkus Armbruster return 0; 7246a02c806SStefan Hajnoczi } 7256a02c806SStefan Hajnoczi #else 7266a02c806SStefan Hajnoczi static void vsock_unsupported(Error **errp) 7276a02c806SStefan Hajnoczi { 7286a02c806SStefan Hajnoczi error_setg(errp, "socket family AF_VSOCK unsupported"); 7296a02c806SStefan Hajnoczi } 7306a02c806SStefan Hajnoczi 731b2587932SCao jin static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp) 7326a02c806SStefan Hajnoczi { 7336a02c806SStefan Hajnoczi vsock_unsupported(errp); 7346a02c806SStefan Hajnoczi return -1; 7356a02c806SStefan Hajnoczi } 7366a02c806SStefan Hajnoczi 7376a02c806SStefan Hajnoczi static int vsock_listen_saddr(VsockSocketAddress *vaddr, 7386a02c806SStefan Hajnoczi Error **errp) 7396a02c806SStefan Hajnoczi { 7406a02c806SStefan Hajnoczi vsock_unsupported(errp); 7416a02c806SStefan Hajnoczi return -1; 7426a02c806SStefan Hajnoczi } 7436a02c806SStefan Hajnoczi 7444db5c619SMarkus Armbruster static int vsock_parse(VsockSocketAddress *addr, const char *str, 7454db5c619SMarkus Armbruster Error **errp) 7466a02c806SStefan Hajnoczi { 7476a02c806SStefan Hajnoczi vsock_unsupported(errp); 7484db5c619SMarkus Armbruster return -1; 7496a02c806SStefan Hajnoczi } 7506a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 7516a02c806SStefan Hajnoczi 752baacf047SPaolo Bonzini #ifndef _WIN32 753baacf047SPaolo Bonzini 7541856835dSDaniel P. Berrange static int unix_listen_saddr(UnixSocketAddress *saddr, 7551856835dSDaniel P. Berrange bool update_addr, 7561856835dSDaniel P. Berrange Error **errp) 757baacf047SPaolo Bonzini { 758baacf047SPaolo Bonzini struct sockaddr_un un; 759baacf047SPaolo Bonzini int sock, fd; 760ad9579aaSDaniel P. Berrange char *pathbuf = NULL; 761ad9579aaSDaniel P. Berrange const char *path; 762baacf047SPaolo Bonzini 763baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 764baacf047SPaolo Bonzini if (sock < 0) { 765b658c53dSPaolo Bonzini error_setg_errno(errp, errno, "Failed to create Unix socket"); 766baacf047SPaolo Bonzini return -1; 767baacf047SPaolo Bonzini } 768baacf047SPaolo Bonzini 769ad9579aaSDaniel P. Berrange if (saddr->path && saddr->path[0]) { 770ad9579aaSDaniel P. Berrange path = saddr->path; 771baacf047SPaolo Bonzini } else { 772b658c53dSPaolo Bonzini const char *tmpdir = getenv("TMPDIR"); 773b658c53dSPaolo Bonzini tmpdir = tmpdir ? tmpdir : "/tmp"; 774ad9579aaSDaniel P. Berrange path = pathbuf = g_strdup_printf("%s/qemu-socket-XXXXXX", tmpdir); 775ad9579aaSDaniel P. Berrange } 776ad9579aaSDaniel P. Berrange 777ad9579aaSDaniel P. Berrange if (strlen(path) > sizeof(un.sun_path)) { 778ad9579aaSDaniel P. Berrange error_setg(errp, "UNIX socket path '%s' is too long", path); 779ad9579aaSDaniel P. Berrange error_append_hint(errp, "Path must be less than %zu bytes\n", 780ad9579aaSDaniel P. Berrange sizeof(un.sun_path)); 781b658c53dSPaolo Bonzini goto err; 782b658c53dSPaolo Bonzini } 783b658c53dSPaolo Bonzini 784ad9579aaSDaniel P. Berrange if (pathbuf != NULL) { 785baacf047SPaolo Bonzini /* 786baacf047SPaolo Bonzini * This dummy fd usage silences the mktemp() unsecure warning. 787baacf047SPaolo Bonzini * Using mkstemp() doesn't make things more secure here 788baacf047SPaolo Bonzini * though. bind() complains about existing files, so we have 789baacf047SPaolo Bonzini * to unlink first and thus re-open the race window. The 790baacf047SPaolo Bonzini * worst case possible is bind() failing, i.e. a DoS attack. 791baacf047SPaolo Bonzini */ 792ad9579aaSDaniel P. Berrange fd = mkstemp(pathbuf); 793b658c53dSPaolo Bonzini if (fd < 0) { 794b658c53dSPaolo Bonzini error_setg_errno(errp, errno, 795ad9579aaSDaniel P. Berrange "Failed to make a temporary socket %s", pathbuf); 796b658c53dSPaolo Bonzini goto err; 797b658c53dSPaolo Bonzini } 798b658c53dSPaolo Bonzini close(fd); 799baacf047SPaolo Bonzini } 800baacf047SPaolo Bonzini 801ad9579aaSDaniel P. Berrange if (unlink(path) < 0 && errno != ENOENT) { 8020ef705a2SCole Robinson error_setg_errno(errp, errno, 803ad9579aaSDaniel P. Berrange "Failed to unlink socket %s", path); 8040ef705a2SCole Robinson goto err; 8050ef705a2SCole Robinson } 806ad9579aaSDaniel P. Berrange 807ad9579aaSDaniel P. Berrange memset(&un, 0, sizeof(un)); 808ad9579aaSDaniel P. Berrange un.sun_family = AF_UNIX; 809ad9579aaSDaniel P. Berrange strncpy(un.sun_path, path, sizeof(un.sun_path)); 810ad9579aaSDaniel P. Berrange 811baacf047SPaolo Bonzini if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { 81256382bd5SDaniel P. Berrange error_setg_errno(errp, errno, "Failed to bind socket to %s", path); 813baacf047SPaolo Bonzini goto err; 814baacf047SPaolo Bonzini } 815baacf047SPaolo Bonzini if (listen(sock, 1) < 0) { 816235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to listen on socket"); 817baacf047SPaolo Bonzini goto err; 818baacf047SPaolo Bonzini } 819baacf047SPaolo Bonzini 820ad9579aaSDaniel P. Berrange if (update_addr && pathbuf) { 821ad9579aaSDaniel P. Berrange g_free(saddr->path); 822ad9579aaSDaniel P. Berrange saddr->path = pathbuf; 823ad9579aaSDaniel P. Berrange } else { 824ad9579aaSDaniel P. Berrange g_free(pathbuf); 825ad9579aaSDaniel P. Berrange } 826baacf047SPaolo Bonzini return sock; 827baacf047SPaolo Bonzini 828baacf047SPaolo Bonzini err: 829ad9579aaSDaniel P. Berrange g_free(pathbuf); 830baacf047SPaolo Bonzini closesocket(sock); 831baacf047SPaolo Bonzini return -1; 832baacf047SPaolo Bonzini } 833baacf047SPaolo Bonzini 834b2587932SCao jin static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) 835baacf047SPaolo Bonzini { 836baacf047SPaolo Bonzini struct sockaddr_un un; 837baacf047SPaolo Bonzini int sock, rc; 838baacf047SPaolo Bonzini 8392942e420SDaniel P. Berrange if (saddr->path == NULL) { 840312fd5f2SMarkus Armbruster error_setg(errp, "unix connect: no path specified"); 841baacf047SPaolo Bonzini return -1; 842baacf047SPaolo Bonzini } 843baacf047SPaolo Bonzini 844baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 845baacf047SPaolo Bonzini if (sock < 0) { 846235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 847baacf047SPaolo Bonzini return -1; 848baacf047SPaolo Bonzini } 849baacf047SPaolo Bonzini 850ad9579aaSDaniel P. Berrange if (strlen(saddr->path) > sizeof(un.sun_path)) { 851ad9579aaSDaniel P. Berrange error_setg(errp, "UNIX socket path '%s' is too long", saddr->path); 852ad9579aaSDaniel P. Berrange error_append_hint(errp, "Path must be less than %zu bytes\n", 853ad9579aaSDaniel P. Berrange sizeof(un.sun_path)); 854ad9579aaSDaniel P. Berrange goto err; 855ad9579aaSDaniel P. Berrange } 856ad9579aaSDaniel P. Berrange 857baacf047SPaolo Bonzini memset(&un, 0, sizeof(un)); 858baacf047SPaolo Bonzini un.sun_family = AF_UNIX; 859ad9579aaSDaniel P. Berrange strncpy(un.sun_path, saddr->path, sizeof(un.sun_path)); 860baacf047SPaolo Bonzini 861baacf047SPaolo Bonzini /* connect to peer */ 862baacf047SPaolo Bonzini do { 863baacf047SPaolo Bonzini rc = 0; 864baacf047SPaolo Bonzini if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { 865b16a44e1SDaniel P. Berrange rc = -errno; 866baacf047SPaolo Bonzini } 867baacf047SPaolo Bonzini } while (rc == -EINTR); 868baacf047SPaolo Bonzini 869baacf047SPaolo Bonzini if (rc < 0) { 870ad9579aaSDaniel P. Berrange error_setg_errno(errp, -rc, "Failed to connect socket %s", 871ad9579aaSDaniel P. Berrange saddr->path); 872ad9579aaSDaniel P. Berrange goto err; 873baacf047SPaolo Bonzini } 874baacf047SPaolo Bonzini 875baacf047SPaolo Bonzini return sock; 876ad9579aaSDaniel P. Berrange 877ad9579aaSDaniel P. Berrange err: 878ad9579aaSDaniel P. Berrange close(sock); 879ad9579aaSDaniel P. Berrange return -1; 880baacf047SPaolo Bonzini } 881baacf047SPaolo Bonzini 882baacf047SPaolo Bonzini #else 883baacf047SPaolo Bonzini 8841856835dSDaniel P. Berrange static int unix_listen_saddr(UnixSocketAddress *saddr, 8851856835dSDaniel P. Berrange bool update_addr, 8861856835dSDaniel P. Berrange Error **errp) 887baacf047SPaolo Bonzini { 888baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 889baacf047SPaolo Bonzini errno = ENOTSUP; 890baacf047SPaolo Bonzini return -1; 891baacf047SPaolo Bonzini } 892baacf047SPaolo Bonzini 893b2587932SCao jin static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) 894baacf047SPaolo Bonzini { 895baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 896baacf047SPaolo Bonzini errno = ENOTSUP; 897baacf047SPaolo Bonzini return -1; 898baacf047SPaolo Bonzini } 899baacf047SPaolo Bonzini #endif 900baacf047SPaolo Bonzini 901baacf047SPaolo Bonzini /* compatibility wrapper */ 902baacf047SPaolo Bonzini int unix_listen(const char *str, char *ostr, int olen, Error **errp) 903baacf047SPaolo Bonzini { 904baacf047SPaolo Bonzini char *path, *optstr; 905baacf047SPaolo Bonzini int sock, len; 9061856835dSDaniel P. Berrange UnixSocketAddress *saddr; 907baacf047SPaolo Bonzini 9081856835dSDaniel P. Berrange saddr = g_new0(UnixSocketAddress, 1); 909baacf047SPaolo Bonzini 910baacf047SPaolo Bonzini optstr = strchr(str, ','); 911baacf047SPaolo Bonzini if (optstr) { 912baacf047SPaolo Bonzini len = optstr - str; 913baacf047SPaolo Bonzini if (len) { 914baacf047SPaolo Bonzini path = g_malloc(len+1); 915baacf047SPaolo Bonzini snprintf(path, len+1, "%.*s", len, str); 9161856835dSDaniel P. Berrange saddr->path = path; 917baacf047SPaolo Bonzini } 918baacf047SPaolo Bonzini } else { 9191856835dSDaniel P. Berrange saddr->path = g_strdup(str); 920baacf047SPaolo Bonzini } 921baacf047SPaolo Bonzini 9221856835dSDaniel P. Berrange sock = unix_listen_saddr(saddr, true, errp); 923baacf047SPaolo Bonzini 92426015051SCao jin if (sock != -1 && ostr) { 9251856835dSDaniel P. Berrange snprintf(ostr, olen, "%s%s", saddr->path, optstr ? optstr : ""); 92626015051SCao jin } 92726015051SCao jin 9281856835dSDaniel P. Berrange qapi_free_UnixSocketAddress(saddr); 929baacf047SPaolo Bonzini return sock; 930baacf047SPaolo Bonzini } 931baacf047SPaolo Bonzini 932baacf047SPaolo Bonzini int unix_connect(const char *path, Error **errp) 933baacf047SPaolo Bonzini { 9342942e420SDaniel P. Berrange UnixSocketAddress *saddr; 935baacf047SPaolo Bonzini int sock; 936baacf047SPaolo Bonzini 9372942e420SDaniel P. Berrange saddr = g_new0(UnixSocketAddress, 1); 9382942e420SDaniel P. Berrange saddr->path = g_strdup(path); 939b2587932SCao jin sock = unix_connect_saddr(saddr, errp); 9402942e420SDaniel P. Berrange qapi_free_UnixSocketAddress(saddr); 941baacf047SPaolo Bonzini return sock; 942baacf047SPaolo Bonzini } 943baacf047SPaolo Bonzini 944baacf047SPaolo Bonzini 945bd269ebcSMarkus Armbruster SocketAddress *socket_parse(const char *str, Error **errp) 946baacf047SPaolo Bonzini { 947bd269ebcSMarkus Armbruster SocketAddress *addr; 948baacf047SPaolo Bonzini 949bd269ebcSMarkus Armbruster addr = g_new0(SocketAddress, 1); 950baacf047SPaolo Bonzini if (strstart(str, "unix:", NULL)) { 951baacf047SPaolo Bonzini if (str[5] == '\0') { 952312fd5f2SMarkus Armbruster error_setg(errp, "invalid Unix socket address"); 953baacf047SPaolo Bonzini goto fail; 954baacf047SPaolo Bonzini } else { 955bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_UNIX; 956bd269ebcSMarkus Armbruster addr->u.q_unix.path = g_strdup(str + 5); 957baacf047SPaolo Bonzini } 958baacf047SPaolo Bonzini } else if (strstart(str, "fd:", NULL)) { 959baacf047SPaolo Bonzini if (str[3] == '\0') { 960312fd5f2SMarkus Armbruster error_setg(errp, "invalid file descriptor address"); 961baacf047SPaolo Bonzini goto fail; 962baacf047SPaolo Bonzini } else { 963bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_FD; 964bd269ebcSMarkus Armbruster addr->u.fd.str = g_strdup(str + 3); 965baacf047SPaolo Bonzini } 9666a02c806SStefan Hajnoczi } else if (strstart(str, "vsock:", NULL)) { 967bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_VSOCK; 968bd269ebcSMarkus Armbruster if (vsock_parse(&addr->u.vsock, str + strlen("vsock:"), errp)) { 9696a02c806SStefan Hajnoczi goto fail; 9706a02c806SStefan Hajnoczi } 971baacf047SPaolo Bonzini } else { 972bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_INET; 973bd269ebcSMarkus Armbruster if (inet_parse(&addr->u.inet, str, errp)) { 974baacf047SPaolo Bonzini goto fail; 975baacf047SPaolo Bonzini } 976baacf047SPaolo Bonzini } 977baacf047SPaolo Bonzini return addr; 978baacf047SPaolo Bonzini 979baacf047SPaolo Bonzini fail: 980bd269ebcSMarkus Armbruster qapi_free_SocketAddress(addr); 981baacf047SPaolo Bonzini return NULL; 982baacf047SPaolo Bonzini } 983baacf047SPaolo Bonzini 984b2587932SCao jin int socket_connect(SocketAddress *addr, Error **errp) 985baacf047SPaolo Bonzini { 986baacf047SPaolo Bonzini int fd; 987baacf047SPaolo Bonzini 9882d32addaSEric Blake switch (addr->type) { 989bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_INET: 990b2587932SCao jin fd = inet_connect_saddr(&addr->u.inet, errp); 991baacf047SPaolo Bonzini break; 992baacf047SPaolo Bonzini 993bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_UNIX: 994b2587932SCao jin fd = unix_connect_saddr(&addr->u.q_unix, errp); 995baacf047SPaolo Bonzini break; 996baacf047SPaolo Bonzini 997bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_FD: 998bd269ebcSMarkus Armbruster fd = monitor_get_fd(cur_mon, addr->u.fd.str, errp); 999baacf047SPaolo Bonzini break; 1000baacf047SPaolo Bonzini 1001bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_VSOCK: 1002b2587932SCao jin fd = vsock_connect_saddr(&addr->u.vsock, errp); 10036a02c806SStefan Hajnoczi break; 10046a02c806SStefan Hajnoczi 1005baacf047SPaolo Bonzini default: 1006baacf047SPaolo Bonzini abort(); 1007baacf047SPaolo Bonzini } 1008baacf047SPaolo Bonzini return fd; 1009baacf047SPaolo Bonzini } 1010baacf047SPaolo Bonzini 1011bd269ebcSMarkus Armbruster int socket_listen(SocketAddress *addr, Error **errp) 1012baacf047SPaolo Bonzini { 1013baacf047SPaolo Bonzini int fd; 1014baacf047SPaolo Bonzini 10152d32addaSEric Blake switch (addr->type) { 1016bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_INET: 1017bd269ebcSMarkus Armbruster fd = inet_listen_saddr(&addr->u.inet, 0, false, errp); 1018baacf047SPaolo Bonzini break; 1019baacf047SPaolo Bonzini 1020bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_UNIX: 1021bd269ebcSMarkus Armbruster fd = unix_listen_saddr(&addr->u.q_unix, false, errp); 1022baacf047SPaolo Bonzini break; 1023baacf047SPaolo Bonzini 1024bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_FD: 1025bd269ebcSMarkus Armbruster fd = monitor_get_fd(cur_mon, addr->u.fd.str, errp); 1026baacf047SPaolo Bonzini break; 1027baacf047SPaolo Bonzini 1028bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_VSOCK: 1029bd269ebcSMarkus Armbruster fd = vsock_listen_saddr(&addr->u.vsock, errp); 10306a02c806SStefan Hajnoczi break; 10316a02c806SStefan Hajnoczi 1032baacf047SPaolo Bonzini default: 1033baacf047SPaolo Bonzini abort(); 1034baacf047SPaolo Bonzini } 1035baacf047SPaolo Bonzini return fd; 1036baacf047SPaolo Bonzini } 1037baacf047SPaolo Bonzini 103874b6ce43SMarc-André Lureau void socket_listen_cleanup(int fd, Error **errp) 103974b6ce43SMarc-André Lureau { 1040bd269ebcSMarkus Armbruster SocketAddress *addr; 104174b6ce43SMarc-André Lureau 104274b6ce43SMarc-André Lureau addr = socket_local_address(fd, errp); 104374b6ce43SMarc-André Lureau 1044bd269ebcSMarkus Armbruster if (addr->type == SOCKET_ADDRESS_TYPE_UNIX 1045bd269ebcSMarkus Armbruster && addr->u.q_unix.path) { 1046bd269ebcSMarkus Armbruster if (unlink(addr->u.q_unix.path) < 0 && errno != ENOENT) { 104774b6ce43SMarc-André Lureau error_setg_errno(errp, errno, 104874b6ce43SMarc-André Lureau "Failed to unlink socket %s", 1049bd269ebcSMarkus Armbruster addr->u.q_unix.path); 105074b6ce43SMarc-André Lureau } 105174b6ce43SMarc-André Lureau } 105274b6ce43SMarc-André Lureau 1053bd269ebcSMarkus Armbruster qapi_free_SocketAddress(addr); 105474b6ce43SMarc-André Lureau } 105574b6ce43SMarc-André Lureau 1056bd269ebcSMarkus Armbruster int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp) 10573ecc059dSGerd Hoffmann { 10583ecc059dSGerd Hoffmann int fd; 10593ecc059dSGerd Hoffmann 1060ca0b64e5SMarkus Armbruster /* 1061bd269ebcSMarkus Armbruster * TODO SOCKET_ADDRESS_TYPE_FD when fd is AF_INET or AF_INET6 1062ca0b64e5SMarkus Armbruster * (although other address families can do SOCK_DGRAM, too) 1063ca0b64e5SMarkus Armbruster */ 10642d32addaSEric Blake switch (remote->type) { 1065bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_INET: 1066bd269ebcSMarkus Armbruster fd = inet_dgram_saddr(&remote->u.inet, 1067bd269ebcSMarkus Armbruster local ? &local->u.inet : NULL, errp); 10683ecc059dSGerd Hoffmann break; 10693ecc059dSGerd Hoffmann 10703ecc059dSGerd Hoffmann default: 10713ecc059dSGerd Hoffmann error_setg(errp, "socket type unsupported for datagram"); 10727a5b6af1SGerd Hoffmann fd = -1; 10733ecc059dSGerd Hoffmann } 10743ecc059dSGerd Hoffmann return fd; 10753ecc059dSGerd Hoffmann } 107617c55decSDaniel P. Berrange 107717c55decSDaniel P. Berrange 1078bd269ebcSMarkus Armbruster static SocketAddress * 107917c55decSDaniel P. Berrange socket_sockaddr_to_address_inet(struct sockaddr_storage *sa, 108017c55decSDaniel P. Berrange socklen_t salen, 108117c55decSDaniel P. Berrange Error **errp) 108217c55decSDaniel P. Berrange { 108317c55decSDaniel P. Berrange char host[NI_MAXHOST]; 108417c55decSDaniel P. Berrange char serv[NI_MAXSERV]; 1085bd269ebcSMarkus Armbruster SocketAddress *addr; 10860399293eSEric Blake InetSocketAddress *inet; 108717c55decSDaniel P. Berrange int ret; 108817c55decSDaniel P. Berrange 108917c55decSDaniel P. Berrange ret = getnameinfo((struct sockaddr *)sa, salen, 109017c55decSDaniel P. Berrange host, sizeof(host), 109117c55decSDaniel P. Berrange serv, sizeof(serv), 109217c55decSDaniel P. Berrange NI_NUMERICHOST | NI_NUMERICSERV); 109317c55decSDaniel P. Berrange if (ret != 0) { 109417c55decSDaniel P. Berrange error_setg(errp, "Cannot format numeric socket address: %s", 109517c55decSDaniel P. Berrange gai_strerror(ret)); 109617c55decSDaniel P. Berrange return NULL; 109717c55decSDaniel P. Berrange } 109817c55decSDaniel P. Berrange 1099bd269ebcSMarkus Armbruster addr = g_new0(SocketAddress, 1); 1100bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_INET; 1101bd269ebcSMarkus Armbruster inet = &addr->u.inet; 11020399293eSEric Blake inet->host = g_strdup(host); 11030399293eSEric Blake inet->port = g_strdup(serv); 110417c55decSDaniel P. Berrange if (sa->ss_family == AF_INET) { 11050399293eSEric Blake inet->has_ipv4 = inet->ipv4 = true; 110617c55decSDaniel P. Berrange } else { 11070399293eSEric Blake inet->has_ipv6 = inet->ipv6 = true; 110817c55decSDaniel P. Berrange } 110917c55decSDaniel P. Berrange 111017c55decSDaniel P. Berrange return addr; 111117c55decSDaniel P. Berrange } 111217c55decSDaniel P. Berrange 111317c55decSDaniel P. Berrange 111417c55decSDaniel P. Berrange #ifndef WIN32 1115bd269ebcSMarkus Armbruster static SocketAddress * 111617c55decSDaniel P. Berrange socket_sockaddr_to_address_unix(struct sockaddr_storage *sa, 111717c55decSDaniel P. Berrange socklen_t salen, 111817c55decSDaniel P. Berrange Error **errp) 111917c55decSDaniel P. Berrange { 1120bd269ebcSMarkus Armbruster SocketAddress *addr; 112117c55decSDaniel P. Berrange struct sockaddr_un *su = (struct sockaddr_un *)sa; 112217c55decSDaniel P. Berrange 1123bd269ebcSMarkus Armbruster addr = g_new0(SocketAddress, 1); 1124bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_UNIX; 112517c55decSDaniel P. Berrange if (su->sun_path[0]) { 1126bd269ebcSMarkus Armbruster addr->u.q_unix.path = g_strndup(su->sun_path, sizeof(su->sun_path)); 112717c55decSDaniel P. Berrange } 112817c55decSDaniel P. Berrange 112917c55decSDaniel P. Berrange return addr; 113017c55decSDaniel P. Berrange } 113117c55decSDaniel P. Berrange #endif /* WIN32 */ 113217c55decSDaniel P. Berrange 11336a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 1134bd269ebcSMarkus Armbruster static SocketAddress * 11356a02c806SStefan Hajnoczi socket_sockaddr_to_address_vsock(struct sockaddr_storage *sa, 11366a02c806SStefan Hajnoczi socklen_t salen, 11376a02c806SStefan Hajnoczi Error **errp) 11386a02c806SStefan Hajnoczi { 1139bd269ebcSMarkus Armbruster SocketAddress *addr; 11406a02c806SStefan Hajnoczi VsockSocketAddress *vaddr; 11416a02c806SStefan Hajnoczi struct sockaddr_vm *svm = (struct sockaddr_vm *)sa; 11426a02c806SStefan Hajnoczi 1143bd269ebcSMarkus Armbruster addr = g_new0(SocketAddress, 1); 1144bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_VSOCK; 1145bd269ebcSMarkus Armbruster vaddr = &addr->u.vsock; 11466a02c806SStefan Hajnoczi vaddr->cid = g_strdup_printf("%u", svm->svm_cid); 11476a02c806SStefan Hajnoczi vaddr->port = g_strdup_printf("%u", svm->svm_port); 11486a02c806SStefan Hajnoczi 11496a02c806SStefan Hajnoczi return addr; 11506a02c806SStefan Hajnoczi } 11516a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 11526a02c806SStefan Hajnoczi 1153bd269ebcSMarkus Armbruster SocketAddress * 115417c55decSDaniel P. Berrange socket_sockaddr_to_address(struct sockaddr_storage *sa, 115517c55decSDaniel P. Berrange socklen_t salen, 115617c55decSDaniel P. Berrange Error **errp) 115717c55decSDaniel P. Berrange { 115817c55decSDaniel P. Berrange switch (sa->ss_family) { 115917c55decSDaniel P. Berrange case AF_INET: 116017c55decSDaniel P. Berrange case AF_INET6: 116117c55decSDaniel P. Berrange return socket_sockaddr_to_address_inet(sa, salen, errp); 116217c55decSDaniel P. Berrange 116317c55decSDaniel P. Berrange #ifndef WIN32 116417c55decSDaniel P. Berrange case AF_UNIX: 116517c55decSDaniel P. Berrange return socket_sockaddr_to_address_unix(sa, salen, errp); 116617c55decSDaniel P. Berrange #endif /* WIN32 */ 116717c55decSDaniel P. Berrange 11686a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 11696a02c806SStefan Hajnoczi case AF_VSOCK: 11706a02c806SStefan Hajnoczi return socket_sockaddr_to_address_vsock(sa, salen, errp); 11716a02c806SStefan Hajnoczi #endif 11726a02c806SStefan Hajnoczi 117317c55decSDaniel P. Berrange default: 117417c55decSDaniel P. Berrange error_setg(errp, "socket family %d unsupported", 117517c55decSDaniel P. Berrange sa->ss_family); 117617c55decSDaniel P. Berrange return NULL; 117717c55decSDaniel P. Berrange } 117817c55decSDaniel P. Berrange return 0; 117917c55decSDaniel P. Berrange } 118017c55decSDaniel P. Berrange 118117c55decSDaniel P. Berrange 1182bd269ebcSMarkus Armbruster SocketAddress *socket_local_address(int fd, Error **errp) 118317c55decSDaniel P. Berrange { 118417c55decSDaniel P. Berrange struct sockaddr_storage ss; 118517c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 118617c55decSDaniel P. Berrange 118717c55decSDaniel P. Berrange if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) { 1188b16a44e1SDaniel P. Berrange error_setg_errno(errp, errno, "%s", 118917c55decSDaniel P. Berrange "Unable to query local socket address"); 119017c55decSDaniel P. Berrange return NULL; 119117c55decSDaniel P. Berrange } 119217c55decSDaniel P. Berrange 119317c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 119417c55decSDaniel P. Berrange } 119517c55decSDaniel P. Berrange 119617c55decSDaniel P. Berrange 1197bd269ebcSMarkus Armbruster SocketAddress *socket_remote_address(int fd, Error **errp) 119817c55decSDaniel P. Berrange { 119917c55decSDaniel P. Berrange struct sockaddr_storage ss; 120017c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 120117c55decSDaniel P. Berrange 120217c55decSDaniel P. Berrange if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) { 1203b16a44e1SDaniel P. Berrange error_setg_errno(errp, errno, "%s", 120417c55decSDaniel P. Berrange "Unable to query remote socket address"); 120517c55decSDaniel P. Berrange return NULL; 120617c55decSDaniel P. Berrange } 120717c55decSDaniel P. Berrange 120817c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 120917c55decSDaniel P. Berrange } 12102a8e21c7SDaniel P. Berrange 1211216411b8SMarkus Armbruster 1212bd269ebcSMarkus Armbruster SocketAddress *socket_address_flatten(SocketAddressLegacy *addr_legacy) 1213bd269ebcSMarkus Armbruster { 1214fc0f0059SMarkus Armbruster SocketAddress *addr; 1215bd269ebcSMarkus Armbruster 1216bd269ebcSMarkus Armbruster if (!addr_legacy) { 1217bd269ebcSMarkus Armbruster return NULL; 1218bd269ebcSMarkus Armbruster } 1219bd269ebcSMarkus Armbruster 1220fc0f0059SMarkus Armbruster addr = g_new(SocketAddress, 1); 1221fc0f0059SMarkus Armbruster 1222bd269ebcSMarkus Armbruster switch (addr_legacy->type) { 1223bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_LEGACY_KIND_INET: 1224bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_INET; 1225bd269ebcSMarkus Armbruster QAPI_CLONE_MEMBERS(InetSocketAddress, &addr->u.inet, 1226bd269ebcSMarkus Armbruster addr_legacy->u.inet.data); 1227bd269ebcSMarkus Armbruster break; 1228bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_LEGACY_KIND_UNIX: 1229bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_UNIX; 1230bd269ebcSMarkus Armbruster QAPI_CLONE_MEMBERS(UnixSocketAddress, &addr->u.q_unix, 1231bd269ebcSMarkus Armbruster addr_legacy->u.q_unix.data); 1232bd269ebcSMarkus Armbruster break; 1233bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_LEGACY_KIND_VSOCK: 1234bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_VSOCK; 1235bd269ebcSMarkus Armbruster QAPI_CLONE_MEMBERS(VsockSocketAddress, &addr->u.vsock, 1236bd269ebcSMarkus Armbruster addr_legacy->u.vsock.data); 1237bd269ebcSMarkus Armbruster break; 1238bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_LEGACY_KIND_FD: 1239bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_FD; 1240bd269ebcSMarkus Armbruster QAPI_CLONE_MEMBERS(String, &addr->u.fd, addr_legacy->u.fd.data); 1241bd269ebcSMarkus Armbruster break; 1242bd269ebcSMarkus Armbruster default: 1243bd269ebcSMarkus Armbruster abort(); 1244bd269ebcSMarkus Armbruster } 1245bd269ebcSMarkus Armbruster 1246bd269ebcSMarkus Armbruster return addr; 1247bd269ebcSMarkus Armbruster } 1248