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" 279af23989SMarkus Armbruster #include "qapi/qapi-visit-sockets.h" 28baacf047SPaolo Bonzini #include "qemu/sockets.h" 29baacf047SPaolo Bonzini #include "qemu/main-loop.h" 30b3db211fSDaniel P. Berrange #include "qapi/qobject-input-visitor.h" 31b3db211fSDaniel P. Berrange #include "qapi/qobject-output-visitor.h" 32f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 33baacf047SPaolo Bonzini 34baacf047SPaolo Bonzini #ifndef AI_ADDRCONFIG 35baacf047SPaolo Bonzini # define AI_ADDRCONFIG 0 36baacf047SPaolo Bonzini #endif 37340849a9SDaniel P. Berrange 383de3d698SWolfgang Bumiller #ifndef AI_V4MAPPED 393de3d698SWolfgang Bumiller # define AI_V4MAPPED 0 403de3d698SWolfgang Bumiller #endif 41baacf047SPaolo Bonzini 426979a813SDaniel P. Berrange #ifndef AI_NUMERICSERV 436979a813SDaniel P. Berrange # define AI_NUMERICSERV 0 446979a813SDaniel P. Berrange #endif 456979a813SDaniel P. Berrange 46baacf047SPaolo Bonzini 47baacf047SPaolo Bonzini static int inet_getport(struct addrinfo *e) 48baacf047SPaolo Bonzini { 49baacf047SPaolo Bonzini struct sockaddr_in *i4; 50baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 51baacf047SPaolo Bonzini 52baacf047SPaolo Bonzini switch (e->ai_family) { 53baacf047SPaolo Bonzini case PF_INET6: 54baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 55baacf047SPaolo Bonzini return ntohs(i6->sin6_port); 56baacf047SPaolo Bonzini case PF_INET: 57baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 58baacf047SPaolo Bonzini return ntohs(i4->sin_port); 59baacf047SPaolo Bonzini default: 60baacf047SPaolo Bonzini return 0; 61baacf047SPaolo Bonzini } 62baacf047SPaolo Bonzini } 63baacf047SPaolo Bonzini 64baacf047SPaolo Bonzini static void inet_setport(struct addrinfo *e, int port) 65baacf047SPaolo Bonzini { 66baacf047SPaolo Bonzini struct sockaddr_in *i4; 67baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 68baacf047SPaolo Bonzini 69baacf047SPaolo Bonzini switch (e->ai_family) { 70baacf047SPaolo Bonzini case PF_INET6: 71baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 72baacf047SPaolo Bonzini i6->sin6_port = htons(port); 73baacf047SPaolo Bonzini break; 74baacf047SPaolo Bonzini case PF_INET: 75baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 76baacf047SPaolo Bonzini i4->sin_port = htons(port); 77baacf047SPaolo Bonzini break; 78baacf047SPaolo Bonzini } 79baacf047SPaolo Bonzini } 80baacf047SPaolo Bonzini 81a589569fSWenchao Xia NetworkAddressFamily inet_netfamily(int family) 82a589569fSWenchao Xia { 83a589569fSWenchao Xia switch (family) { 84a589569fSWenchao Xia case PF_INET6: return NETWORK_ADDRESS_FAMILY_IPV6; 85a589569fSWenchao Xia case PF_INET: return NETWORK_ADDRESS_FAMILY_IPV4; 86a589569fSWenchao Xia case PF_UNIX: return NETWORK_ADDRESS_FAMILY_UNIX; 876a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 886a02c806SStefan Hajnoczi case PF_VSOCK: return NETWORK_ADDRESS_FAMILY_VSOCK; 896a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 90a589569fSWenchao Xia } 91a589569fSWenchao Xia return NETWORK_ADDRESS_FAMILY_UNKNOWN; 92a589569fSWenchao Xia } 93a589569fSWenchao Xia 9458dc31f1SDaniel P. Berrange bool fd_is_socket(int fd) 9558dc31f1SDaniel P. Berrange { 9658dc31f1SDaniel P. Berrange int optval; 9758dc31f1SDaniel P. Berrange socklen_t optlen = sizeof(optval); 9858dc31f1SDaniel P. Berrange return !qemu_getsockopt(fd, SOL_SOCKET, SO_TYPE, &optval, &optlen); 9958dc31f1SDaniel P. Berrange } 10058dc31f1SDaniel P. Berrange 10158dc31f1SDaniel P. Berrange 1021856835dSDaniel P. Berrange /* 1031856835dSDaniel P. Berrange * Matrix we're trying to apply 1041856835dSDaniel P. Berrange * 1051856835dSDaniel P. Berrange * ipv4 ipv6 family 1061856835dSDaniel P. Berrange * - - PF_UNSPEC 1071856835dSDaniel P. Berrange * - f PF_INET 1081856835dSDaniel P. Berrange * - t PF_INET6 1091856835dSDaniel P. Berrange * f - PF_INET6 1101856835dSDaniel P. Berrange * f f <error> 1111856835dSDaniel P. Berrange * f t PF_INET6 1121856835dSDaniel P. Berrange * t - PF_INET 1131856835dSDaniel P. Berrange * t f PF_INET 11494bc0d19SDaniel P. Berrange * t t PF_INET6/PF_UNSPEC 1151856835dSDaniel P. Berrange * 116d43eda3dSWei Jiangang * NB, this matrix is only about getting the necessary results 1171856835dSDaniel P. Berrange * from getaddrinfo(). Some of the cases require further work 1181856835dSDaniel P. Berrange * after reading results from getaddrinfo in order to fully 11994bc0d19SDaniel P. Berrange * apply the logic the end user wants. 12094bc0d19SDaniel P. Berrange * 12194bc0d19SDaniel P. Berrange * In the first and last cases, we must set IPV6_V6ONLY=0 12294bc0d19SDaniel P. Berrange * when binding, to allow a single listener to potentially 12394bc0d19SDaniel P. Berrange * accept both IPv4+6 addresses. 1241856835dSDaniel P. Berrange */ 125c1b412f1SDaniel P. Berrange int inet_ai_family_from_address(InetSocketAddress *addr, 1261856835dSDaniel P. Berrange Error **errp) 1271856835dSDaniel P. Berrange { 1281856835dSDaniel P. Berrange if (addr->has_ipv6 && addr->has_ipv4 && 1291856835dSDaniel P. Berrange !addr->ipv6 && !addr->ipv4) { 1301856835dSDaniel P. Berrange error_setg(errp, "Cannot disable IPv4 and IPv6 at same time"); 1311856835dSDaniel P. Berrange return PF_UNSPEC; 1321856835dSDaniel P. Berrange } 13394bc0d19SDaniel P. Berrange if ((addr->has_ipv6 && addr->ipv6) && (addr->has_ipv4 && addr->ipv4)) { 13494bc0d19SDaniel P. Berrange /* 13594bc0d19SDaniel P. Berrange * Some backends can only do a single listener. In that case 13694bc0d19SDaniel P. Berrange * we want empty hostname to resolve to "::" and then use the 13794bc0d19SDaniel P. Berrange * flag IPV6_V6ONLY==0 to get both protocols on 1 socket. This 13894bc0d19SDaniel P. Berrange * doesn't work for addresses other than "", so they're just 13994bc0d19SDaniel P. Berrange * inevitably broken until multiple listeners can be used, 14094bc0d19SDaniel P. Berrange * and thus we honour getaddrinfo automatic protocol detection 14194bc0d19SDaniel P. Berrange * Once all backends do multi-listener, remove the PF_INET6 14294bc0d19SDaniel P. Berrange * branch entirely. 14394bc0d19SDaniel P. Berrange */ 14494bc0d19SDaniel P. Berrange if (!addr->host || g_str_equal(addr->host, "")) { 14594bc0d19SDaniel P. Berrange return PF_INET6; 14694bc0d19SDaniel P. Berrange } else { 14794bc0d19SDaniel P. Berrange return PF_UNSPEC; 14894bc0d19SDaniel P. Berrange } 14994bc0d19SDaniel P. Berrange } 1501856835dSDaniel P. Berrange if ((addr->has_ipv6 && addr->ipv6) || (addr->has_ipv4 && !addr->ipv4)) { 1511856835dSDaniel P. Berrange return PF_INET6; 1521856835dSDaniel P. Berrange } 1531856835dSDaniel P. Berrange if ((addr->has_ipv4 && addr->ipv4) || (addr->has_ipv6 && !addr->ipv6)) { 1541856835dSDaniel P. Berrange return PF_INET; 1551856835dSDaniel P. Berrange } 1561856835dSDaniel P. Berrange return PF_UNSPEC; 1571856835dSDaniel P. Berrange } 1581856835dSDaniel P. Berrange 15939f80521SKnut Omang static int create_fast_reuse_socket(struct addrinfo *e) 16039f80521SKnut Omang { 16139f80521SKnut Omang int slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); 16239f80521SKnut Omang if (slisten < 0) { 16339f80521SKnut Omang return -1; 16439f80521SKnut Omang } 16539f80521SKnut Omang socket_set_fast_reuse(slisten); 16639f80521SKnut Omang return slisten; 16739f80521SKnut Omang } 16839f80521SKnut Omang 16989382c3dSKnut Omang static int try_bind(int socket, InetSocketAddress *saddr, struct addrinfo *e) 17089382c3dSKnut Omang { 17189382c3dSKnut Omang #ifndef IPV6_V6ONLY 17289382c3dSKnut Omang return bind(socket, e->ai_addr, e->ai_addrlen); 17389382c3dSKnut Omang #else 17489382c3dSKnut Omang /* 17589382c3dSKnut Omang * Deals with first & last cases in matrix in comment 17689382c3dSKnut Omang * for inet_ai_family_from_address(). 17789382c3dSKnut Omang */ 17889382c3dSKnut Omang int v6only = 17989382c3dSKnut Omang ((!saddr->has_ipv4 && !saddr->has_ipv6) || 18089382c3dSKnut Omang (saddr->has_ipv4 && saddr->ipv4 && 18189382c3dSKnut Omang saddr->has_ipv6 && saddr->ipv6)) ? 0 : 1; 18289382c3dSKnut Omang int stat; 18389382c3dSKnut Omang 18489382c3dSKnut Omang rebind: 18589382c3dSKnut Omang if (e->ai_family == PF_INET6) { 18689382c3dSKnut Omang qemu_setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, 18789382c3dSKnut Omang sizeof(v6only)); 18889382c3dSKnut Omang } 18989382c3dSKnut Omang 19089382c3dSKnut Omang stat = bind(socket, e->ai_addr, e->ai_addrlen); 19189382c3dSKnut Omang if (!stat) { 19289382c3dSKnut Omang return 0; 19389382c3dSKnut Omang } 19489382c3dSKnut Omang 19589382c3dSKnut Omang /* If we got EADDRINUSE from an IPv6 bind & v6only is unset, 19689382c3dSKnut Omang * it could be that the IPv4 port is already claimed, so retry 19789382c3dSKnut Omang * with v6only set 19889382c3dSKnut Omang */ 19989382c3dSKnut Omang if (e->ai_family == PF_INET6 && errno == EADDRINUSE && !v6only) { 20089382c3dSKnut Omang v6only = 1; 20189382c3dSKnut Omang goto rebind; 20289382c3dSKnut Omang } 20389382c3dSKnut Omang return stat; 20489382c3dSKnut Omang #endif 20589382c3dSKnut Omang } 20689382c3dSKnut Omang 2071856835dSDaniel P. Berrange static int inet_listen_saddr(InetSocketAddress *saddr, 2081856835dSDaniel P. Berrange int port_offset, 2091856835dSDaniel P. Berrange Error **errp) 210baacf047SPaolo Bonzini { 211baacf047SPaolo Bonzini struct addrinfo ai,*res,*e; 212baacf047SPaolo Bonzini char port[33]; 213baacf047SPaolo Bonzini char uaddr[INET6_ADDRSTRLEN+1]; 214baacf047SPaolo Bonzini char uport[33]; 2159cf961bbSKnut Omang int rc, port_min, port_max, p; 21610a7b7e6SDaniel P. Berrange int slisten = -1; 2179cf961bbSKnut Omang int saved_errno = 0; 2189cf961bbSKnut Omang bool socket_created = false; 2191856835dSDaniel P. Berrange Error *err = NULL; 220baacf047SPaolo Bonzini 221baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 2223de3d698SWolfgang Bumiller ai.ai_flags = AI_PASSIVE; 2236979a813SDaniel P. Berrange if (saddr->has_numeric && saddr->numeric) { 2246979a813SDaniel P. Berrange ai.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV; 2256979a813SDaniel P. Berrange } 2261856835dSDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(saddr, &err); 227baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 228baacf047SPaolo Bonzini 2291856835dSDaniel P. Berrange if (err) { 2301856835dSDaniel P. Berrange error_propagate(errp, err); 2311856835dSDaniel P. Berrange return -1; 2321856835dSDaniel P. Berrange } 2331856835dSDaniel P. Berrange 2341856835dSDaniel P. Berrange if (saddr->host == NULL) { 2350983f5e6SDaniel P. Berrange error_setg(errp, "host not specified"); 236baacf047SPaolo Bonzini return -1; 237baacf047SPaolo Bonzini } 2381856835dSDaniel P. Berrange if (saddr->port != NULL) { 2391856835dSDaniel P. Berrange pstrcpy(port, sizeof(port), saddr->port); 2400983f5e6SDaniel P. Berrange } else { 2410983f5e6SDaniel P. Berrange port[0] = '\0'; 2420983f5e6SDaniel P. Berrange } 243baacf047SPaolo Bonzini 244baacf047SPaolo Bonzini /* lookup */ 2458bc89127SGerd Hoffmann if (port_offset) { 2468bc89127SGerd Hoffmann unsigned long long baseport; 2470983f5e6SDaniel P. Berrange if (strlen(port) == 0) { 2480983f5e6SDaniel P. Berrange error_setg(errp, "port not specified"); 2490983f5e6SDaniel P. Berrange return -1; 2500983f5e6SDaniel P. Berrange } 2518bc89127SGerd Hoffmann if (parse_uint_full(port, &baseport, 10) < 0) { 2528bc89127SGerd Hoffmann error_setg(errp, "can't convert to a number: %s", port); 2538bc89127SGerd Hoffmann return -1; 2548bc89127SGerd Hoffmann } 2558bc89127SGerd Hoffmann if (baseport > 65535 || 2568bc89127SGerd Hoffmann baseport + port_offset > 65535) { 2578bc89127SGerd Hoffmann error_setg(errp, "port %s out of range", port); 2588bc89127SGerd Hoffmann return -1; 2598bc89127SGerd Hoffmann } 2608bc89127SGerd Hoffmann snprintf(port, sizeof(port), "%d", (int)baseport + port_offset); 2618bc89127SGerd Hoffmann } 2621856835dSDaniel P. Berrange rc = getaddrinfo(strlen(saddr->host) ? saddr->host : NULL, 2630983f5e6SDaniel P. Berrange strlen(port) ? port : NULL, &ai, &res); 264baacf047SPaolo Bonzini if (rc != 0) { 2651856835dSDaniel P. Berrange error_setg(errp, "address resolution failed for %s:%s: %s", 2661856835dSDaniel P. Berrange saddr->host, port, gai_strerror(rc)); 267baacf047SPaolo Bonzini return -1; 268baacf047SPaolo Bonzini } 269baacf047SPaolo Bonzini 2709cf961bbSKnut Omang /* create socket + bind/listen */ 271baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 272baacf047SPaolo Bonzini getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, 273baacf047SPaolo Bonzini uaddr,INET6_ADDRSTRLEN,uport,32, 274baacf047SPaolo Bonzini NI_NUMERICHOST | NI_NUMERICSERV); 27539f80521SKnut Omang 276baacf047SPaolo Bonzini port_min = inet_getport(e); 2771856835dSDaniel P. Berrange port_max = saddr->has_to ? saddr->to + port_offset : port_min; 278baacf047SPaolo Bonzini for (p = port_min; p <= port_max; p++) { 279baacf047SPaolo Bonzini inet_setport(e, p); 28010a7b7e6SDaniel P. Berrange 28110a7b7e6SDaniel P. Berrange slisten = create_fast_reuse_socket(e); 28210a7b7e6SDaniel P. Berrange if (slisten < 0) { 28310a7b7e6SDaniel P. Berrange /* First time we expect we might fail to create the socket 28410a7b7e6SDaniel P. Berrange * eg if 'e' has AF_INET6 but ipv6 kmod is not loaded. 28510a7b7e6SDaniel P. Berrange * Later iterations should always succeed if first iteration 28610a7b7e6SDaniel P. Berrange * worked though, so treat that as fatal. 28710a7b7e6SDaniel P. Berrange */ 28810a7b7e6SDaniel P. Berrange if (p == port_min) { 2899cf961bbSKnut Omang continue; 2909cf961bbSKnut Omang } else { 29110a7b7e6SDaniel P. Berrange error_setg_errno(errp, errno, 29210a7b7e6SDaniel P. Berrange "Failed to recreate failed listening socket"); 2939cf961bbSKnut Omang goto listen_failed; 2949cf961bbSKnut Omang } 2959cf961bbSKnut Omang } 29610a7b7e6SDaniel P. Berrange socket_created = true; 29710a7b7e6SDaniel P. Berrange 29810a7b7e6SDaniel P. Berrange rc = try_bind(slisten, saddr, e); 29910a7b7e6SDaniel P. Berrange if (rc < 0) { 30010a7b7e6SDaniel P. Berrange if (errno != EADDRINUSE) { 30110a7b7e6SDaniel P. Berrange error_setg_errno(errp, errno, "Failed to bind socket"); 30210a7b7e6SDaniel P. Berrange goto listen_failed; 30310a7b7e6SDaniel P. Berrange } 30410a7b7e6SDaniel P. Berrange } else { 3059cf961bbSKnut Omang if (!listen(slisten, 1)) { 3069cf961bbSKnut Omang goto listen_ok; 3079cf961bbSKnut Omang } 3089cf961bbSKnut Omang if (errno != EADDRINUSE) { 3099cf961bbSKnut Omang error_setg_errno(errp, errno, "Failed to listen on socket"); 3109cf961bbSKnut Omang goto listen_failed; 3119cf961bbSKnut Omang } 31210a7b7e6SDaniel P. Berrange } 3139cf961bbSKnut Omang /* Someone else managed to bind to the same port and beat us 3149cf961bbSKnut Omang * to listen on it! Socket semantics does not allow us to 3159cf961bbSKnut Omang * recover from this situation, so we need to recreate the 3169cf961bbSKnut Omang * socket to allow bind attempts for subsequent ports: 3179cf961bbSKnut Omang */ 3189cf961bbSKnut Omang closesocket(slisten); 31910a7b7e6SDaniel P. Berrange slisten = -1; 320baacf047SPaolo Bonzini } 321baacf047SPaolo Bonzini } 3229cf961bbSKnut Omang error_setg_errno(errp, errno, 3239cf961bbSKnut Omang socket_created ? 3249cf961bbSKnut Omang "Failed to find an available port" : 3259cf961bbSKnut Omang "Failed to create a socket"); 3269cf961bbSKnut Omang listen_failed: 3279cf961bbSKnut Omang saved_errno = errno; 3289cf961bbSKnut Omang if (slisten >= 0) { 329baacf047SPaolo Bonzini closesocket(slisten); 330baacf047SPaolo Bonzini } 331baacf047SPaolo Bonzini freeaddrinfo(res); 3329cf961bbSKnut Omang errno = saved_errno; 333baacf047SPaolo Bonzini return -1; 334baacf047SPaolo Bonzini 3359cf961bbSKnut Omang listen_ok: 336baacf047SPaolo Bonzini freeaddrinfo(res); 337baacf047SPaolo Bonzini return slisten; 338baacf047SPaolo Bonzini } 339baacf047SPaolo Bonzini 340baacf047SPaolo Bonzini #ifdef _WIN32 341baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 342baacf047SPaolo Bonzini ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY) 343baacf047SPaolo Bonzini #else 344baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 345baacf047SPaolo Bonzini ((rc) == -EINPROGRESS) 346baacf047SPaolo Bonzini #endif 347baacf047SPaolo Bonzini 348b2587932SCao jin static int inet_connect_addr(struct addrinfo *addr, Error **errp); 349baacf047SPaolo Bonzini 350b2587932SCao jin static int inet_connect_addr(struct addrinfo *addr, Error **errp) 351baacf047SPaolo Bonzini { 352baacf047SPaolo Bonzini int sock, rc; 353baacf047SPaolo Bonzini 354baacf047SPaolo Bonzini sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); 355baacf047SPaolo Bonzini if (sock < 0) { 356235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 357baacf047SPaolo Bonzini return -1; 358baacf047SPaolo Bonzini } 35904fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 360b2587932SCao jin 361baacf047SPaolo Bonzini /* connect to peer */ 362baacf047SPaolo Bonzini do { 363baacf047SPaolo Bonzini rc = 0; 364baacf047SPaolo Bonzini if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) { 365b16a44e1SDaniel P. Berrange rc = -errno; 366baacf047SPaolo Bonzini } 367baacf047SPaolo Bonzini } while (rc == -EINTR); 368baacf047SPaolo Bonzini 369b2587932SCao jin if (rc < 0) { 370235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to connect socket"); 371baacf047SPaolo Bonzini closesocket(sock); 372baacf047SPaolo Bonzini return -1; 373baacf047SPaolo Bonzini } 374b2587932SCao jin 375baacf047SPaolo Bonzini return sock; 376baacf047SPaolo Bonzini } 377baacf047SPaolo Bonzini 3782942e420SDaniel P. Berrange static struct addrinfo *inet_parse_connect_saddr(InetSocketAddress *saddr, 3792942e420SDaniel P. Berrange Error **errp) 380baacf047SPaolo Bonzini { 381baacf047SPaolo Bonzini struct addrinfo ai, *res; 382baacf047SPaolo Bonzini int rc; 3832942e420SDaniel P. Berrange Error *err = NULL; 384340849a9SDaniel P. Berrange static int useV4Mapped = 1; 385baacf047SPaolo Bonzini 386baacf047SPaolo Bonzini memset(&ai, 0, sizeof(ai)); 387baacf047SPaolo Bonzini 388340849a9SDaniel P. Berrange ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; 389340849a9SDaniel P. Berrange if (atomic_read(&useV4Mapped)) { 390340849a9SDaniel P. Berrange ai.ai_flags |= AI_V4MAPPED; 391340849a9SDaniel P. Berrange } 3922942e420SDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(saddr, &err); 393baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 394baacf047SPaolo Bonzini 3952942e420SDaniel P. Berrange if (err) { 3962942e420SDaniel P. Berrange error_propagate(errp, err); 3972942e420SDaniel P. Berrange return NULL; 3982942e420SDaniel P. Berrange } 3992942e420SDaniel P. Berrange 4002942e420SDaniel P. Berrange if (saddr->host == NULL || saddr->port == NULL) { 401baacf047SPaolo Bonzini error_setg(errp, "host and/or port not specified"); 402baacf047SPaolo Bonzini return NULL; 403baacf047SPaolo Bonzini } 404baacf047SPaolo Bonzini 405baacf047SPaolo Bonzini /* lookup */ 4062942e420SDaniel P. Berrange rc = getaddrinfo(saddr->host, saddr->port, &ai, &res); 407340849a9SDaniel P. Berrange 408340849a9SDaniel P. Berrange /* At least FreeBSD and OS-X 10.6 declare AI_V4MAPPED but 409340849a9SDaniel P. Berrange * then don't implement it in their getaddrinfo(). Detect 410340849a9SDaniel P. Berrange * this and retry without the flag since that's preferrable 411340849a9SDaniel P. Berrange * to a fatal error 412340849a9SDaniel P. Berrange */ 413340849a9SDaniel P. Berrange if (rc == EAI_BADFLAGS && 414340849a9SDaniel P. Berrange (ai.ai_flags & AI_V4MAPPED)) { 415340849a9SDaniel P. Berrange atomic_set(&useV4Mapped, 0); 416340849a9SDaniel P. Berrange ai.ai_flags &= ~AI_V4MAPPED; 417340849a9SDaniel P. Berrange rc = getaddrinfo(saddr->host, saddr->port, &ai, &res); 418340849a9SDaniel P. Berrange } 419baacf047SPaolo Bonzini if (rc != 0) { 4202942e420SDaniel P. Berrange error_setg(errp, "address resolution failed for %s:%s: %s", 4212942e420SDaniel P. Berrange saddr->host, saddr->port, gai_strerror(rc)); 422baacf047SPaolo Bonzini return NULL; 423baacf047SPaolo Bonzini } 424baacf047SPaolo Bonzini return res; 425baacf047SPaolo Bonzini } 426baacf047SPaolo Bonzini 427baacf047SPaolo Bonzini /** 428baacf047SPaolo Bonzini * Create a socket and connect it to an address. 429baacf047SPaolo Bonzini * 4302942e420SDaniel P. Berrange * @saddr: Inet socket address specification 431baacf047SPaolo Bonzini * @errp: set on error 432baacf047SPaolo Bonzini * 433baacf047SPaolo Bonzini * Returns: -1 on error, file descriptor on success. 434baacf047SPaolo Bonzini */ 435b2587932SCao jin int inet_connect_saddr(InetSocketAddress *saddr, Error **errp) 436baacf047SPaolo Bonzini { 4373f9286b7SMarkus Armbruster Error *local_err = NULL; 438baacf047SPaolo Bonzini struct addrinfo *res, *e; 439baacf047SPaolo Bonzini int sock = -1; 440baacf047SPaolo Bonzini 4412942e420SDaniel P. Berrange res = inet_parse_connect_saddr(saddr, errp); 442baacf047SPaolo Bonzini if (!res) { 443baacf047SPaolo Bonzini return -1; 444baacf047SPaolo Bonzini } 445baacf047SPaolo Bonzini 446baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 4473f9286b7SMarkus Armbruster error_free(local_err); 4483f9286b7SMarkus Armbruster local_err = NULL; 449b2587932SCao jin sock = inet_connect_addr(e, &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 } 458b2587932SCao jin 459baacf047SPaolo Bonzini freeaddrinfo(res); 460baacf047SPaolo Bonzini return sock; 461baacf047SPaolo Bonzini } 462baacf047SPaolo Bonzini 4638b39910eSDaniel P. Berrange static int inet_dgram_saddr(InetSocketAddress *sraddr, 4648b39910eSDaniel P. Berrange InetSocketAddress *sladdr, 4658b39910eSDaniel P. Berrange Error **errp) 466baacf047SPaolo Bonzini { 467baacf047SPaolo Bonzini struct addrinfo ai, *peer = NULL, *local = NULL; 468baacf047SPaolo Bonzini const char *addr; 469baacf047SPaolo Bonzini const char *port; 470baacf047SPaolo Bonzini int sock = -1, rc; 4718b39910eSDaniel P. Berrange Error *err = NULL; 472baacf047SPaolo Bonzini 473baacf047SPaolo Bonzini /* lookup peer addr */ 474baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 4753de3d698SWolfgang Bumiller ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG; 4768b39910eSDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(sraddr, &err); 477baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 478baacf047SPaolo Bonzini 4798b39910eSDaniel P. Berrange if (err) { 4808b39910eSDaniel P. Berrange error_propagate(errp, err); 48158c652c0SPaolo Bonzini goto err; 4828b39910eSDaniel P. Berrange } 4838b39910eSDaniel P. Berrange 4848b39910eSDaniel P. Berrange addr = sraddr->host; 4858b39910eSDaniel P. Berrange port = sraddr->port; 486baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 487baacf047SPaolo Bonzini addr = "localhost"; 488baacf047SPaolo Bonzini } 489baacf047SPaolo Bonzini if (port == NULL || strlen(port) == 0) { 490baacf047SPaolo Bonzini error_setg(errp, "remote port not specified"); 49158c652c0SPaolo Bonzini goto err; 492baacf047SPaolo Bonzini } 493baacf047SPaolo Bonzini 4949cd1883cSCao jin if ((rc = getaddrinfo(addr, port, &ai, &peer)) != 0) { 495baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 496baacf047SPaolo Bonzini gai_strerror(rc)); 49758c652c0SPaolo Bonzini goto err; 498baacf047SPaolo Bonzini } 499baacf047SPaolo Bonzini 500baacf047SPaolo Bonzini /* lookup local addr */ 501baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 502baacf047SPaolo Bonzini ai.ai_flags = AI_PASSIVE; 503baacf047SPaolo Bonzini ai.ai_family = peer->ai_family; 504baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 505baacf047SPaolo Bonzini 5068b39910eSDaniel P. Berrange if (sladdr) { 5078b39910eSDaniel P. Berrange addr = sladdr->host; 5088b39910eSDaniel P. Berrange port = sladdr->port; 509baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 510baacf047SPaolo Bonzini addr = NULL; 511baacf047SPaolo Bonzini } 5128b39910eSDaniel P. Berrange if (!port || strlen(port) == 0) { 513baacf047SPaolo Bonzini port = "0"; 5148b39910eSDaniel P. Berrange } 5158b39910eSDaniel P. Berrange } else { 5168b39910eSDaniel P. Berrange addr = NULL; 5178b39910eSDaniel P. Berrange port = "0"; 5188b39910eSDaniel P. Berrange } 519baacf047SPaolo Bonzini 5209cd1883cSCao jin if ((rc = getaddrinfo(addr, port, &ai, &local)) != 0) { 521baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 522baacf047SPaolo Bonzini gai_strerror(rc)); 523baacf047SPaolo Bonzini goto err; 524baacf047SPaolo Bonzini } 525baacf047SPaolo Bonzini 526baacf047SPaolo Bonzini /* create socket */ 527baacf047SPaolo Bonzini sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); 528baacf047SPaolo Bonzini if (sock < 0) { 529235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 530baacf047SPaolo Bonzini goto err; 531baacf047SPaolo Bonzini } 53204fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 533baacf047SPaolo Bonzini 534baacf047SPaolo Bonzini /* bind socket */ 535baacf047SPaolo Bonzini if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { 536235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to bind socket"); 537baacf047SPaolo Bonzini goto err; 538baacf047SPaolo Bonzini } 539baacf047SPaolo Bonzini 540baacf047SPaolo Bonzini /* connect to peer */ 541baacf047SPaolo Bonzini if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { 542235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to connect socket"); 543baacf047SPaolo Bonzini goto err; 544baacf047SPaolo Bonzini } 545baacf047SPaolo Bonzini 546baacf047SPaolo Bonzini freeaddrinfo(local); 547baacf047SPaolo Bonzini freeaddrinfo(peer); 548baacf047SPaolo Bonzini return sock; 549baacf047SPaolo Bonzini 550baacf047SPaolo Bonzini err: 55126015051SCao jin if (sock != -1) { 552baacf047SPaolo Bonzini closesocket(sock); 55326015051SCao jin } 55426015051SCao jin if (local) { 555baacf047SPaolo Bonzini freeaddrinfo(local); 55626015051SCao jin } 55726015051SCao jin if (peer) { 558baacf047SPaolo Bonzini freeaddrinfo(peer); 55926015051SCao jin } 56026015051SCao jin 561baacf047SPaolo Bonzini return -1; 562baacf047SPaolo Bonzini } 563baacf047SPaolo Bonzini 564baacf047SPaolo Bonzini /* compatibility wrapper */ 5653e32370aSDaniel P. Berrange static int inet_parse_flag(const char *flagname, const char *optstr, bool *val, 5663e32370aSDaniel P. Berrange Error **errp) 5673e32370aSDaniel P. Berrange { 5683e32370aSDaniel P. Berrange char *end; 5693e32370aSDaniel P. Berrange size_t len; 5703e32370aSDaniel P. Berrange 5713e32370aSDaniel P. Berrange end = strstr(optstr, ","); 5723e32370aSDaniel P. Berrange if (end) { 5733e32370aSDaniel P. Berrange if (end[1] == ',') { /* Reject 'ipv6=on,,foo' */ 5743e32370aSDaniel P. Berrange error_setg(errp, "error parsing '%s' flag '%s'", flagname, optstr); 5753e32370aSDaniel P. Berrange return -1; 5763e32370aSDaniel P. Berrange } 5773e32370aSDaniel P. Berrange len = end - optstr; 5783e32370aSDaniel P. Berrange } else { 5793e32370aSDaniel P. Berrange len = strlen(optstr); 5803e32370aSDaniel P. Berrange } 5813e32370aSDaniel P. Berrange if (len == 0 || (len == 3 && strncmp(optstr, "=on", len) == 0)) { 5823e32370aSDaniel P. Berrange *val = true; 5833e32370aSDaniel P. Berrange } else if (len == 4 && strncmp(optstr, "=off", len) == 0) { 5843e32370aSDaniel P. Berrange *val = false; 5853e32370aSDaniel P. Berrange } else { 5863e32370aSDaniel P. Berrange error_setg(errp, "error parsing '%s' flag '%s'", flagname, optstr); 5873e32370aSDaniel P. Berrange return -1; 5883e32370aSDaniel P. Berrange } 5893e32370aSDaniel P. Berrange return 0; 5903e32370aSDaniel P. Berrange } 5913e32370aSDaniel P. Berrange 5920785bd7aSMarkus Armbruster int inet_parse(InetSocketAddress *addr, const char *str, Error **errp) 593baacf047SPaolo Bonzini { 594baacf047SPaolo Bonzini const char *optstr, *h; 59555a10996SKevin Wolf char host[65]; 596baacf047SPaolo Bonzini char port[33]; 597baacf047SPaolo Bonzini int to; 598baacf047SPaolo Bonzini int pos; 5993e32370aSDaniel P. Berrange char *begin; 600baacf047SPaolo Bonzini 6010785bd7aSMarkus Armbruster memset(addr, 0, sizeof(*addr)); 602baacf047SPaolo Bonzini 603baacf047SPaolo Bonzini /* parse address */ 604baacf047SPaolo Bonzini if (str[0] == ':') { 605baacf047SPaolo Bonzini /* no host given */ 606baacf047SPaolo Bonzini host[0] = '\0'; 6079cd1883cSCao jin if (sscanf(str, ":%32[^,]%n", port, &pos) != 1) { 608baacf047SPaolo Bonzini error_setg(errp, "error parsing port in address '%s'", str); 6090785bd7aSMarkus Armbruster return -1; 610baacf047SPaolo Bonzini } 611baacf047SPaolo Bonzini } else if (str[0] == '[') { 612baacf047SPaolo Bonzini /* IPv6 addr */ 6139cd1883cSCao jin if (sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos) != 2) { 614baacf047SPaolo Bonzini error_setg(errp, "error parsing IPv6 address '%s'", str); 6150785bd7aSMarkus Armbruster return -1; 616baacf047SPaolo Bonzini } 617baacf047SPaolo Bonzini } else { 618391b7b97SJán Tomko /* hostname or IPv4 addr */ 6199cd1883cSCao jin if (sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos) != 2) { 620baacf047SPaolo Bonzini error_setg(errp, "error parsing address '%s'", str); 6210785bd7aSMarkus Armbruster return -1; 622baacf047SPaolo Bonzini } 623baacf047SPaolo Bonzini } 624baacf047SPaolo Bonzini 625baacf047SPaolo Bonzini addr->host = g_strdup(host); 626baacf047SPaolo Bonzini addr->port = g_strdup(port); 627baacf047SPaolo Bonzini 628baacf047SPaolo Bonzini /* parse options */ 629baacf047SPaolo Bonzini optstr = str + pos; 630baacf047SPaolo Bonzini h = strstr(optstr, ",to="); 631baacf047SPaolo Bonzini if (h) { 632baacf047SPaolo Bonzini h += 4; 633baacf047SPaolo Bonzini if (sscanf(h, "%d%n", &to, &pos) != 1 || 634baacf047SPaolo Bonzini (h[pos] != '\0' && h[pos] != ',')) { 635baacf047SPaolo Bonzini error_setg(errp, "error parsing to= argument"); 6360785bd7aSMarkus Armbruster return -1; 637baacf047SPaolo Bonzini } 638baacf047SPaolo Bonzini addr->has_to = true; 639baacf047SPaolo Bonzini addr->to = to; 640baacf047SPaolo Bonzini } 6413e32370aSDaniel P. Berrange begin = strstr(optstr, ",ipv4"); 6423e32370aSDaniel P. Berrange if (begin) { 6433e32370aSDaniel P. Berrange if (inet_parse_flag("ipv4", begin + 5, &addr->ipv4, errp) < 0) { 6443e32370aSDaniel P. Berrange return -1; 645baacf047SPaolo Bonzini } 6463e32370aSDaniel P. Berrange addr->has_ipv4 = true; 6473e32370aSDaniel P. Berrange } 6483e32370aSDaniel P. Berrange begin = strstr(optstr, ",ipv6"); 6493e32370aSDaniel P. Berrange if (begin) { 6503e32370aSDaniel P. Berrange if (inet_parse_flag("ipv6", begin + 5, &addr->ipv6, errp) < 0) { 6513e32370aSDaniel P. Berrange return -1; 6523e32370aSDaniel P. Berrange } 6533e32370aSDaniel P. Berrange addr->has_ipv6 = true; 654baacf047SPaolo Bonzini } 6550785bd7aSMarkus Armbruster return 0; 656baacf047SPaolo Bonzini } 657baacf047SPaolo Bonzini 658baacf047SPaolo Bonzini 659baacf047SPaolo Bonzini /** 660baacf047SPaolo Bonzini * Create a blocking socket and connect it to an address. 661baacf047SPaolo Bonzini * 662baacf047SPaolo Bonzini * @str: address string 663baacf047SPaolo Bonzini * @errp: set in case of an error 664baacf047SPaolo Bonzini * 665baacf047SPaolo Bonzini * Returns -1 in case of error, file descriptor on success 666baacf047SPaolo Bonzini **/ 667baacf047SPaolo Bonzini int inet_connect(const char *str, Error **errp) 668baacf047SPaolo Bonzini { 669baacf047SPaolo Bonzini int sock = -1; 6700785bd7aSMarkus Armbruster InetSocketAddress *addr = g_new(InetSocketAddress, 1); 671baacf047SPaolo Bonzini 6720785bd7aSMarkus Armbruster if (!inet_parse(addr, str, errp)) { 673b2587932SCao jin sock = inet_connect_saddr(addr, errp); 674baacf047SPaolo Bonzini } 6750785bd7aSMarkus Armbruster qapi_free_InetSocketAddress(addr); 676baacf047SPaolo Bonzini return sock; 677baacf047SPaolo Bonzini } 678baacf047SPaolo Bonzini 6796a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 6806a02c806SStefan Hajnoczi static bool vsock_parse_vaddr_to_sockaddr(const VsockSocketAddress *vaddr, 6816a02c806SStefan Hajnoczi struct sockaddr_vm *svm, 6826a02c806SStefan Hajnoczi Error **errp) 6836a02c806SStefan Hajnoczi { 6846a02c806SStefan Hajnoczi unsigned long long val; 6856a02c806SStefan Hajnoczi 6866a02c806SStefan Hajnoczi memset(svm, 0, sizeof(*svm)); 6876a02c806SStefan Hajnoczi svm->svm_family = AF_VSOCK; 6886a02c806SStefan Hajnoczi 6896a02c806SStefan Hajnoczi if (parse_uint_full(vaddr->cid, &val, 10) < 0 || 6906a02c806SStefan Hajnoczi val > UINT32_MAX) { 6916a02c806SStefan Hajnoczi error_setg(errp, "Failed to parse cid '%s'", vaddr->cid); 6926a02c806SStefan Hajnoczi return false; 6936a02c806SStefan Hajnoczi } 6946a02c806SStefan Hajnoczi svm->svm_cid = val; 6956a02c806SStefan Hajnoczi 6966a02c806SStefan Hajnoczi if (parse_uint_full(vaddr->port, &val, 10) < 0 || 6976a02c806SStefan Hajnoczi val > UINT32_MAX) { 6986a02c806SStefan Hajnoczi error_setg(errp, "Failed to parse port '%s'", vaddr->port); 6996a02c806SStefan Hajnoczi return false; 7006a02c806SStefan Hajnoczi } 7016a02c806SStefan Hajnoczi svm->svm_port = val; 7026a02c806SStefan Hajnoczi 7036a02c806SStefan Hajnoczi return true; 7046a02c806SStefan Hajnoczi } 7056a02c806SStefan Hajnoczi 706b2587932SCao jin static int vsock_connect_addr(const struct sockaddr_vm *svm, Error **errp) 7076a02c806SStefan Hajnoczi { 7086a02c806SStefan Hajnoczi int sock, rc; 7096a02c806SStefan Hajnoczi 7106a02c806SStefan Hajnoczi sock = qemu_socket(AF_VSOCK, SOCK_STREAM, 0); 7116a02c806SStefan Hajnoczi if (sock < 0) { 7126a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to create socket"); 7136a02c806SStefan Hajnoczi return -1; 7146a02c806SStefan Hajnoczi } 715b2587932SCao jin 7166a02c806SStefan Hajnoczi /* connect to peer */ 7176a02c806SStefan Hajnoczi do { 7186a02c806SStefan Hajnoczi rc = 0; 7196a02c806SStefan Hajnoczi if (connect(sock, (const struct sockaddr *)svm, sizeof(*svm)) < 0) { 7206a02c806SStefan Hajnoczi rc = -errno; 7216a02c806SStefan Hajnoczi } 7226a02c806SStefan Hajnoczi } while (rc == -EINTR); 7236a02c806SStefan Hajnoczi 724b2587932SCao jin if (rc < 0) { 7256a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to connect socket"); 7266a02c806SStefan Hajnoczi closesocket(sock); 7276a02c806SStefan Hajnoczi return -1; 7286a02c806SStefan Hajnoczi } 729b2587932SCao jin 7306a02c806SStefan Hajnoczi return sock; 7316a02c806SStefan Hajnoczi } 7326a02c806SStefan Hajnoczi 733b2587932SCao jin static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp) 7346a02c806SStefan Hajnoczi { 7356a02c806SStefan Hajnoczi struct sockaddr_vm svm; 7366a02c806SStefan Hajnoczi int sock = -1; 7376a02c806SStefan Hajnoczi 7386a02c806SStefan Hajnoczi if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) { 7396a02c806SStefan Hajnoczi return -1; 7406a02c806SStefan Hajnoczi } 7416a02c806SStefan Hajnoczi 742b2587932SCao jin sock = vsock_connect_addr(&svm, errp); 7436a02c806SStefan Hajnoczi 7446a02c806SStefan Hajnoczi return sock; 7456a02c806SStefan Hajnoczi } 7466a02c806SStefan Hajnoczi 7476a02c806SStefan Hajnoczi static int vsock_listen_saddr(VsockSocketAddress *vaddr, 7486a02c806SStefan Hajnoczi Error **errp) 7496a02c806SStefan Hajnoczi { 7506a02c806SStefan Hajnoczi struct sockaddr_vm svm; 7516a02c806SStefan Hajnoczi int slisten; 7526a02c806SStefan Hajnoczi 7536a02c806SStefan Hajnoczi if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) { 7546a02c806SStefan Hajnoczi return -1; 7556a02c806SStefan Hajnoczi } 7566a02c806SStefan Hajnoczi 7576a02c806SStefan Hajnoczi slisten = qemu_socket(AF_VSOCK, SOCK_STREAM, 0); 7586a02c806SStefan Hajnoczi if (slisten < 0) { 7596a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to create socket"); 7606a02c806SStefan Hajnoczi return -1; 7616a02c806SStefan Hajnoczi } 7626a02c806SStefan Hajnoczi 7636a02c806SStefan Hajnoczi if (bind(slisten, (const struct sockaddr *)&svm, sizeof(svm)) != 0) { 7646a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to bind socket"); 7656a02c806SStefan Hajnoczi closesocket(slisten); 7666a02c806SStefan Hajnoczi return -1; 7676a02c806SStefan Hajnoczi } 7686a02c806SStefan Hajnoczi 7696a02c806SStefan Hajnoczi if (listen(slisten, 1) != 0) { 7706a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to listen on socket"); 7716a02c806SStefan Hajnoczi closesocket(slisten); 7726a02c806SStefan Hajnoczi return -1; 7736a02c806SStefan Hajnoczi } 7746a02c806SStefan Hajnoczi return slisten; 7756a02c806SStefan Hajnoczi } 7766a02c806SStefan Hajnoczi 7774db5c619SMarkus Armbruster static int vsock_parse(VsockSocketAddress *addr, const char *str, 7784db5c619SMarkus Armbruster Error **errp) 7796a02c806SStefan Hajnoczi { 7806a02c806SStefan Hajnoczi char cid[33]; 7816a02c806SStefan Hajnoczi char port[33]; 7826a02c806SStefan Hajnoczi int n; 7836a02c806SStefan Hajnoczi 7846a02c806SStefan Hajnoczi if (sscanf(str, "%32[^:]:%32[^,]%n", cid, port, &n) != 2) { 7856a02c806SStefan Hajnoczi error_setg(errp, "error parsing address '%s'", str); 7864db5c619SMarkus Armbruster return -1; 7876a02c806SStefan Hajnoczi } 7886a02c806SStefan Hajnoczi if (str[n] != '\0') { 7896a02c806SStefan Hajnoczi error_setg(errp, "trailing characters in address '%s'", str); 7904db5c619SMarkus Armbruster return -1; 7916a02c806SStefan Hajnoczi } 7926a02c806SStefan Hajnoczi 7936a02c806SStefan Hajnoczi addr->cid = g_strdup(cid); 7946a02c806SStefan Hajnoczi addr->port = g_strdup(port); 7954db5c619SMarkus Armbruster return 0; 7966a02c806SStefan Hajnoczi } 7976a02c806SStefan Hajnoczi #else 7986a02c806SStefan Hajnoczi static void vsock_unsupported(Error **errp) 7996a02c806SStefan Hajnoczi { 8006a02c806SStefan Hajnoczi error_setg(errp, "socket family AF_VSOCK unsupported"); 8016a02c806SStefan Hajnoczi } 8026a02c806SStefan Hajnoczi 803b2587932SCao jin static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp) 8046a02c806SStefan Hajnoczi { 8056a02c806SStefan Hajnoczi vsock_unsupported(errp); 8066a02c806SStefan Hajnoczi return -1; 8076a02c806SStefan Hajnoczi } 8086a02c806SStefan Hajnoczi 8096a02c806SStefan Hajnoczi static int vsock_listen_saddr(VsockSocketAddress *vaddr, 8106a02c806SStefan Hajnoczi Error **errp) 8116a02c806SStefan Hajnoczi { 8126a02c806SStefan Hajnoczi vsock_unsupported(errp); 8136a02c806SStefan Hajnoczi return -1; 8146a02c806SStefan Hajnoczi } 8156a02c806SStefan Hajnoczi 8164db5c619SMarkus Armbruster static int vsock_parse(VsockSocketAddress *addr, const char *str, 8174db5c619SMarkus Armbruster Error **errp) 8186a02c806SStefan Hajnoczi { 8196a02c806SStefan Hajnoczi vsock_unsupported(errp); 8204db5c619SMarkus Armbruster return -1; 8216a02c806SStefan Hajnoczi } 8226a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 8236a02c806SStefan Hajnoczi 824baacf047SPaolo Bonzini #ifndef _WIN32 825baacf047SPaolo Bonzini 8261856835dSDaniel P. Berrange static int unix_listen_saddr(UnixSocketAddress *saddr, 8271856835dSDaniel P. Berrange Error **errp) 828baacf047SPaolo Bonzini { 829baacf047SPaolo Bonzini struct sockaddr_un un; 830baacf047SPaolo Bonzini int sock, fd; 831ad9579aaSDaniel P. Berrange char *pathbuf = NULL; 832ad9579aaSDaniel P. Berrange const char *path; 8332d2023c3SDaniel P. Berrangé size_t pathlen; 834baacf047SPaolo Bonzini 835baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 836baacf047SPaolo Bonzini if (sock < 0) { 837b658c53dSPaolo Bonzini error_setg_errno(errp, errno, "Failed to create Unix socket"); 838baacf047SPaolo Bonzini return -1; 839baacf047SPaolo Bonzini } 840baacf047SPaolo Bonzini 841ad9579aaSDaniel P. Berrange if (saddr->path && saddr->path[0]) { 842ad9579aaSDaniel P. Berrange path = saddr->path; 843baacf047SPaolo Bonzini } else { 844b658c53dSPaolo Bonzini const char *tmpdir = getenv("TMPDIR"); 845b658c53dSPaolo Bonzini tmpdir = tmpdir ? tmpdir : "/tmp"; 846ad9579aaSDaniel P. Berrange path = pathbuf = g_strdup_printf("%s/qemu-socket-XXXXXX", tmpdir); 847ad9579aaSDaniel P. Berrange } 848ad9579aaSDaniel P. Berrange 8492d2023c3SDaniel P. Berrangé pathlen = strlen(path); 8502d2023c3SDaniel P. Berrangé if (pathlen > sizeof(un.sun_path)) { 851ad9579aaSDaniel P. Berrange error_setg(errp, "UNIX socket path '%s' is too long", path); 852ad9579aaSDaniel P. Berrange error_append_hint(errp, "Path must be less than %zu bytes\n", 853ad9579aaSDaniel P. Berrange sizeof(un.sun_path)); 854b658c53dSPaolo Bonzini goto err; 855b658c53dSPaolo Bonzini } 856b658c53dSPaolo Bonzini 857ad9579aaSDaniel P. Berrange if (pathbuf != NULL) { 858baacf047SPaolo Bonzini /* 859baacf047SPaolo Bonzini * This dummy fd usage silences the mktemp() unsecure warning. 860baacf047SPaolo Bonzini * Using mkstemp() doesn't make things more secure here 861baacf047SPaolo Bonzini * though. bind() complains about existing files, so we have 862baacf047SPaolo Bonzini * to unlink first and thus re-open the race window. The 863baacf047SPaolo Bonzini * worst case possible is bind() failing, i.e. a DoS attack. 864baacf047SPaolo Bonzini */ 865ad9579aaSDaniel P. Berrange fd = mkstemp(pathbuf); 866b658c53dSPaolo Bonzini if (fd < 0) { 867b658c53dSPaolo Bonzini error_setg_errno(errp, errno, 868ad9579aaSDaniel P. Berrange "Failed to make a temporary socket %s", pathbuf); 869b658c53dSPaolo Bonzini goto err; 870b658c53dSPaolo Bonzini } 871b658c53dSPaolo Bonzini close(fd); 872baacf047SPaolo Bonzini } 873baacf047SPaolo Bonzini 874ad9579aaSDaniel P. Berrange if (unlink(path) < 0 && errno != ENOENT) { 8750ef705a2SCole Robinson error_setg_errno(errp, errno, 876ad9579aaSDaniel P. Berrange "Failed to unlink socket %s", path); 8770ef705a2SCole Robinson goto err; 8780ef705a2SCole Robinson } 879ad9579aaSDaniel P. Berrange 880ad9579aaSDaniel P. Berrange memset(&un, 0, sizeof(un)); 881ad9579aaSDaniel P. Berrange un.sun_family = AF_UNIX; 8822d2023c3SDaniel P. Berrangé memcpy(un.sun_path, path, pathlen); 883ad9579aaSDaniel P. Berrange 884baacf047SPaolo Bonzini if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { 88556382bd5SDaniel P. Berrange error_setg_errno(errp, errno, "Failed to bind socket to %s", path); 886baacf047SPaolo Bonzini goto err; 887baacf047SPaolo Bonzini } 888baacf047SPaolo Bonzini if (listen(sock, 1) < 0) { 889235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to listen on socket"); 890baacf047SPaolo Bonzini goto err; 891baacf047SPaolo Bonzini } 892baacf047SPaolo Bonzini 893ad9579aaSDaniel P. Berrange g_free(pathbuf); 894baacf047SPaolo Bonzini return sock; 895baacf047SPaolo Bonzini 896baacf047SPaolo Bonzini err: 897ad9579aaSDaniel P. Berrange g_free(pathbuf); 898baacf047SPaolo Bonzini closesocket(sock); 899baacf047SPaolo Bonzini return -1; 900baacf047SPaolo Bonzini } 901baacf047SPaolo Bonzini 902b2587932SCao jin static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) 903baacf047SPaolo Bonzini { 904baacf047SPaolo Bonzini struct sockaddr_un un; 905baacf047SPaolo Bonzini int sock, rc; 9062d2023c3SDaniel P. Berrangé size_t pathlen; 907baacf047SPaolo Bonzini 9082942e420SDaniel P. Berrange if (saddr->path == NULL) { 909312fd5f2SMarkus Armbruster error_setg(errp, "unix connect: no path specified"); 910baacf047SPaolo Bonzini return -1; 911baacf047SPaolo Bonzini } 912baacf047SPaolo Bonzini 913baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 914baacf047SPaolo Bonzini if (sock < 0) { 915235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 916baacf047SPaolo Bonzini return -1; 917baacf047SPaolo Bonzini } 918baacf047SPaolo Bonzini 9192d2023c3SDaniel P. Berrangé pathlen = strlen(saddr->path); 9202d2023c3SDaniel P. Berrangé if (pathlen > sizeof(un.sun_path)) { 921ad9579aaSDaniel P. Berrange error_setg(errp, "UNIX socket path '%s' is too long", saddr->path); 922ad9579aaSDaniel P. Berrange error_append_hint(errp, "Path must be less than %zu bytes\n", 923ad9579aaSDaniel P. Berrange sizeof(un.sun_path)); 924ad9579aaSDaniel P. Berrange goto err; 925ad9579aaSDaniel P. Berrange } 926ad9579aaSDaniel P. Berrange 927baacf047SPaolo Bonzini memset(&un, 0, sizeof(un)); 928baacf047SPaolo Bonzini un.sun_family = AF_UNIX; 9292d2023c3SDaniel P. Berrangé memcpy(un.sun_path, saddr->path, pathlen); 930baacf047SPaolo Bonzini 931baacf047SPaolo Bonzini /* connect to peer */ 932baacf047SPaolo Bonzini do { 933baacf047SPaolo Bonzini rc = 0; 934baacf047SPaolo Bonzini if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { 935b16a44e1SDaniel P. Berrange rc = -errno; 936baacf047SPaolo Bonzini } 937baacf047SPaolo Bonzini } while (rc == -EINTR); 938baacf047SPaolo Bonzini 939baacf047SPaolo Bonzini if (rc < 0) { 940ad9579aaSDaniel P. Berrange error_setg_errno(errp, -rc, "Failed to connect socket %s", 941ad9579aaSDaniel P. Berrange saddr->path); 942ad9579aaSDaniel P. Berrange goto err; 943baacf047SPaolo Bonzini } 944baacf047SPaolo Bonzini 945baacf047SPaolo Bonzini return sock; 946ad9579aaSDaniel P. Berrange 947ad9579aaSDaniel P. Berrange err: 948ad9579aaSDaniel P. Berrange close(sock); 949ad9579aaSDaniel P. Berrange return -1; 950baacf047SPaolo Bonzini } 951baacf047SPaolo Bonzini 952baacf047SPaolo Bonzini #else 953baacf047SPaolo Bonzini 9541856835dSDaniel P. Berrange static int unix_listen_saddr(UnixSocketAddress *saddr, 9551856835dSDaniel P. Berrange Error **errp) 956baacf047SPaolo Bonzini { 957baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 958baacf047SPaolo Bonzini errno = ENOTSUP; 959baacf047SPaolo Bonzini return -1; 960baacf047SPaolo Bonzini } 961baacf047SPaolo Bonzini 962b2587932SCao jin static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) 963baacf047SPaolo Bonzini { 964baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 965baacf047SPaolo Bonzini errno = ENOTSUP; 966baacf047SPaolo Bonzini return -1; 967baacf047SPaolo Bonzini } 968baacf047SPaolo Bonzini #endif 969baacf047SPaolo Bonzini 970baacf047SPaolo Bonzini /* compatibility wrapper */ 97162473511SDaniel P. Berrange int unix_listen(const char *str, Error **errp) 972baacf047SPaolo Bonzini { 9731856835dSDaniel P. Berrange UnixSocketAddress *saddr; 974*caf88d74SMarc-André Lureau int sock; 975baacf047SPaolo Bonzini 9761856835dSDaniel P. Berrange saddr = g_new0(UnixSocketAddress, 1); 9771856835dSDaniel P. Berrange saddr->path = g_strdup(str); 97862473511SDaniel P. Berrange sock = unix_listen_saddr(saddr, errp); 9791856835dSDaniel P. Berrange qapi_free_UnixSocketAddress(saddr); 980baacf047SPaolo Bonzini return sock; 981baacf047SPaolo Bonzini } 982baacf047SPaolo Bonzini 983baacf047SPaolo Bonzini int unix_connect(const char *path, Error **errp) 984baacf047SPaolo Bonzini { 9852942e420SDaniel P. Berrange UnixSocketAddress *saddr; 986baacf047SPaolo Bonzini int sock; 987baacf047SPaolo Bonzini 9882942e420SDaniel P. Berrange saddr = g_new0(UnixSocketAddress, 1); 9892942e420SDaniel P. Berrange saddr->path = g_strdup(path); 990b2587932SCao jin sock = unix_connect_saddr(saddr, errp); 9912942e420SDaniel P. Berrange qapi_free_UnixSocketAddress(saddr); 992baacf047SPaolo Bonzini return sock; 993baacf047SPaolo Bonzini } 994baacf047SPaolo Bonzini 995baacf047SPaolo Bonzini 996bd269ebcSMarkus Armbruster SocketAddress *socket_parse(const char *str, Error **errp) 997baacf047SPaolo Bonzini { 998bd269ebcSMarkus Armbruster SocketAddress *addr; 999baacf047SPaolo Bonzini 1000bd269ebcSMarkus Armbruster addr = g_new0(SocketAddress, 1); 1001baacf047SPaolo Bonzini if (strstart(str, "unix:", NULL)) { 1002baacf047SPaolo Bonzini if (str[5] == '\0') { 1003312fd5f2SMarkus Armbruster error_setg(errp, "invalid Unix socket address"); 1004baacf047SPaolo Bonzini goto fail; 1005baacf047SPaolo Bonzini } else { 1006bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_UNIX; 1007bd269ebcSMarkus Armbruster addr->u.q_unix.path = g_strdup(str + 5); 1008baacf047SPaolo Bonzini } 1009baacf047SPaolo Bonzini } else if (strstart(str, "fd:", NULL)) { 1010baacf047SPaolo Bonzini if (str[3] == '\0') { 1011312fd5f2SMarkus Armbruster error_setg(errp, "invalid file descriptor address"); 1012baacf047SPaolo Bonzini goto fail; 1013baacf047SPaolo Bonzini } else { 1014bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_FD; 1015bd269ebcSMarkus Armbruster addr->u.fd.str = g_strdup(str + 3); 1016baacf047SPaolo Bonzini } 10176a02c806SStefan Hajnoczi } else if (strstart(str, "vsock:", NULL)) { 1018bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_VSOCK; 1019bd269ebcSMarkus Armbruster if (vsock_parse(&addr->u.vsock, str + strlen("vsock:"), errp)) { 10206a02c806SStefan Hajnoczi goto fail; 10216a02c806SStefan Hajnoczi } 1022baacf047SPaolo Bonzini } else { 1023bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_INET; 1024bd269ebcSMarkus Armbruster if (inet_parse(&addr->u.inet, str, errp)) { 1025baacf047SPaolo Bonzini goto fail; 1026baacf047SPaolo Bonzini } 1027baacf047SPaolo Bonzini } 1028baacf047SPaolo Bonzini return addr; 1029baacf047SPaolo Bonzini 1030baacf047SPaolo Bonzini fail: 1031bd269ebcSMarkus Armbruster qapi_free_SocketAddress(addr); 1032baacf047SPaolo Bonzini return NULL; 1033baacf047SPaolo Bonzini } 1034baacf047SPaolo Bonzini 103530bdb3c5SDaniel P. Berrange static int socket_get_fd(const char *fdstr, Error **errp) 103630bdb3c5SDaniel P. Berrange { 10371723d6b1SDaniel P. Berrange int fd; 10381723d6b1SDaniel P. Berrange if (cur_mon) { 10391723d6b1SDaniel P. Berrange fd = monitor_get_fd(cur_mon, fdstr, errp); 104030bdb3c5SDaniel P. Berrange if (fd < 0) { 104130bdb3c5SDaniel P. Berrange return -1; 104230bdb3c5SDaniel P. Berrange } 10431723d6b1SDaniel P. Berrange } else { 10441723d6b1SDaniel P. Berrange if (qemu_strtoi(fdstr, NULL, 10, &fd) < 0) { 10451723d6b1SDaniel P. Berrange error_setg_errno(errp, errno, 10461723d6b1SDaniel P. Berrange "Unable to parse FD number %s", 10471723d6b1SDaniel P. Berrange fdstr); 10481723d6b1SDaniel P. Berrange return -1; 10491723d6b1SDaniel P. Berrange } 10501723d6b1SDaniel P. Berrange } 105130bdb3c5SDaniel P. Berrange if (!fd_is_socket(fd)) { 105230bdb3c5SDaniel P. Berrange error_setg(errp, "File descriptor '%s' is not a socket", fdstr); 105330bdb3c5SDaniel P. Berrange close(fd); 105430bdb3c5SDaniel P. Berrange return -1; 105530bdb3c5SDaniel P. Berrange } 105630bdb3c5SDaniel P. Berrange return fd; 105730bdb3c5SDaniel P. Berrange } 105830bdb3c5SDaniel P. Berrange 1059b2587932SCao jin int socket_connect(SocketAddress *addr, Error **errp) 1060baacf047SPaolo Bonzini { 1061baacf047SPaolo Bonzini int fd; 1062baacf047SPaolo Bonzini 10632d32addaSEric Blake switch (addr->type) { 1064bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_INET: 1065b2587932SCao jin fd = inet_connect_saddr(&addr->u.inet, errp); 1066baacf047SPaolo Bonzini break; 1067baacf047SPaolo Bonzini 1068bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_UNIX: 1069b2587932SCao jin fd = unix_connect_saddr(&addr->u.q_unix, errp); 1070baacf047SPaolo Bonzini break; 1071baacf047SPaolo Bonzini 1072bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_FD: 107330bdb3c5SDaniel P. Berrange fd = socket_get_fd(addr->u.fd.str, errp); 1074baacf047SPaolo Bonzini break; 1075baacf047SPaolo Bonzini 1076bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_VSOCK: 1077b2587932SCao jin fd = vsock_connect_saddr(&addr->u.vsock, errp); 10786a02c806SStefan Hajnoczi break; 10796a02c806SStefan Hajnoczi 1080baacf047SPaolo Bonzini default: 1081baacf047SPaolo Bonzini abort(); 1082baacf047SPaolo Bonzini } 1083baacf047SPaolo Bonzini return fd; 1084baacf047SPaolo Bonzini } 1085baacf047SPaolo Bonzini 1086bd269ebcSMarkus Armbruster int socket_listen(SocketAddress *addr, Error **errp) 1087baacf047SPaolo Bonzini { 1088baacf047SPaolo Bonzini int fd; 1089baacf047SPaolo Bonzini 10902d32addaSEric Blake switch (addr->type) { 1091bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_INET: 109262473511SDaniel P. Berrange fd = inet_listen_saddr(&addr->u.inet, 0, errp); 1093baacf047SPaolo Bonzini break; 1094baacf047SPaolo Bonzini 1095bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_UNIX: 109662473511SDaniel P. Berrange fd = unix_listen_saddr(&addr->u.q_unix, errp); 1097baacf047SPaolo Bonzini break; 1098baacf047SPaolo Bonzini 1099bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_FD: 110030bdb3c5SDaniel P. Berrange fd = socket_get_fd(addr->u.fd.str, errp); 1101baacf047SPaolo Bonzini break; 1102baacf047SPaolo Bonzini 1103bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_VSOCK: 1104bd269ebcSMarkus Armbruster fd = vsock_listen_saddr(&addr->u.vsock, errp); 11056a02c806SStefan Hajnoczi break; 11066a02c806SStefan Hajnoczi 1107baacf047SPaolo Bonzini default: 1108baacf047SPaolo Bonzini abort(); 1109baacf047SPaolo Bonzini } 1110baacf047SPaolo Bonzini return fd; 1111baacf047SPaolo Bonzini } 1112baacf047SPaolo Bonzini 111374b6ce43SMarc-André Lureau void socket_listen_cleanup(int fd, Error **errp) 111474b6ce43SMarc-André Lureau { 1115bd269ebcSMarkus Armbruster SocketAddress *addr; 111674b6ce43SMarc-André Lureau 111774b6ce43SMarc-André Lureau addr = socket_local_address(fd, errp); 11182d7ad7c0SDaniel P. Berrange if (!addr) { 11192d7ad7c0SDaniel P. Berrange return; 11202d7ad7c0SDaniel P. Berrange } 112174b6ce43SMarc-André Lureau 1122bd269ebcSMarkus Armbruster if (addr->type == SOCKET_ADDRESS_TYPE_UNIX 1123bd269ebcSMarkus Armbruster && addr->u.q_unix.path) { 1124bd269ebcSMarkus Armbruster if (unlink(addr->u.q_unix.path) < 0 && errno != ENOENT) { 112574b6ce43SMarc-André Lureau error_setg_errno(errp, errno, 112674b6ce43SMarc-André Lureau "Failed to unlink socket %s", 1127bd269ebcSMarkus Armbruster addr->u.q_unix.path); 112874b6ce43SMarc-André Lureau } 112974b6ce43SMarc-André Lureau } 113074b6ce43SMarc-André Lureau 1131bd269ebcSMarkus Armbruster qapi_free_SocketAddress(addr); 113274b6ce43SMarc-André Lureau } 113374b6ce43SMarc-André Lureau 1134bd269ebcSMarkus Armbruster int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp) 11353ecc059dSGerd Hoffmann { 11363ecc059dSGerd Hoffmann int fd; 11373ecc059dSGerd Hoffmann 1138ca0b64e5SMarkus Armbruster /* 1139bd269ebcSMarkus Armbruster * TODO SOCKET_ADDRESS_TYPE_FD when fd is AF_INET or AF_INET6 1140ca0b64e5SMarkus Armbruster * (although other address families can do SOCK_DGRAM, too) 1141ca0b64e5SMarkus Armbruster */ 11422d32addaSEric Blake switch (remote->type) { 1143bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_INET: 1144bd269ebcSMarkus Armbruster fd = inet_dgram_saddr(&remote->u.inet, 1145bd269ebcSMarkus Armbruster local ? &local->u.inet : NULL, errp); 11463ecc059dSGerd Hoffmann break; 11473ecc059dSGerd Hoffmann 11483ecc059dSGerd Hoffmann default: 11493ecc059dSGerd Hoffmann error_setg(errp, "socket type unsupported for datagram"); 11507a5b6af1SGerd Hoffmann fd = -1; 11513ecc059dSGerd Hoffmann } 11523ecc059dSGerd Hoffmann return fd; 11533ecc059dSGerd Hoffmann } 115417c55decSDaniel P. Berrange 115517c55decSDaniel P. Berrange 1156bd269ebcSMarkus Armbruster static SocketAddress * 115717c55decSDaniel P. Berrange socket_sockaddr_to_address_inet(struct sockaddr_storage *sa, 115817c55decSDaniel P. Berrange socklen_t salen, 115917c55decSDaniel P. Berrange Error **errp) 116017c55decSDaniel P. Berrange { 116117c55decSDaniel P. Berrange char host[NI_MAXHOST]; 116217c55decSDaniel P. Berrange char serv[NI_MAXSERV]; 1163bd269ebcSMarkus Armbruster SocketAddress *addr; 11640399293eSEric Blake InetSocketAddress *inet; 116517c55decSDaniel P. Berrange int ret; 116617c55decSDaniel P. Berrange 116717c55decSDaniel P. Berrange ret = getnameinfo((struct sockaddr *)sa, salen, 116817c55decSDaniel P. Berrange host, sizeof(host), 116917c55decSDaniel P. Berrange serv, sizeof(serv), 117017c55decSDaniel P. Berrange NI_NUMERICHOST | NI_NUMERICSERV); 117117c55decSDaniel P. Berrange if (ret != 0) { 117217c55decSDaniel P. Berrange error_setg(errp, "Cannot format numeric socket address: %s", 117317c55decSDaniel P. Berrange gai_strerror(ret)); 117417c55decSDaniel P. Berrange return NULL; 117517c55decSDaniel P. Berrange } 117617c55decSDaniel P. Berrange 1177bd269ebcSMarkus Armbruster addr = g_new0(SocketAddress, 1); 1178bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_INET; 1179bd269ebcSMarkus Armbruster inet = &addr->u.inet; 11800399293eSEric Blake inet->host = g_strdup(host); 11810399293eSEric Blake inet->port = g_strdup(serv); 118217c55decSDaniel P. Berrange if (sa->ss_family == AF_INET) { 11830399293eSEric Blake inet->has_ipv4 = inet->ipv4 = true; 118417c55decSDaniel P. Berrange } else { 11850399293eSEric Blake inet->has_ipv6 = inet->ipv6 = true; 118617c55decSDaniel P. Berrange } 118717c55decSDaniel P. Berrange 118817c55decSDaniel P. Berrange return addr; 118917c55decSDaniel P. Berrange } 119017c55decSDaniel P. Berrange 119117c55decSDaniel P. Berrange 119217c55decSDaniel P. Berrange #ifndef WIN32 1193bd269ebcSMarkus Armbruster static SocketAddress * 119417c55decSDaniel P. Berrange socket_sockaddr_to_address_unix(struct sockaddr_storage *sa, 119517c55decSDaniel P. Berrange socklen_t salen, 119617c55decSDaniel P. Berrange Error **errp) 119717c55decSDaniel P. Berrange { 1198bd269ebcSMarkus Armbruster SocketAddress *addr; 119917c55decSDaniel P. Berrange struct sockaddr_un *su = (struct sockaddr_un *)sa; 120017c55decSDaniel P. Berrange 1201bd269ebcSMarkus Armbruster addr = g_new0(SocketAddress, 1); 1202bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_UNIX; 120317c55decSDaniel P. Berrange if (su->sun_path[0]) { 1204bd269ebcSMarkus Armbruster addr->u.q_unix.path = g_strndup(su->sun_path, sizeof(su->sun_path)); 120517c55decSDaniel P. Berrange } 120617c55decSDaniel P. Berrange 120717c55decSDaniel P. Berrange return addr; 120817c55decSDaniel P. Berrange } 120917c55decSDaniel P. Berrange #endif /* WIN32 */ 121017c55decSDaniel P. Berrange 12116a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 1212bd269ebcSMarkus Armbruster static SocketAddress * 12136a02c806SStefan Hajnoczi socket_sockaddr_to_address_vsock(struct sockaddr_storage *sa, 12146a02c806SStefan Hajnoczi socklen_t salen, 12156a02c806SStefan Hajnoczi Error **errp) 12166a02c806SStefan Hajnoczi { 1217bd269ebcSMarkus Armbruster SocketAddress *addr; 12186a02c806SStefan Hajnoczi VsockSocketAddress *vaddr; 12196a02c806SStefan Hajnoczi struct sockaddr_vm *svm = (struct sockaddr_vm *)sa; 12206a02c806SStefan Hajnoczi 1221bd269ebcSMarkus Armbruster addr = g_new0(SocketAddress, 1); 1222bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_VSOCK; 1223bd269ebcSMarkus Armbruster vaddr = &addr->u.vsock; 12246a02c806SStefan Hajnoczi vaddr->cid = g_strdup_printf("%u", svm->svm_cid); 12256a02c806SStefan Hajnoczi vaddr->port = g_strdup_printf("%u", svm->svm_port); 12266a02c806SStefan Hajnoczi 12276a02c806SStefan Hajnoczi return addr; 12286a02c806SStefan Hajnoczi } 12296a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 12306a02c806SStefan Hajnoczi 1231bd269ebcSMarkus Armbruster SocketAddress * 123217c55decSDaniel P. Berrange socket_sockaddr_to_address(struct sockaddr_storage *sa, 123317c55decSDaniel P. Berrange socklen_t salen, 123417c55decSDaniel P. Berrange Error **errp) 123517c55decSDaniel P. Berrange { 123617c55decSDaniel P. Berrange switch (sa->ss_family) { 123717c55decSDaniel P. Berrange case AF_INET: 123817c55decSDaniel P. Berrange case AF_INET6: 123917c55decSDaniel P. Berrange return socket_sockaddr_to_address_inet(sa, salen, errp); 124017c55decSDaniel P. Berrange 124117c55decSDaniel P. Berrange #ifndef WIN32 124217c55decSDaniel P. Berrange case AF_UNIX: 124317c55decSDaniel P. Berrange return socket_sockaddr_to_address_unix(sa, salen, errp); 124417c55decSDaniel P. Berrange #endif /* WIN32 */ 124517c55decSDaniel P. Berrange 12466a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 12476a02c806SStefan Hajnoczi case AF_VSOCK: 12486a02c806SStefan Hajnoczi return socket_sockaddr_to_address_vsock(sa, salen, errp); 12496a02c806SStefan Hajnoczi #endif 12506a02c806SStefan Hajnoczi 125117c55decSDaniel P. Berrange default: 125217c55decSDaniel P. Berrange error_setg(errp, "socket family %d unsupported", 125317c55decSDaniel P. Berrange sa->ss_family); 125417c55decSDaniel P. Berrange return NULL; 125517c55decSDaniel P. Berrange } 125617c55decSDaniel P. Berrange return 0; 125717c55decSDaniel P. Berrange } 125817c55decSDaniel P. Berrange 125917c55decSDaniel P. Berrange 1260bd269ebcSMarkus Armbruster SocketAddress *socket_local_address(int fd, Error **errp) 126117c55decSDaniel P. Berrange { 126217c55decSDaniel P. Berrange struct sockaddr_storage ss; 126317c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 126417c55decSDaniel P. Berrange 126517c55decSDaniel P. Berrange if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) { 1266b16a44e1SDaniel P. Berrange error_setg_errno(errp, errno, "%s", 126717c55decSDaniel P. Berrange "Unable to query local socket address"); 126817c55decSDaniel P. Berrange return NULL; 126917c55decSDaniel P. Berrange } 127017c55decSDaniel P. Berrange 127117c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 127217c55decSDaniel P. Berrange } 127317c55decSDaniel P. Berrange 127417c55decSDaniel P. Berrange 1275bd269ebcSMarkus Armbruster SocketAddress *socket_remote_address(int fd, Error **errp) 127617c55decSDaniel P. Berrange { 127717c55decSDaniel P. Berrange struct sockaddr_storage ss; 127817c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 127917c55decSDaniel P. Berrange 128017c55decSDaniel P. Berrange if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) { 1281b16a44e1SDaniel P. Berrange error_setg_errno(errp, errno, "%s", 128217c55decSDaniel P. Berrange "Unable to query remote socket address"); 128317c55decSDaniel P. Berrange return NULL; 128417c55decSDaniel P. Berrange } 128517c55decSDaniel P. Berrange 128617c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 128717c55decSDaniel P. Berrange } 12882a8e21c7SDaniel P. Berrange 1289216411b8SMarkus Armbruster 1290bd269ebcSMarkus Armbruster SocketAddress *socket_address_flatten(SocketAddressLegacy *addr_legacy) 1291bd269ebcSMarkus Armbruster { 1292fc0f0059SMarkus Armbruster SocketAddress *addr; 1293bd269ebcSMarkus Armbruster 1294bd269ebcSMarkus Armbruster if (!addr_legacy) { 1295bd269ebcSMarkus Armbruster return NULL; 1296bd269ebcSMarkus Armbruster } 1297bd269ebcSMarkus Armbruster 1298fc0f0059SMarkus Armbruster addr = g_new(SocketAddress, 1); 1299fc0f0059SMarkus Armbruster 1300bd269ebcSMarkus Armbruster switch (addr_legacy->type) { 1301bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_LEGACY_KIND_INET: 1302bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_INET; 1303bd269ebcSMarkus Armbruster QAPI_CLONE_MEMBERS(InetSocketAddress, &addr->u.inet, 1304bd269ebcSMarkus Armbruster addr_legacy->u.inet.data); 1305bd269ebcSMarkus Armbruster break; 1306bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_LEGACY_KIND_UNIX: 1307bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_UNIX; 1308bd269ebcSMarkus Armbruster QAPI_CLONE_MEMBERS(UnixSocketAddress, &addr->u.q_unix, 1309bd269ebcSMarkus Armbruster addr_legacy->u.q_unix.data); 1310bd269ebcSMarkus Armbruster break; 1311bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_LEGACY_KIND_VSOCK: 1312bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_VSOCK; 1313bd269ebcSMarkus Armbruster QAPI_CLONE_MEMBERS(VsockSocketAddress, &addr->u.vsock, 1314bd269ebcSMarkus Armbruster addr_legacy->u.vsock.data); 1315bd269ebcSMarkus Armbruster break; 1316bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_LEGACY_KIND_FD: 1317bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_FD; 1318bd269ebcSMarkus Armbruster QAPI_CLONE_MEMBERS(String, &addr->u.fd, addr_legacy->u.fd.data); 1319bd269ebcSMarkus Armbruster break; 1320bd269ebcSMarkus Armbruster default: 1321bd269ebcSMarkus Armbruster abort(); 1322bd269ebcSMarkus Armbruster } 1323bd269ebcSMarkus Armbruster 1324bd269ebcSMarkus Armbruster return addr; 1325bd269ebcSMarkus Armbruster } 1326