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 24a8d25326SMarkus Armbruster #include "qemu-common.h" 25baacf047SPaolo Bonzini #include "monitor/monitor.h" 26bd269ebcSMarkus Armbruster #include "qapi/clone-visitor.h" 27da34e65cSMarkus Armbruster #include "qapi/error.h" 289af23989SMarkus Armbruster #include "qapi/qapi-visit-sockets.h" 29baacf047SPaolo Bonzini #include "qemu/sockets.h" 30baacf047SPaolo Bonzini #include "qemu/main-loop.h" 31b3db211fSDaniel P. Berrange #include "qapi/qobject-input-visitor.h" 32b3db211fSDaniel P. Berrange #include "qapi/qobject-output-visitor.h" 33f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 34e5b6353cSJuan Quintela #include "trace.h" 35baacf047SPaolo Bonzini 36baacf047SPaolo Bonzini #ifndef AI_ADDRCONFIG 37baacf047SPaolo Bonzini # define AI_ADDRCONFIG 0 38baacf047SPaolo Bonzini #endif 39340849a9SDaniel P. Berrange 403de3d698SWolfgang Bumiller #ifndef AI_V4MAPPED 413de3d698SWolfgang Bumiller # define AI_V4MAPPED 0 423de3d698SWolfgang Bumiller #endif 43baacf047SPaolo Bonzini 446979a813SDaniel P. Berrange #ifndef AI_NUMERICSERV 456979a813SDaniel P. Berrange # define AI_NUMERICSERV 0 466979a813SDaniel P. Berrange #endif 476979a813SDaniel P. Berrange 48baacf047SPaolo Bonzini 49baacf047SPaolo Bonzini static int inet_getport(struct addrinfo *e) 50baacf047SPaolo Bonzini { 51baacf047SPaolo Bonzini struct sockaddr_in *i4; 52baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 53baacf047SPaolo Bonzini 54baacf047SPaolo Bonzini switch (e->ai_family) { 55baacf047SPaolo Bonzini case PF_INET6: 56baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 57baacf047SPaolo Bonzini return ntohs(i6->sin6_port); 58baacf047SPaolo Bonzini case PF_INET: 59baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 60baacf047SPaolo Bonzini return ntohs(i4->sin_port); 61baacf047SPaolo Bonzini default: 62baacf047SPaolo Bonzini return 0; 63baacf047SPaolo Bonzini } 64baacf047SPaolo Bonzini } 65baacf047SPaolo Bonzini 66baacf047SPaolo Bonzini static void inet_setport(struct addrinfo *e, int port) 67baacf047SPaolo Bonzini { 68baacf047SPaolo Bonzini struct sockaddr_in *i4; 69baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 70baacf047SPaolo Bonzini 71baacf047SPaolo Bonzini switch (e->ai_family) { 72baacf047SPaolo Bonzini case PF_INET6: 73baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 74baacf047SPaolo Bonzini i6->sin6_port = htons(port); 75baacf047SPaolo Bonzini break; 76baacf047SPaolo Bonzini case PF_INET: 77baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 78baacf047SPaolo Bonzini i4->sin_port = htons(port); 79baacf047SPaolo Bonzini break; 80baacf047SPaolo Bonzini } 81baacf047SPaolo Bonzini } 82baacf047SPaolo Bonzini 83a589569fSWenchao Xia NetworkAddressFamily inet_netfamily(int family) 84a589569fSWenchao Xia { 85a589569fSWenchao Xia switch (family) { 86a589569fSWenchao Xia case PF_INET6: return NETWORK_ADDRESS_FAMILY_IPV6; 87a589569fSWenchao Xia case PF_INET: return NETWORK_ADDRESS_FAMILY_IPV4; 88a589569fSWenchao Xia case PF_UNIX: return NETWORK_ADDRESS_FAMILY_UNIX; 896a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 906a02c806SStefan Hajnoczi case PF_VSOCK: return NETWORK_ADDRESS_FAMILY_VSOCK; 916a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 92a589569fSWenchao Xia } 93a589569fSWenchao Xia return NETWORK_ADDRESS_FAMILY_UNKNOWN; 94a589569fSWenchao Xia } 95a589569fSWenchao Xia 9658dc31f1SDaniel P. Berrange bool fd_is_socket(int fd) 9758dc31f1SDaniel P. Berrange { 9858dc31f1SDaniel P. Berrange int optval; 9958dc31f1SDaniel P. Berrange socklen_t optlen = sizeof(optval); 10058dc31f1SDaniel P. Berrange return !qemu_getsockopt(fd, SOL_SOCKET, SO_TYPE, &optval, &optlen); 10158dc31f1SDaniel P. Berrange } 10258dc31f1SDaniel P. Berrange 10358dc31f1SDaniel P. Berrange 1041856835dSDaniel P. Berrange /* 1051856835dSDaniel P. Berrange * Matrix we're trying to apply 1061856835dSDaniel P. Berrange * 1071856835dSDaniel P. Berrange * ipv4 ipv6 family 1081856835dSDaniel P. Berrange * - - PF_UNSPEC 1091856835dSDaniel P. Berrange * - f PF_INET 1101856835dSDaniel P. Berrange * - t PF_INET6 1111856835dSDaniel P. Berrange * f - PF_INET6 1121856835dSDaniel P. Berrange * f f <error> 1131856835dSDaniel P. Berrange * f t PF_INET6 1141856835dSDaniel P. Berrange * t - PF_INET 1151856835dSDaniel P. Berrange * t f PF_INET 11694bc0d19SDaniel P. Berrange * t t PF_INET6/PF_UNSPEC 1171856835dSDaniel P. Berrange * 118d43eda3dSWei Jiangang * NB, this matrix is only about getting the necessary results 1191856835dSDaniel P. Berrange * from getaddrinfo(). Some of the cases require further work 1201856835dSDaniel P. Berrange * after reading results from getaddrinfo in order to fully 12194bc0d19SDaniel P. Berrange * apply the logic the end user wants. 12294bc0d19SDaniel P. Berrange * 12394bc0d19SDaniel P. Berrange * In the first and last cases, we must set IPV6_V6ONLY=0 12494bc0d19SDaniel P. Berrange * when binding, to allow a single listener to potentially 12594bc0d19SDaniel P. Berrange * accept both IPv4+6 addresses. 1261856835dSDaniel P. Berrange */ 127c1b412f1SDaniel P. Berrange int inet_ai_family_from_address(InetSocketAddress *addr, 1281856835dSDaniel P. Berrange Error **errp) 1291856835dSDaniel P. Berrange { 1301856835dSDaniel P. Berrange if (addr->has_ipv6 && addr->has_ipv4 && 1311856835dSDaniel P. Berrange !addr->ipv6 && !addr->ipv4) { 1321856835dSDaniel P. Berrange error_setg(errp, "Cannot disable IPv4 and IPv6 at same time"); 1331856835dSDaniel P. Berrange return PF_UNSPEC; 1341856835dSDaniel P. Berrange } 13594bc0d19SDaniel P. Berrange if ((addr->has_ipv6 && addr->ipv6) && (addr->has_ipv4 && addr->ipv4)) { 13694bc0d19SDaniel P. Berrange /* 13794bc0d19SDaniel P. Berrange * Some backends can only do a single listener. In that case 13894bc0d19SDaniel P. Berrange * we want empty hostname to resolve to "::" and then use the 13994bc0d19SDaniel P. Berrange * flag IPV6_V6ONLY==0 to get both protocols on 1 socket. This 14094bc0d19SDaniel P. Berrange * doesn't work for addresses other than "", so they're just 14194bc0d19SDaniel P. Berrange * inevitably broken until multiple listeners can be used, 14294bc0d19SDaniel P. Berrange * and thus we honour getaddrinfo automatic protocol detection 14394bc0d19SDaniel P. Berrange * Once all backends do multi-listener, remove the PF_INET6 14494bc0d19SDaniel P. Berrange * branch entirely. 14594bc0d19SDaniel P. Berrange */ 14694bc0d19SDaniel P. Berrange if (!addr->host || g_str_equal(addr->host, "")) { 14794bc0d19SDaniel P. Berrange return PF_INET6; 14894bc0d19SDaniel P. Berrange } else { 14994bc0d19SDaniel P. Berrange return PF_UNSPEC; 15094bc0d19SDaniel P. Berrange } 15194bc0d19SDaniel P. Berrange } 1521856835dSDaniel P. Berrange if ((addr->has_ipv6 && addr->ipv6) || (addr->has_ipv4 && !addr->ipv4)) { 1531856835dSDaniel P. Berrange return PF_INET6; 1541856835dSDaniel P. Berrange } 1551856835dSDaniel P. Berrange if ((addr->has_ipv4 && addr->ipv4) || (addr->has_ipv6 && !addr->ipv6)) { 1561856835dSDaniel P. Berrange return PF_INET; 1571856835dSDaniel P. Berrange } 1581856835dSDaniel P. Berrange return PF_UNSPEC; 1591856835dSDaniel P. Berrange } 1601856835dSDaniel P. Berrange 16139f80521SKnut Omang static int create_fast_reuse_socket(struct addrinfo *e) 16239f80521SKnut Omang { 16339f80521SKnut Omang int slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); 16439f80521SKnut Omang if (slisten < 0) { 16539f80521SKnut Omang return -1; 16639f80521SKnut Omang } 16739f80521SKnut Omang socket_set_fast_reuse(slisten); 16839f80521SKnut Omang return slisten; 16939f80521SKnut Omang } 17039f80521SKnut Omang 17189382c3dSKnut Omang static int try_bind(int socket, InetSocketAddress *saddr, struct addrinfo *e) 17289382c3dSKnut Omang { 17389382c3dSKnut Omang #ifndef IPV6_V6ONLY 17489382c3dSKnut Omang return bind(socket, e->ai_addr, e->ai_addrlen); 17589382c3dSKnut Omang #else 17689382c3dSKnut Omang /* 17789382c3dSKnut Omang * Deals with first & last cases in matrix in comment 17889382c3dSKnut Omang * for inet_ai_family_from_address(). 17989382c3dSKnut Omang */ 18089382c3dSKnut Omang int v6only = 18189382c3dSKnut Omang ((!saddr->has_ipv4 && !saddr->has_ipv6) || 18289382c3dSKnut Omang (saddr->has_ipv4 && saddr->ipv4 && 18389382c3dSKnut Omang saddr->has_ipv6 && saddr->ipv6)) ? 0 : 1; 18489382c3dSKnut Omang int stat; 18589382c3dSKnut Omang 18689382c3dSKnut Omang rebind: 18789382c3dSKnut Omang if (e->ai_family == PF_INET6) { 18889382c3dSKnut Omang qemu_setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, 18989382c3dSKnut Omang sizeof(v6only)); 19089382c3dSKnut Omang } 19189382c3dSKnut Omang 19289382c3dSKnut Omang stat = bind(socket, e->ai_addr, e->ai_addrlen); 19389382c3dSKnut Omang if (!stat) { 19489382c3dSKnut Omang return 0; 19589382c3dSKnut Omang } 19689382c3dSKnut Omang 19789382c3dSKnut Omang /* If we got EADDRINUSE from an IPv6 bind & v6only is unset, 19889382c3dSKnut Omang * it could be that the IPv4 port is already claimed, so retry 19989382c3dSKnut Omang * with v6only set 20089382c3dSKnut Omang */ 20189382c3dSKnut Omang if (e->ai_family == PF_INET6 && errno == EADDRINUSE && !v6only) { 20289382c3dSKnut Omang v6only = 1; 20389382c3dSKnut Omang goto rebind; 20489382c3dSKnut Omang } 20589382c3dSKnut Omang return stat; 20689382c3dSKnut Omang #endif 20789382c3dSKnut Omang } 20889382c3dSKnut Omang 2091856835dSDaniel P. Berrange static int inet_listen_saddr(InetSocketAddress *saddr, 2101856835dSDaniel P. Berrange int port_offset, 211e5b6353cSJuan Quintela int num, 2121856835dSDaniel P. Berrange Error **errp) 213baacf047SPaolo Bonzini { 214baacf047SPaolo Bonzini struct addrinfo ai,*res,*e; 215baacf047SPaolo Bonzini char port[33]; 216baacf047SPaolo Bonzini char uaddr[INET6_ADDRSTRLEN+1]; 217baacf047SPaolo Bonzini char uport[33]; 2189cf961bbSKnut Omang int rc, port_min, port_max, p; 21910a7b7e6SDaniel P. Berrange int slisten = -1; 2209cf961bbSKnut Omang int saved_errno = 0; 2219cf961bbSKnut Omang bool socket_created = false; 2221856835dSDaniel P. Berrange Error *err = NULL; 223baacf047SPaolo Bonzini 224aec21d31SVladimir Sementsov-Ogievskiy if (saddr->keep_alive) { 225aec21d31SVladimir Sementsov-Ogievskiy error_setg(errp, "keep-alive option is not supported for passive " 226aec21d31SVladimir Sementsov-Ogievskiy "sockets"); 227aec21d31SVladimir Sementsov-Ogievskiy return -1; 228aec21d31SVladimir Sementsov-Ogievskiy } 229aec21d31SVladimir Sementsov-Ogievskiy 230baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 2313de3d698SWolfgang Bumiller ai.ai_flags = AI_PASSIVE; 2326979a813SDaniel P. Berrange if (saddr->has_numeric && saddr->numeric) { 2336979a813SDaniel P. Berrange ai.ai_flags |= AI_NUMERICHOST | AI_NUMERICSERV; 2346979a813SDaniel P. Berrange } 2351856835dSDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(saddr, &err); 236baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 237baacf047SPaolo Bonzini 2381856835dSDaniel P. Berrange if (err) { 2391856835dSDaniel P. Berrange error_propagate(errp, err); 2401856835dSDaniel P. Berrange return -1; 2411856835dSDaniel P. Berrange } 2421856835dSDaniel P. Berrange 2431856835dSDaniel P. Berrange if (saddr->host == NULL) { 2440983f5e6SDaniel P. Berrange error_setg(errp, "host not specified"); 245baacf047SPaolo Bonzini return -1; 246baacf047SPaolo Bonzini } 2471856835dSDaniel P. Berrange if (saddr->port != NULL) { 2481856835dSDaniel P. Berrange pstrcpy(port, sizeof(port), saddr->port); 2490983f5e6SDaniel P. Berrange } else { 2500983f5e6SDaniel P. Berrange port[0] = '\0'; 2510983f5e6SDaniel P. Berrange } 252baacf047SPaolo Bonzini 253baacf047SPaolo Bonzini /* lookup */ 2548bc89127SGerd Hoffmann if (port_offset) { 2558bc89127SGerd Hoffmann unsigned long long baseport; 2560983f5e6SDaniel P. Berrange if (strlen(port) == 0) { 2570983f5e6SDaniel P. Berrange error_setg(errp, "port not specified"); 2580983f5e6SDaniel P. Berrange return -1; 2590983f5e6SDaniel P. Berrange } 2608bc89127SGerd Hoffmann if (parse_uint_full(port, &baseport, 10) < 0) { 2618bc89127SGerd Hoffmann error_setg(errp, "can't convert to a number: %s", port); 2628bc89127SGerd Hoffmann return -1; 2638bc89127SGerd Hoffmann } 2648bc89127SGerd Hoffmann if (baseport > 65535 || 2658bc89127SGerd Hoffmann baseport + port_offset > 65535) { 2668bc89127SGerd Hoffmann error_setg(errp, "port %s out of range", port); 2678bc89127SGerd Hoffmann return -1; 2688bc89127SGerd Hoffmann } 2698bc89127SGerd Hoffmann snprintf(port, sizeof(port), "%d", (int)baseport + port_offset); 2708bc89127SGerd Hoffmann } 2711856835dSDaniel P. Berrange rc = getaddrinfo(strlen(saddr->host) ? saddr->host : NULL, 2720983f5e6SDaniel P. Berrange strlen(port) ? port : NULL, &ai, &res); 273baacf047SPaolo Bonzini if (rc != 0) { 2741856835dSDaniel P. Berrange error_setg(errp, "address resolution failed for %s:%s: %s", 2751856835dSDaniel P. Berrange saddr->host, port, gai_strerror(rc)); 276baacf047SPaolo Bonzini return -1; 277baacf047SPaolo Bonzini } 278baacf047SPaolo Bonzini 2799cf961bbSKnut Omang /* create socket + bind/listen */ 280baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 281*653163fcSMarc-André Lureau #ifdef HAVE_IPPROTO_MPTCP 2828bd1078aSDr. David Alan Gilbert if (saddr->has_mptcp && saddr->mptcp) { 2838bd1078aSDr. David Alan Gilbert e->ai_protocol = IPPROTO_MPTCP; 2848bd1078aSDr. David Alan Gilbert } 2858bd1078aSDr. David Alan Gilbert #endif 286baacf047SPaolo Bonzini getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, 287baacf047SPaolo Bonzini uaddr,INET6_ADDRSTRLEN,uport,32, 288baacf047SPaolo Bonzini NI_NUMERICHOST | NI_NUMERICSERV); 28939f80521SKnut Omang 290baacf047SPaolo Bonzini port_min = inet_getport(e); 2911856835dSDaniel P. Berrange port_max = saddr->has_to ? saddr->to + port_offset : port_min; 292baacf047SPaolo Bonzini for (p = port_min; p <= port_max; p++) { 293baacf047SPaolo Bonzini inet_setport(e, p); 29410a7b7e6SDaniel P. Berrange 29510a7b7e6SDaniel P. Berrange slisten = create_fast_reuse_socket(e); 29610a7b7e6SDaniel P. Berrange if (slisten < 0) { 29710a7b7e6SDaniel P. Berrange /* First time we expect we might fail to create the socket 29810a7b7e6SDaniel P. Berrange * eg if 'e' has AF_INET6 but ipv6 kmod is not loaded. 29910a7b7e6SDaniel P. Berrange * Later iterations should always succeed if first iteration 30010a7b7e6SDaniel P. Berrange * worked though, so treat that as fatal. 30110a7b7e6SDaniel P. Berrange */ 30210a7b7e6SDaniel P. Berrange if (p == port_min) { 3039cf961bbSKnut Omang continue; 3049cf961bbSKnut Omang } else { 30510a7b7e6SDaniel P. Berrange error_setg_errno(errp, errno, 30610a7b7e6SDaniel P. Berrange "Failed to recreate failed listening socket"); 3079cf961bbSKnut Omang goto listen_failed; 3089cf961bbSKnut Omang } 3099cf961bbSKnut Omang } 31010a7b7e6SDaniel P. Berrange socket_created = true; 31110a7b7e6SDaniel P. Berrange 31210a7b7e6SDaniel P. Berrange rc = try_bind(slisten, saddr, e); 31310a7b7e6SDaniel P. Berrange if (rc < 0) { 31410a7b7e6SDaniel P. Berrange if (errno != EADDRINUSE) { 31510a7b7e6SDaniel P. Berrange error_setg_errno(errp, errno, "Failed to bind socket"); 31610a7b7e6SDaniel P. Berrange goto listen_failed; 31710a7b7e6SDaniel P. Berrange } 31810a7b7e6SDaniel P. Berrange } else { 319e5b6353cSJuan Quintela if (!listen(slisten, num)) { 3209cf961bbSKnut Omang goto listen_ok; 3219cf961bbSKnut Omang } 3229cf961bbSKnut Omang if (errno != EADDRINUSE) { 3239cf961bbSKnut Omang error_setg_errno(errp, errno, "Failed to listen on socket"); 3249cf961bbSKnut Omang goto listen_failed; 3259cf961bbSKnut Omang } 32610a7b7e6SDaniel P. Berrange } 3279cf961bbSKnut Omang /* Someone else managed to bind to the same port and beat us 3289cf961bbSKnut Omang * to listen on it! Socket semantics does not allow us to 3299cf961bbSKnut Omang * recover from this situation, so we need to recreate the 3309cf961bbSKnut Omang * socket to allow bind attempts for subsequent ports: 3319cf961bbSKnut Omang */ 3329cf961bbSKnut Omang closesocket(slisten); 33310a7b7e6SDaniel P. Berrange slisten = -1; 334baacf047SPaolo Bonzini } 335baacf047SPaolo Bonzini } 3369cf961bbSKnut Omang error_setg_errno(errp, errno, 3379cf961bbSKnut Omang socket_created ? 3389cf961bbSKnut Omang "Failed to find an available port" : 3399cf961bbSKnut Omang "Failed to create a socket"); 3409cf961bbSKnut Omang listen_failed: 3419cf961bbSKnut Omang saved_errno = errno; 3429cf961bbSKnut Omang if (slisten >= 0) { 343baacf047SPaolo Bonzini closesocket(slisten); 344baacf047SPaolo Bonzini } 345baacf047SPaolo Bonzini freeaddrinfo(res); 3469cf961bbSKnut Omang errno = saved_errno; 347baacf047SPaolo Bonzini return -1; 348baacf047SPaolo Bonzini 3499cf961bbSKnut Omang listen_ok: 350baacf047SPaolo Bonzini freeaddrinfo(res); 351baacf047SPaolo Bonzini return slisten; 352baacf047SPaolo Bonzini } 353baacf047SPaolo Bonzini 354baacf047SPaolo Bonzini #ifdef _WIN32 355baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 356baacf047SPaolo Bonzini ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY) 357baacf047SPaolo Bonzini #else 358baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 359baacf047SPaolo Bonzini ((rc) == -EINPROGRESS) 360baacf047SPaolo Bonzini #endif 361baacf047SPaolo Bonzini 362dfc00eb7SDaniel P. Berrangé static int inet_connect_addr(const InetSocketAddress *saddr, 363dfc00eb7SDaniel P. Berrangé struct addrinfo *addr, Error **errp) 364baacf047SPaolo Bonzini { 365baacf047SPaolo Bonzini int sock, rc; 366baacf047SPaolo Bonzini 367baacf047SPaolo Bonzini sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); 368baacf047SPaolo Bonzini if (sock < 0) { 369dfc00eb7SDaniel P. Berrangé error_setg_errno(errp, errno, "Failed to create socket family %d", 370dfc00eb7SDaniel P. Berrangé addr->ai_family); 371baacf047SPaolo Bonzini return -1; 372baacf047SPaolo Bonzini } 37304fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 374b2587932SCao jin 375baacf047SPaolo Bonzini /* connect to peer */ 376baacf047SPaolo Bonzini do { 377baacf047SPaolo Bonzini rc = 0; 378baacf047SPaolo Bonzini if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) { 379b16a44e1SDaniel P. Berrange rc = -errno; 380baacf047SPaolo Bonzini } 381baacf047SPaolo Bonzini } while (rc == -EINTR); 382baacf047SPaolo Bonzini 383b2587932SCao jin if (rc < 0) { 384dfc00eb7SDaniel P. Berrangé error_setg_errno(errp, errno, "Failed to connect to '%s:%s'", 385dfc00eb7SDaniel P. Berrangé saddr->host, saddr->port); 386baacf047SPaolo Bonzini closesocket(sock); 387baacf047SPaolo Bonzini return -1; 388baacf047SPaolo Bonzini } 389b2587932SCao jin 390baacf047SPaolo Bonzini return sock; 391baacf047SPaolo Bonzini } 392baacf047SPaolo Bonzini 3932942e420SDaniel P. Berrange static struct addrinfo *inet_parse_connect_saddr(InetSocketAddress *saddr, 3942942e420SDaniel P. Berrange Error **errp) 395baacf047SPaolo Bonzini { 396baacf047SPaolo Bonzini struct addrinfo ai, *res; 397baacf047SPaolo Bonzini int rc; 3982942e420SDaniel P. Berrange Error *err = NULL; 399340849a9SDaniel P. Berrange static int useV4Mapped = 1; 400baacf047SPaolo Bonzini 401baacf047SPaolo Bonzini memset(&ai, 0, sizeof(ai)); 402baacf047SPaolo Bonzini 403340849a9SDaniel P. Berrange ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; 404d73415a3SStefan Hajnoczi if (qatomic_read(&useV4Mapped)) { 405340849a9SDaniel P. Berrange ai.ai_flags |= AI_V4MAPPED; 406340849a9SDaniel P. Berrange } 4072942e420SDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(saddr, &err); 408baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 409baacf047SPaolo Bonzini 4102942e420SDaniel P. Berrange if (err) { 4112942e420SDaniel P. Berrange error_propagate(errp, err); 4122942e420SDaniel P. Berrange return NULL; 4132942e420SDaniel P. Berrange } 4142942e420SDaniel P. Berrange 4152942e420SDaniel P. Berrange if (saddr->host == NULL || saddr->port == NULL) { 416baacf047SPaolo Bonzini error_setg(errp, "host and/or port not specified"); 417baacf047SPaolo Bonzini return NULL; 418baacf047SPaolo Bonzini } 419baacf047SPaolo Bonzini 420baacf047SPaolo Bonzini /* lookup */ 4212942e420SDaniel P. Berrange rc = getaddrinfo(saddr->host, saddr->port, &ai, &res); 422340849a9SDaniel P. Berrange 423340849a9SDaniel P. Berrange /* At least FreeBSD and OS-X 10.6 declare AI_V4MAPPED but 424340849a9SDaniel P. Berrange * then don't implement it in their getaddrinfo(). Detect 4258cc360b9Szhaolichang * this and retry without the flag since that's preferable 426340849a9SDaniel P. Berrange * to a fatal error 427340849a9SDaniel P. Berrange */ 428340849a9SDaniel P. Berrange if (rc == EAI_BADFLAGS && 429340849a9SDaniel P. Berrange (ai.ai_flags & AI_V4MAPPED)) { 430d73415a3SStefan Hajnoczi qatomic_set(&useV4Mapped, 0); 431340849a9SDaniel P. Berrange ai.ai_flags &= ~AI_V4MAPPED; 432340849a9SDaniel P. Berrange rc = getaddrinfo(saddr->host, saddr->port, &ai, &res); 433340849a9SDaniel P. Berrange } 434baacf047SPaolo Bonzini if (rc != 0) { 4352942e420SDaniel P. Berrange error_setg(errp, "address resolution failed for %s:%s: %s", 4362942e420SDaniel P. Berrange saddr->host, saddr->port, gai_strerror(rc)); 437baacf047SPaolo Bonzini return NULL; 438baacf047SPaolo Bonzini } 439baacf047SPaolo Bonzini return res; 440baacf047SPaolo Bonzini } 441baacf047SPaolo Bonzini 442baacf047SPaolo Bonzini /** 443baacf047SPaolo Bonzini * Create a socket and connect it to an address. 444baacf047SPaolo Bonzini * 4452942e420SDaniel P. Berrange * @saddr: Inet socket address specification 446baacf047SPaolo Bonzini * @errp: set on error 447baacf047SPaolo Bonzini * 448baacf047SPaolo Bonzini * Returns: -1 on error, file descriptor on success. 449baacf047SPaolo Bonzini */ 450b2587932SCao jin int inet_connect_saddr(InetSocketAddress *saddr, Error **errp) 451baacf047SPaolo Bonzini { 4523f9286b7SMarkus Armbruster Error *local_err = NULL; 453baacf047SPaolo Bonzini struct addrinfo *res, *e; 454baacf047SPaolo Bonzini int sock = -1; 455baacf047SPaolo Bonzini 4562942e420SDaniel P. Berrange res = inet_parse_connect_saddr(saddr, errp); 457baacf047SPaolo Bonzini if (!res) { 458baacf047SPaolo Bonzini return -1; 459baacf047SPaolo Bonzini } 460baacf047SPaolo Bonzini 461baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 4623f9286b7SMarkus Armbruster error_free(local_err); 4633f9286b7SMarkus Armbruster local_err = NULL; 4648bd1078aSDr. David Alan Gilbert 465*653163fcSMarc-André Lureau #ifdef HAVE_IPPROTO_MPTCP 4668bd1078aSDr. David Alan Gilbert if (saddr->has_mptcp && saddr->mptcp) { 4678bd1078aSDr. David Alan Gilbert e->ai_protocol = IPPROTO_MPTCP; 4688bd1078aSDr. David Alan Gilbert } 4698bd1078aSDr. David Alan Gilbert #endif 4708bd1078aSDr. David Alan Gilbert 471dfc00eb7SDaniel P. Berrangé sock = inet_connect_addr(saddr, e, &local_err); 4723f9286b7SMarkus Armbruster if (sock >= 0) { 473baacf047SPaolo Bonzini break; 474baacf047SPaolo Bonzini } 475baacf047SPaolo Bonzini } 4763f9286b7SMarkus Armbruster 477da5e1169SVladimir Sementsov-Ogievskiy freeaddrinfo(res); 478da5e1169SVladimir Sementsov-Ogievskiy 4793f9286b7SMarkus Armbruster if (sock < 0) { 4803f9286b7SMarkus Armbruster error_propagate(errp, local_err); 481da5e1169SVladimir Sementsov-Ogievskiy return sock; 4823f9286b7SMarkus Armbruster } 483b2587932SCao jin 484aec21d31SVladimir Sementsov-Ogievskiy if (saddr->keep_alive) { 485aec21d31SVladimir Sementsov-Ogievskiy int val = 1; 486aec21d31SVladimir Sementsov-Ogievskiy int ret = qemu_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, 487aec21d31SVladimir Sementsov-Ogievskiy &val, sizeof(val)); 488aec21d31SVladimir Sementsov-Ogievskiy 489aec21d31SVladimir Sementsov-Ogievskiy if (ret < 0) { 490aec21d31SVladimir Sementsov-Ogievskiy error_setg_errno(errp, errno, "Unable to set KEEPALIVE"); 491aec21d31SVladimir Sementsov-Ogievskiy close(sock); 492aec21d31SVladimir Sementsov-Ogievskiy return -1; 493aec21d31SVladimir Sementsov-Ogievskiy } 494aec21d31SVladimir Sementsov-Ogievskiy } 495aec21d31SVladimir Sementsov-Ogievskiy 496baacf047SPaolo Bonzini return sock; 497baacf047SPaolo Bonzini } 498baacf047SPaolo Bonzini 4998b39910eSDaniel P. Berrange static int inet_dgram_saddr(InetSocketAddress *sraddr, 5008b39910eSDaniel P. Berrange InetSocketAddress *sladdr, 5018b39910eSDaniel P. Berrange Error **errp) 502baacf047SPaolo Bonzini { 503baacf047SPaolo Bonzini struct addrinfo ai, *peer = NULL, *local = NULL; 504baacf047SPaolo Bonzini const char *addr; 505baacf047SPaolo Bonzini const char *port; 506baacf047SPaolo Bonzini int sock = -1, rc; 5078b39910eSDaniel P. Berrange Error *err = NULL; 508baacf047SPaolo Bonzini 509baacf047SPaolo Bonzini /* lookup peer addr */ 510baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 5113de3d698SWolfgang Bumiller ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG; 5128b39910eSDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(sraddr, &err); 513baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 514baacf047SPaolo Bonzini 5158b39910eSDaniel P. Berrange if (err) { 5168b39910eSDaniel P. Berrange error_propagate(errp, err); 51758c652c0SPaolo Bonzini goto err; 5188b39910eSDaniel P. Berrange } 5198b39910eSDaniel P. Berrange 5208b39910eSDaniel P. Berrange addr = sraddr->host; 5218b39910eSDaniel P. Berrange port = sraddr->port; 522baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 523baacf047SPaolo Bonzini addr = "localhost"; 524baacf047SPaolo Bonzini } 525baacf047SPaolo Bonzini if (port == NULL || strlen(port) == 0) { 526baacf047SPaolo Bonzini error_setg(errp, "remote port not specified"); 52758c652c0SPaolo Bonzini goto err; 528baacf047SPaolo Bonzini } 529baacf047SPaolo Bonzini 5309cd1883cSCao jin if ((rc = getaddrinfo(addr, port, &ai, &peer)) != 0) { 531baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 532baacf047SPaolo Bonzini gai_strerror(rc)); 53358c652c0SPaolo Bonzini goto err; 534baacf047SPaolo Bonzini } 535baacf047SPaolo Bonzini 536baacf047SPaolo Bonzini /* lookup local addr */ 537baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 538baacf047SPaolo Bonzini ai.ai_flags = AI_PASSIVE; 539baacf047SPaolo Bonzini ai.ai_family = peer->ai_family; 540baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 541baacf047SPaolo Bonzini 5428b39910eSDaniel P. Berrange if (sladdr) { 5438b39910eSDaniel P. Berrange addr = sladdr->host; 5448b39910eSDaniel P. Berrange port = sladdr->port; 545baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 546baacf047SPaolo Bonzini addr = NULL; 547baacf047SPaolo Bonzini } 5488b39910eSDaniel P. Berrange if (!port || strlen(port) == 0) { 549baacf047SPaolo Bonzini port = "0"; 5508b39910eSDaniel P. Berrange } 5518b39910eSDaniel P. Berrange } else { 5528b39910eSDaniel P. Berrange addr = NULL; 5538b39910eSDaniel P. Berrange port = "0"; 5548b39910eSDaniel P. Berrange } 555baacf047SPaolo Bonzini 5569cd1883cSCao jin if ((rc = getaddrinfo(addr, port, &ai, &local)) != 0) { 557baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 558baacf047SPaolo Bonzini gai_strerror(rc)); 559baacf047SPaolo Bonzini goto err; 560baacf047SPaolo Bonzini } 561baacf047SPaolo Bonzini 562baacf047SPaolo Bonzini /* create socket */ 563baacf047SPaolo Bonzini sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); 564baacf047SPaolo Bonzini if (sock < 0) { 565dfc00eb7SDaniel P. Berrangé error_setg_errno(errp, errno, "Failed to create socket family %d", 566dfc00eb7SDaniel P. Berrangé peer->ai_family); 567baacf047SPaolo Bonzini goto err; 568baacf047SPaolo Bonzini } 56904fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 570baacf047SPaolo Bonzini 571baacf047SPaolo Bonzini /* bind socket */ 572baacf047SPaolo Bonzini if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { 573235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to bind socket"); 574baacf047SPaolo Bonzini goto err; 575baacf047SPaolo Bonzini } 576baacf047SPaolo Bonzini 577baacf047SPaolo Bonzini /* connect to peer */ 578baacf047SPaolo Bonzini if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { 579dfc00eb7SDaniel P. Berrangé error_setg_errno(errp, errno, "Failed to connect to '%s:%s'", 580dfc00eb7SDaniel P. Berrangé addr, port); 581baacf047SPaolo Bonzini goto err; 582baacf047SPaolo Bonzini } 583baacf047SPaolo Bonzini 584baacf047SPaolo Bonzini freeaddrinfo(local); 585baacf047SPaolo Bonzini freeaddrinfo(peer); 586baacf047SPaolo Bonzini return sock; 587baacf047SPaolo Bonzini 588baacf047SPaolo Bonzini err: 58926015051SCao jin if (sock != -1) { 590baacf047SPaolo Bonzini closesocket(sock); 59126015051SCao jin } 59226015051SCao jin if (local) { 593baacf047SPaolo Bonzini freeaddrinfo(local); 59426015051SCao jin } 59526015051SCao jin if (peer) { 596baacf047SPaolo Bonzini freeaddrinfo(peer); 59726015051SCao jin } 59826015051SCao jin 599baacf047SPaolo Bonzini return -1; 600baacf047SPaolo Bonzini } 601baacf047SPaolo Bonzini 602baacf047SPaolo Bonzini /* compatibility wrapper */ 6033e32370aSDaniel P. Berrange static int inet_parse_flag(const char *flagname, const char *optstr, bool *val, 6043e32370aSDaniel P. Berrange Error **errp) 6053e32370aSDaniel P. Berrange { 6063e32370aSDaniel P. Berrange char *end; 6073e32370aSDaniel P. Berrange size_t len; 6083e32370aSDaniel P. Berrange 6093e32370aSDaniel P. Berrange end = strstr(optstr, ","); 6103e32370aSDaniel P. Berrange if (end) { 6113e32370aSDaniel P. Berrange if (end[1] == ',') { /* Reject 'ipv6=on,,foo' */ 6123e32370aSDaniel P. Berrange error_setg(errp, "error parsing '%s' flag '%s'", flagname, optstr); 6133e32370aSDaniel P. Berrange return -1; 6143e32370aSDaniel P. Berrange } 6153e32370aSDaniel P. Berrange len = end - optstr; 6163e32370aSDaniel P. Berrange } else { 6173e32370aSDaniel P. Berrange len = strlen(optstr); 6183e32370aSDaniel P. Berrange } 6193e32370aSDaniel P. Berrange if (len == 0 || (len == 3 && strncmp(optstr, "=on", len) == 0)) { 6203e32370aSDaniel P. Berrange *val = true; 6213e32370aSDaniel P. Berrange } else if (len == 4 && strncmp(optstr, "=off", len) == 0) { 6223e32370aSDaniel P. Berrange *val = false; 6233e32370aSDaniel P. Berrange } else { 6243e32370aSDaniel P. Berrange error_setg(errp, "error parsing '%s' flag '%s'", flagname, optstr); 6253e32370aSDaniel P. Berrange return -1; 6263e32370aSDaniel P. Berrange } 6273e32370aSDaniel P. Berrange return 0; 6283e32370aSDaniel P. Berrange } 6293e32370aSDaniel P. Berrange 6300785bd7aSMarkus Armbruster int inet_parse(InetSocketAddress *addr, const char *str, Error **errp) 631baacf047SPaolo Bonzini { 632baacf047SPaolo Bonzini const char *optstr, *h; 63355a10996SKevin Wolf char host[65]; 634baacf047SPaolo Bonzini char port[33]; 635baacf047SPaolo Bonzini int to; 636baacf047SPaolo Bonzini int pos; 6373e32370aSDaniel P. Berrange char *begin; 638baacf047SPaolo Bonzini 6390785bd7aSMarkus Armbruster memset(addr, 0, sizeof(*addr)); 640baacf047SPaolo Bonzini 641baacf047SPaolo Bonzini /* parse address */ 642baacf047SPaolo Bonzini if (str[0] == ':') { 643baacf047SPaolo Bonzini /* no host given */ 644baacf047SPaolo Bonzini host[0] = '\0'; 6459cd1883cSCao jin if (sscanf(str, ":%32[^,]%n", port, &pos) != 1) { 646baacf047SPaolo Bonzini error_setg(errp, "error parsing port in address '%s'", str); 6470785bd7aSMarkus Armbruster return -1; 648baacf047SPaolo Bonzini } 649baacf047SPaolo Bonzini } else if (str[0] == '[') { 650baacf047SPaolo Bonzini /* IPv6 addr */ 6519cd1883cSCao jin if (sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos) != 2) { 652baacf047SPaolo Bonzini error_setg(errp, "error parsing IPv6 address '%s'", str); 6530785bd7aSMarkus Armbruster return -1; 654baacf047SPaolo Bonzini } 655baacf047SPaolo Bonzini } else { 656391b7b97SJán Tomko /* hostname or IPv4 addr */ 6579cd1883cSCao jin if (sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos) != 2) { 658baacf047SPaolo Bonzini error_setg(errp, "error parsing address '%s'", str); 6590785bd7aSMarkus Armbruster return -1; 660baacf047SPaolo Bonzini } 661baacf047SPaolo Bonzini } 662baacf047SPaolo Bonzini 663baacf047SPaolo Bonzini addr->host = g_strdup(host); 664baacf047SPaolo Bonzini addr->port = g_strdup(port); 665baacf047SPaolo Bonzini 666baacf047SPaolo Bonzini /* parse options */ 667baacf047SPaolo Bonzini optstr = str + pos; 668baacf047SPaolo Bonzini h = strstr(optstr, ",to="); 669baacf047SPaolo Bonzini if (h) { 670baacf047SPaolo Bonzini h += 4; 671baacf047SPaolo Bonzini if (sscanf(h, "%d%n", &to, &pos) != 1 || 672baacf047SPaolo Bonzini (h[pos] != '\0' && h[pos] != ',')) { 673baacf047SPaolo Bonzini error_setg(errp, "error parsing to= argument"); 6740785bd7aSMarkus Armbruster return -1; 675baacf047SPaolo Bonzini } 676baacf047SPaolo Bonzini addr->has_to = true; 677baacf047SPaolo Bonzini addr->to = to; 678baacf047SPaolo Bonzini } 6793e32370aSDaniel P. Berrange begin = strstr(optstr, ",ipv4"); 6803e32370aSDaniel P. Berrange if (begin) { 6813e32370aSDaniel P. Berrange if (inet_parse_flag("ipv4", begin + 5, &addr->ipv4, errp) < 0) { 6823e32370aSDaniel P. Berrange return -1; 683baacf047SPaolo Bonzini } 6843e32370aSDaniel P. Berrange addr->has_ipv4 = true; 6853e32370aSDaniel P. Berrange } 6863e32370aSDaniel P. Berrange begin = strstr(optstr, ",ipv6"); 6873e32370aSDaniel P. Berrange if (begin) { 6883e32370aSDaniel P. Berrange if (inet_parse_flag("ipv6", begin + 5, &addr->ipv6, errp) < 0) { 6893e32370aSDaniel P. Berrange return -1; 6903e32370aSDaniel P. Berrange } 6913e32370aSDaniel P. Berrange addr->has_ipv6 = true; 692baacf047SPaolo Bonzini } 693aec21d31SVladimir Sementsov-Ogievskiy begin = strstr(optstr, ",keep-alive"); 694aec21d31SVladimir Sementsov-Ogievskiy if (begin) { 695aec21d31SVladimir Sementsov-Ogievskiy if (inet_parse_flag("keep-alive", begin + strlen(",keep-alive"), 696aec21d31SVladimir Sementsov-Ogievskiy &addr->keep_alive, errp) < 0) 697aec21d31SVladimir Sementsov-Ogievskiy { 698aec21d31SVladimir Sementsov-Ogievskiy return -1; 699aec21d31SVladimir Sementsov-Ogievskiy } 700aec21d31SVladimir Sementsov-Ogievskiy addr->has_keep_alive = true; 701aec21d31SVladimir Sementsov-Ogievskiy } 702*653163fcSMarc-André Lureau #ifdef HAVE_IPPROTO_MPTCP 7038bd1078aSDr. David Alan Gilbert begin = strstr(optstr, ",mptcp"); 7048bd1078aSDr. David Alan Gilbert if (begin) { 7058bd1078aSDr. David Alan Gilbert if (inet_parse_flag("mptcp", begin + strlen(",mptcp"), 7068bd1078aSDr. David Alan Gilbert &addr->mptcp, errp) < 0) 7078bd1078aSDr. David Alan Gilbert { 7088bd1078aSDr. David Alan Gilbert return -1; 7098bd1078aSDr. David Alan Gilbert } 7108bd1078aSDr. David Alan Gilbert addr->has_mptcp = true; 7118bd1078aSDr. David Alan Gilbert } 7128bd1078aSDr. David Alan Gilbert #endif 7130785bd7aSMarkus Armbruster return 0; 714baacf047SPaolo Bonzini } 715baacf047SPaolo Bonzini 716baacf047SPaolo Bonzini 717baacf047SPaolo Bonzini /** 718baacf047SPaolo Bonzini * Create a blocking socket and connect it to an address. 719baacf047SPaolo Bonzini * 720baacf047SPaolo Bonzini * @str: address string 721baacf047SPaolo Bonzini * @errp: set in case of an error 722baacf047SPaolo Bonzini * 723baacf047SPaolo Bonzini * Returns -1 in case of error, file descriptor on success 724baacf047SPaolo Bonzini **/ 725baacf047SPaolo Bonzini int inet_connect(const char *str, Error **errp) 726baacf047SPaolo Bonzini { 727baacf047SPaolo Bonzini int sock = -1; 7280785bd7aSMarkus Armbruster InetSocketAddress *addr = g_new(InetSocketAddress, 1); 729baacf047SPaolo Bonzini 7300785bd7aSMarkus Armbruster if (!inet_parse(addr, str, errp)) { 731b2587932SCao jin sock = inet_connect_saddr(addr, errp); 732baacf047SPaolo Bonzini } 7330785bd7aSMarkus Armbruster qapi_free_InetSocketAddress(addr); 734baacf047SPaolo Bonzini return sock; 735baacf047SPaolo Bonzini } 736baacf047SPaolo Bonzini 7376a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 7386a02c806SStefan Hajnoczi static bool vsock_parse_vaddr_to_sockaddr(const VsockSocketAddress *vaddr, 7396a02c806SStefan Hajnoczi struct sockaddr_vm *svm, 7406a02c806SStefan Hajnoczi Error **errp) 7416a02c806SStefan Hajnoczi { 7426a02c806SStefan Hajnoczi unsigned long long val; 7436a02c806SStefan Hajnoczi 7446a02c806SStefan Hajnoczi memset(svm, 0, sizeof(*svm)); 7456a02c806SStefan Hajnoczi svm->svm_family = AF_VSOCK; 7466a02c806SStefan Hajnoczi 7476a02c806SStefan Hajnoczi if (parse_uint_full(vaddr->cid, &val, 10) < 0 || 7486a02c806SStefan Hajnoczi val > UINT32_MAX) { 7496a02c806SStefan Hajnoczi error_setg(errp, "Failed to parse cid '%s'", vaddr->cid); 7506a02c806SStefan Hajnoczi return false; 7516a02c806SStefan Hajnoczi } 7526a02c806SStefan Hajnoczi svm->svm_cid = val; 7536a02c806SStefan Hajnoczi 7546a02c806SStefan Hajnoczi if (parse_uint_full(vaddr->port, &val, 10) < 0 || 7556a02c806SStefan Hajnoczi val > UINT32_MAX) { 7566a02c806SStefan Hajnoczi error_setg(errp, "Failed to parse port '%s'", vaddr->port); 7576a02c806SStefan Hajnoczi return false; 7586a02c806SStefan Hajnoczi } 7596a02c806SStefan Hajnoczi svm->svm_port = val; 7606a02c806SStefan Hajnoczi 7616a02c806SStefan Hajnoczi return true; 7626a02c806SStefan Hajnoczi } 7636a02c806SStefan Hajnoczi 764dfc00eb7SDaniel P. Berrangé static int vsock_connect_addr(const VsockSocketAddress *vaddr, 765dfc00eb7SDaniel P. Berrangé const struct sockaddr_vm *svm, Error **errp) 7666a02c806SStefan Hajnoczi { 7676a02c806SStefan Hajnoczi int sock, rc; 7686a02c806SStefan Hajnoczi 7696a02c806SStefan Hajnoczi sock = qemu_socket(AF_VSOCK, SOCK_STREAM, 0); 7706a02c806SStefan Hajnoczi if (sock < 0) { 771dfc00eb7SDaniel P. Berrangé error_setg_errno(errp, errno, "Failed to create socket family %d", 772dfc00eb7SDaniel P. Berrangé AF_VSOCK); 7736a02c806SStefan Hajnoczi return -1; 7746a02c806SStefan Hajnoczi } 775b2587932SCao jin 7766a02c806SStefan Hajnoczi /* connect to peer */ 7776a02c806SStefan Hajnoczi do { 7786a02c806SStefan Hajnoczi rc = 0; 7796a02c806SStefan Hajnoczi if (connect(sock, (const struct sockaddr *)svm, sizeof(*svm)) < 0) { 7806a02c806SStefan Hajnoczi rc = -errno; 7816a02c806SStefan Hajnoczi } 7826a02c806SStefan Hajnoczi } while (rc == -EINTR); 7836a02c806SStefan Hajnoczi 784b2587932SCao jin if (rc < 0) { 785dfc00eb7SDaniel P. Berrangé error_setg_errno(errp, errno, "Failed to connect to '%s:%s'", 786dfc00eb7SDaniel P. Berrangé vaddr->cid, vaddr->port); 7876a02c806SStefan Hajnoczi closesocket(sock); 7886a02c806SStefan Hajnoczi return -1; 7896a02c806SStefan Hajnoczi } 790b2587932SCao jin 7916a02c806SStefan Hajnoczi return sock; 7926a02c806SStefan Hajnoczi } 7936a02c806SStefan Hajnoczi 794b2587932SCao jin static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp) 7956a02c806SStefan Hajnoczi { 7966a02c806SStefan Hajnoczi struct sockaddr_vm svm; 7976a02c806SStefan Hajnoczi 7986a02c806SStefan Hajnoczi if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) { 7996a02c806SStefan Hajnoczi return -1; 8006a02c806SStefan Hajnoczi } 8016a02c806SStefan Hajnoczi 802dfc00eb7SDaniel P. Berrangé return vsock_connect_addr(vaddr, &svm, errp); 8036a02c806SStefan Hajnoczi } 8046a02c806SStefan Hajnoczi 8056a02c806SStefan Hajnoczi static int vsock_listen_saddr(VsockSocketAddress *vaddr, 806e5b6353cSJuan Quintela int num, 8076a02c806SStefan Hajnoczi Error **errp) 8086a02c806SStefan Hajnoczi { 8096a02c806SStefan Hajnoczi struct sockaddr_vm svm; 8106a02c806SStefan Hajnoczi int slisten; 8116a02c806SStefan Hajnoczi 8126a02c806SStefan Hajnoczi if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) { 8136a02c806SStefan Hajnoczi return -1; 8146a02c806SStefan Hajnoczi } 8156a02c806SStefan Hajnoczi 8166a02c806SStefan Hajnoczi slisten = qemu_socket(AF_VSOCK, SOCK_STREAM, 0); 8176a02c806SStefan Hajnoczi if (slisten < 0) { 8186a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to create socket"); 8196a02c806SStefan Hajnoczi return -1; 8206a02c806SStefan Hajnoczi } 8216a02c806SStefan Hajnoczi 8226a02c806SStefan Hajnoczi if (bind(slisten, (const struct sockaddr *)&svm, sizeof(svm)) != 0) { 8236a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to bind socket"); 8246a02c806SStefan Hajnoczi closesocket(slisten); 8256a02c806SStefan Hajnoczi return -1; 8266a02c806SStefan Hajnoczi } 8276a02c806SStefan Hajnoczi 828e5b6353cSJuan Quintela if (listen(slisten, num) != 0) { 8296a02c806SStefan Hajnoczi error_setg_errno(errp, errno, "Failed to listen on socket"); 8306a02c806SStefan Hajnoczi closesocket(slisten); 8316a02c806SStefan Hajnoczi return -1; 8326a02c806SStefan Hajnoczi } 8336a02c806SStefan Hajnoczi return slisten; 8346a02c806SStefan Hajnoczi } 8356a02c806SStefan Hajnoczi 8364db5c619SMarkus Armbruster static int vsock_parse(VsockSocketAddress *addr, const char *str, 8374db5c619SMarkus Armbruster Error **errp) 8386a02c806SStefan Hajnoczi { 8396a02c806SStefan Hajnoczi char cid[33]; 8406a02c806SStefan Hajnoczi char port[33]; 8416a02c806SStefan Hajnoczi int n; 8426a02c806SStefan Hajnoczi 8436a02c806SStefan Hajnoczi if (sscanf(str, "%32[^:]:%32[^,]%n", cid, port, &n) != 2) { 8446a02c806SStefan Hajnoczi error_setg(errp, "error parsing address '%s'", str); 8454db5c619SMarkus Armbruster return -1; 8466a02c806SStefan Hajnoczi } 8476a02c806SStefan Hajnoczi if (str[n] != '\0') { 8486a02c806SStefan Hajnoczi error_setg(errp, "trailing characters in address '%s'", str); 8494db5c619SMarkus Armbruster return -1; 8506a02c806SStefan Hajnoczi } 8516a02c806SStefan Hajnoczi 8526a02c806SStefan Hajnoczi addr->cid = g_strdup(cid); 8536a02c806SStefan Hajnoczi addr->port = g_strdup(port); 8544db5c619SMarkus Armbruster return 0; 8556a02c806SStefan Hajnoczi } 8566a02c806SStefan Hajnoczi #else 8576a02c806SStefan Hajnoczi static void vsock_unsupported(Error **errp) 8586a02c806SStefan Hajnoczi { 8596a02c806SStefan Hajnoczi error_setg(errp, "socket family AF_VSOCK unsupported"); 8606a02c806SStefan Hajnoczi } 8616a02c806SStefan Hajnoczi 862b2587932SCao jin static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp) 8636a02c806SStefan Hajnoczi { 8646a02c806SStefan Hajnoczi vsock_unsupported(errp); 8656a02c806SStefan Hajnoczi return -1; 8666a02c806SStefan Hajnoczi } 8676a02c806SStefan Hajnoczi 8686a02c806SStefan Hajnoczi static int vsock_listen_saddr(VsockSocketAddress *vaddr, 869e5b6353cSJuan Quintela int num, 8706a02c806SStefan Hajnoczi Error **errp) 8716a02c806SStefan Hajnoczi { 8726a02c806SStefan Hajnoczi vsock_unsupported(errp); 8736a02c806SStefan Hajnoczi return -1; 8746a02c806SStefan Hajnoczi } 8756a02c806SStefan Hajnoczi 8764db5c619SMarkus Armbruster static int vsock_parse(VsockSocketAddress *addr, const char *str, 8774db5c619SMarkus Armbruster Error **errp) 8786a02c806SStefan Hajnoczi { 8796a02c806SStefan Hajnoczi vsock_unsupported(errp); 8804db5c619SMarkus Armbruster return -1; 8816a02c806SStefan Hajnoczi } 8826a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 8836a02c806SStefan Hajnoczi 884baacf047SPaolo Bonzini #ifndef _WIN32 885baacf047SPaolo Bonzini 8868acefc79SMarkus Armbruster static bool saddr_is_abstract(UnixSocketAddress *saddr) 8878acefc79SMarkus Armbruster { 8888acefc79SMarkus Armbruster #ifdef CONFIG_LINUX 8898acefc79SMarkus Armbruster return saddr->abstract; 8908acefc79SMarkus Armbruster #else 8918acefc79SMarkus Armbruster return false; 8928acefc79SMarkus Armbruster #endif 8938acefc79SMarkus Armbruster } 8948acefc79SMarkus Armbruster 8958acefc79SMarkus Armbruster static bool saddr_is_tight(UnixSocketAddress *saddr) 8968acefc79SMarkus Armbruster { 8978acefc79SMarkus Armbruster #ifdef CONFIG_LINUX 8988acefc79SMarkus Armbruster return !saddr->has_tight || saddr->tight; 8998acefc79SMarkus Armbruster #else 9008acefc79SMarkus Armbruster return false; 9018acefc79SMarkus Armbruster #endif 9028acefc79SMarkus Armbruster } 9038acefc79SMarkus Armbruster 9041856835dSDaniel P. Berrange static int unix_listen_saddr(UnixSocketAddress *saddr, 905e5b6353cSJuan Quintela int num, 9061856835dSDaniel P. Berrange Error **errp) 907baacf047SPaolo Bonzini { 9088acefc79SMarkus Armbruster bool abstract = saddr_is_abstract(saddr); 909baacf047SPaolo Bonzini struct sockaddr_un un; 910baacf047SPaolo Bonzini int sock, fd; 911ad9579aaSDaniel P. Berrange char *pathbuf = NULL; 912ad9579aaSDaniel P. Berrange const char *path; 9132d2023c3SDaniel P. Berrangé size_t pathlen; 914776b97d3Sxiaoqiang zhao size_t addrlen; 915baacf047SPaolo Bonzini 916baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 917baacf047SPaolo Bonzini if (sock < 0) { 918b658c53dSPaolo Bonzini error_setg_errno(errp, errno, "Failed to create Unix socket"); 919baacf047SPaolo Bonzini return -1; 920baacf047SPaolo Bonzini } 921baacf047SPaolo Bonzini 9228acefc79SMarkus Armbruster if (saddr->path[0] || abstract) { 923ad9579aaSDaniel P. Berrange path = saddr->path; 924baacf047SPaolo Bonzini } else { 925b658c53dSPaolo Bonzini const char *tmpdir = getenv("TMPDIR"); 926b658c53dSPaolo Bonzini tmpdir = tmpdir ? tmpdir : "/tmp"; 927ad9579aaSDaniel P. Berrange path = pathbuf = g_strdup_printf("%s/qemu-socket-XXXXXX", tmpdir); 928ad9579aaSDaniel P. Berrange } 929ad9579aaSDaniel P. Berrange 9302d2023c3SDaniel P. Berrangé pathlen = strlen(path); 931776b97d3Sxiaoqiang zhao if (pathlen > sizeof(un.sun_path) || 9328acefc79SMarkus Armbruster (abstract && pathlen > (sizeof(un.sun_path) - 1))) { 933ad9579aaSDaniel P. Berrange error_setg(errp, "UNIX socket path '%s' is too long", path); 934ad9579aaSDaniel P. Berrange error_append_hint(errp, "Path must be less than %zu bytes\n", 9358acefc79SMarkus Armbruster abstract ? sizeof(un.sun_path) - 1 : 936ad9579aaSDaniel P. Berrange sizeof(un.sun_path)); 937b658c53dSPaolo Bonzini goto err; 938b658c53dSPaolo Bonzini } 939b658c53dSPaolo Bonzini 940ad9579aaSDaniel P. Berrange if (pathbuf != NULL) { 941baacf047SPaolo Bonzini /* 942baacf047SPaolo Bonzini * This dummy fd usage silences the mktemp() unsecure warning. 943baacf047SPaolo Bonzini * Using mkstemp() doesn't make things more secure here 944baacf047SPaolo Bonzini * though. bind() complains about existing files, so we have 945baacf047SPaolo Bonzini * to unlink first and thus re-open the race window. The 946baacf047SPaolo Bonzini * worst case possible is bind() failing, i.e. a DoS attack. 947baacf047SPaolo Bonzini */ 948ad9579aaSDaniel P. Berrange fd = mkstemp(pathbuf); 949b658c53dSPaolo Bonzini if (fd < 0) { 950b658c53dSPaolo Bonzini error_setg_errno(errp, errno, 951ad9579aaSDaniel P. Berrange "Failed to make a temporary socket %s", pathbuf); 952b658c53dSPaolo Bonzini goto err; 953b658c53dSPaolo Bonzini } 954b658c53dSPaolo Bonzini close(fd); 955baacf047SPaolo Bonzini } 956baacf047SPaolo Bonzini 9578acefc79SMarkus Armbruster if (!abstract && unlink(path) < 0 && errno != ENOENT) { 9580ef705a2SCole Robinson error_setg_errno(errp, errno, 959ad9579aaSDaniel P. Berrange "Failed to unlink socket %s", path); 9600ef705a2SCole Robinson goto err; 9610ef705a2SCole Robinson } 962ad9579aaSDaniel P. Berrange 963ad9579aaSDaniel P. Berrange memset(&un, 0, sizeof(un)); 964ad9579aaSDaniel P. Berrange un.sun_family = AF_UNIX; 965776b97d3Sxiaoqiang zhao addrlen = sizeof(un); 966ad9579aaSDaniel P. Berrange 9678acefc79SMarkus Armbruster if (abstract) { 968776b97d3Sxiaoqiang zhao un.sun_path[0] = '\0'; 969776b97d3Sxiaoqiang zhao memcpy(&un.sun_path[1], path, pathlen); 9708acefc79SMarkus Armbruster if (saddr_is_tight(saddr)) { 971776b97d3Sxiaoqiang zhao addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + pathlen; 972776b97d3Sxiaoqiang zhao } 973776b97d3Sxiaoqiang zhao } else { 974776b97d3Sxiaoqiang zhao memcpy(un.sun_path, path, pathlen); 975776b97d3Sxiaoqiang zhao } 976776b97d3Sxiaoqiang zhao 977776b97d3Sxiaoqiang zhao if (bind(sock, (struct sockaddr *) &un, addrlen) < 0) { 97856382bd5SDaniel P. Berrange error_setg_errno(errp, errno, "Failed to bind socket to %s", path); 979baacf047SPaolo Bonzini goto err; 980baacf047SPaolo Bonzini } 981e5b6353cSJuan Quintela if (listen(sock, num) < 0) { 982235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to listen on socket"); 983baacf047SPaolo Bonzini goto err; 984baacf047SPaolo Bonzini } 985baacf047SPaolo Bonzini 986ad9579aaSDaniel P. Berrange g_free(pathbuf); 987baacf047SPaolo Bonzini return sock; 988baacf047SPaolo Bonzini 989baacf047SPaolo Bonzini err: 990ad9579aaSDaniel P. Berrange g_free(pathbuf); 991baacf047SPaolo Bonzini closesocket(sock); 992baacf047SPaolo Bonzini return -1; 993baacf047SPaolo Bonzini } 994baacf047SPaolo Bonzini 995b2587932SCao jin static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) 996baacf047SPaolo Bonzini { 9978acefc79SMarkus Armbruster bool abstract = saddr_is_abstract(saddr); 998baacf047SPaolo Bonzini struct sockaddr_un un; 999baacf047SPaolo Bonzini int sock, rc; 10002d2023c3SDaniel P. Berrangé size_t pathlen; 1001776b97d3Sxiaoqiang zhao size_t addrlen; 1002baacf047SPaolo Bonzini 10032942e420SDaniel P. Berrange if (saddr->path == NULL) { 1004312fd5f2SMarkus Armbruster error_setg(errp, "unix connect: no path specified"); 1005baacf047SPaolo Bonzini return -1; 1006baacf047SPaolo Bonzini } 1007baacf047SPaolo Bonzini 1008baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 1009baacf047SPaolo Bonzini if (sock < 0) { 1010235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 1011baacf047SPaolo Bonzini return -1; 1012baacf047SPaolo Bonzini } 1013baacf047SPaolo Bonzini 10142d2023c3SDaniel P. Berrangé pathlen = strlen(saddr->path); 1015776b97d3Sxiaoqiang zhao if (pathlen > sizeof(un.sun_path) || 10168acefc79SMarkus Armbruster (abstract && pathlen > (sizeof(un.sun_path) - 1))) { 1017ad9579aaSDaniel P. Berrange error_setg(errp, "UNIX socket path '%s' is too long", saddr->path); 1018ad9579aaSDaniel P. Berrange error_append_hint(errp, "Path must be less than %zu bytes\n", 10198acefc79SMarkus Armbruster abstract ? sizeof(un.sun_path) - 1 : 1020ad9579aaSDaniel P. Berrange sizeof(un.sun_path)); 1021ad9579aaSDaniel P. Berrange goto err; 1022ad9579aaSDaniel P. Berrange } 1023ad9579aaSDaniel P. Berrange 1024baacf047SPaolo Bonzini memset(&un, 0, sizeof(un)); 1025baacf047SPaolo Bonzini un.sun_family = AF_UNIX; 1026776b97d3Sxiaoqiang zhao addrlen = sizeof(un); 1027baacf047SPaolo Bonzini 10288acefc79SMarkus Armbruster if (abstract) { 1029776b97d3Sxiaoqiang zhao un.sun_path[0] = '\0'; 1030776b97d3Sxiaoqiang zhao memcpy(&un.sun_path[1], saddr->path, pathlen); 10318acefc79SMarkus Armbruster if (saddr_is_tight(saddr)) { 1032776b97d3Sxiaoqiang zhao addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + pathlen; 1033776b97d3Sxiaoqiang zhao } 1034776b97d3Sxiaoqiang zhao } else { 1035776b97d3Sxiaoqiang zhao memcpy(un.sun_path, saddr->path, pathlen); 1036776b97d3Sxiaoqiang zhao } 1037baacf047SPaolo Bonzini /* connect to peer */ 1038baacf047SPaolo Bonzini do { 1039baacf047SPaolo Bonzini rc = 0; 1040776b97d3Sxiaoqiang zhao if (connect(sock, (struct sockaddr *) &un, addrlen) < 0) { 1041b16a44e1SDaniel P. Berrange rc = -errno; 1042baacf047SPaolo Bonzini } 1043baacf047SPaolo Bonzini } while (rc == -EINTR); 1044baacf047SPaolo Bonzini 1045baacf047SPaolo Bonzini if (rc < 0) { 1046dfc00eb7SDaniel P. Berrangé error_setg_errno(errp, -rc, "Failed to connect to '%s'", 1047ad9579aaSDaniel P. Berrange saddr->path); 1048ad9579aaSDaniel P. Berrange goto err; 1049baacf047SPaolo Bonzini } 1050baacf047SPaolo Bonzini 1051baacf047SPaolo Bonzini return sock; 1052ad9579aaSDaniel P. Berrange 1053ad9579aaSDaniel P. Berrange err: 1054ad9579aaSDaniel P. Berrange close(sock); 1055ad9579aaSDaniel P. Berrange return -1; 1056baacf047SPaolo Bonzini } 1057baacf047SPaolo Bonzini 1058baacf047SPaolo Bonzini #else 1059baacf047SPaolo Bonzini 10601856835dSDaniel P. Berrange static int unix_listen_saddr(UnixSocketAddress *saddr, 1061e5b6353cSJuan Quintela int num, 10621856835dSDaniel P. Berrange Error **errp) 1063baacf047SPaolo Bonzini { 1064baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 1065baacf047SPaolo Bonzini errno = ENOTSUP; 1066baacf047SPaolo Bonzini return -1; 1067baacf047SPaolo Bonzini } 1068baacf047SPaolo Bonzini 1069b2587932SCao jin static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) 1070baacf047SPaolo Bonzini { 1071baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 1072baacf047SPaolo Bonzini errno = ENOTSUP; 1073baacf047SPaolo Bonzini return -1; 1074baacf047SPaolo Bonzini } 1075baacf047SPaolo Bonzini #endif 1076baacf047SPaolo Bonzini 1077baacf047SPaolo Bonzini /* compatibility wrapper */ 107862473511SDaniel P. Berrange int unix_listen(const char *str, Error **errp) 1079baacf047SPaolo Bonzini { 10801856835dSDaniel P. Berrange UnixSocketAddress *saddr; 1081caf88d74SMarc-André Lureau int sock; 1082baacf047SPaolo Bonzini 10831856835dSDaniel P. Berrange saddr = g_new0(UnixSocketAddress, 1); 10841856835dSDaniel P. Berrange saddr->path = g_strdup(str); 1085e5b6353cSJuan Quintela sock = unix_listen_saddr(saddr, 1, errp); 10861856835dSDaniel P. Berrange qapi_free_UnixSocketAddress(saddr); 1087baacf047SPaolo Bonzini return sock; 1088baacf047SPaolo Bonzini } 1089baacf047SPaolo Bonzini 1090baacf047SPaolo Bonzini int unix_connect(const char *path, Error **errp) 1091baacf047SPaolo Bonzini { 10922942e420SDaniel P. Berrange UnixSocketAddress *saddr; 1093baacf047SPaolo Bonzini int sock; 1094baacf047SPaolo Bonzini 10952942e420SDaniel P. Berrange saddr = g_new0(UnixSocketAddress, 1); 10962942e420SDaniel P. Berrange saddr->path = g_strdup(path); 1097b2587932SCao jin sock = unix_connect_saddr(saddr, errp); 10982942e420SDaniel P. Berrange qapi_free_UnixSocketAddress(saddr); 1099baacf047SPaolo Bonzini return sock; 1100baacf047SPaolo Bonzini } 1101baacf047SPaolo Bonzini 1102baacf047SPaolo Bonzini 1103bd269ebcSMarkus Armbruster SocketAddress *socket_parse(const char *str, Error **errp) 1104baacf047SPaolo Bonzini { 1105bd269ebcSMarkus Armbruster SocketAddress *addr; 1106baacf047SPaolo Bonzini 1107bd269ebcSMarkus Armbruster addr = g_new0(SocketAddress, 1); 1108baacf047SPaolo Bonzini if (strstart(str, "unix:", NULL)) { 1109baacf047SPaolo Bonzini if (str[5] == '\0') { 1110312fd5f2SMarkus Armbruster error_setg(errp, "invalid Unix socket address"); 1111baacf047SPaolo Bonzini goto fail; 1112baacf047SPaolo Bonzini } else { 1113bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_UNIX; 1114bd269ebcSMarkus Armbruster addr->u.q_unix.path = g_strdup(str + 5); 1115baacf047SPaolo Bonzini } 1116baacf047SPaolo Bonzini } else if (strstart(str, "fd:", NULL)) { 1117baacf047SPaolo Bonzini if (str[3] == '\0') { 1118312fd5f2SMarkus Armbruster error_setg(errp, "invalid file descriptor address"); 1119baacf047SPaolo Bonzini goto fail; 1120baacf047SPaolo Bonzini } else { 1121bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_FD; 1122bd269ebcSMarkus Armbruster addr->u.fd.str = g_strdup(str + 3); 1123baacf047SPaolo Bonzini } 11246a02c806SStefan Hajnoczi } else if (strstart(str, "vsock:", NULL)) { 1125bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_VSOCK; 1126bd269ebcSMarkus Armbruster if (vsock_parse(&addr->u.vsock, str + strlen("vsock:"), errp)) { 11276a02c806SStefan Hajnoczi goto fail; 11286a02c806SStefan Hajnoczi } 1129baacf047SPaolo Bonzini } else { 1130bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_INET; 1131bd269ebcSMarkus Armbruster if (inet_parse(&addr->u.inet, str, errp)) { 1132baacf047SPaolo Bonzini goto fail; 1133baacf047SPaolo Bonzini } 1134baacf047SPaolo Bonzini } 1135baacf047SPaolo Bonzini return addr; 1136baacf047SPaolo Bonzini 1137baacf047SPaolo Bonzini fail: 1138bd269ebcSMarkus Armbruster qapi_free_SocketAddress(addr); 1139baacf047SPaolo Bonzini return NULL; 1140baacf047SPaolo Bonzini } 1141baacf047SPaolo Bonzini 114237179e9eSStefan Hajnoczi static int socket_get_fd(const char *fdstr, Error **errp) 114330bdb3c5SDaniel P. Berrange { 1144947e4744SKevin Wolf Monitor *cur_mon = monitor_cur(); 11451723d6b1SDaniel P. Berrange int fd; 11461723d6b1SDaniel P. Berrange if (cur_mon) { 11471723d6b1SDaniel P. Berrange fd = monitor_get_fd(cur_mon, fdstr, errp); 114830bdb3c5SDaniel P. Berrange if (fd < 0) { 114930bdb3c5SDaniel P. Berrange return -1; 115030bdb3c5SDaniel P. Berrange } 11511723d6b1SDaniel P. Berrange } else { 11521723d6b1SDaniel P. Berrange if (qemu_strtoi(fdstr, NULL, 10, &fd) < 0) { 11531723d6b1SDaniel P. Berrange error_setg_errno(errp, errno, 11541723d6b1SDaniel P. Berrange "Unable to parse FD number %s", 11551723d6b1SDaniel P. Berrange fdstr); 11561723d6b1SDaniel P. Berrange return -1; 11571723d6b1SDaniel P. Berrange } 11581723d6b1SDaniel P. Berrange } 115930bdb3c5SDaniel P. Berrange if (!fd_is_socket(fd)) { 116030bdb3c5SDaniel P. Berrange error_setg(errp, "File descriptor '%s' is not a socket", fdstr); 116130bdb3c5SDaniel P. Berrange close(fd); 116230bdb3c5SDaniel P. Berrange return -1; 116330bdb3c5SDaniel P. Berrange } 116430bdb3c5SDaniel P. Berrange return fd; 116530bdb3c5SDaniel P. Berrange } 116630bdb3c5SDaniel P. Berrange 1167c5423704SVladimir Sementsov-Ogievskiy int socket_address_parse_named_fd(SocketAddress *addr, Error **errp) 1168c5423704SVladimir Sementsov-Ogievskiy { 1169c5423704SVladimir Sementsov-Ogievskiy int fd; 1170c5423704SVladimir Sementsov-Ogievskiy 1171c5423704SVladimir Sementsov-Ogievskiy if (addr->type != SOCKET_ADDRESS_TYPE_FD) { 1172c5423704SVladimir Sementsov-Ogievskiy return 0; 1173c5423704SVladimir Sementsov-Ogievskiy } 1174c5423704SVladimir Sementsov-Ogievskiy 1175c5423704SVladimir Sementsov-Ogievskiy fd = socket_get_fd(addr->u.fd.str, errp); 1176c5423704SVladimir Sementsov-Ogievskiy if (fd < 0) { 1177c5423704SVladimir Sementsov-Ogievskiy return fd; 1178c5423704SVladimir Sementsov-Ogievskiy } 1179c5423704SVladimir Sementsov-Ogievskiy 1180c5423704SVladimir Sementsov-Ogievskiy g_free(addr->u.fd.str); 1181c5423704SVladimir Sementsov-Ogievskiy addr->u.fd.str = g_strdup_printf("%d", fd); 1182c5423704SVladimir Sementsov-Ogievskiy 1183c5423704SVladimir Sementsov-Ogievskiy return 0; 1184c5423704SVladimir Sementsov-Ogievskiy } 1185c5423704SVladimir Sementsov-Ogievskiy 1186b2587932SCao jin int socket_connect(SocketAddress *addr, Error **errp) 1187baacf047SPaolo Bonzini { 1188baacf047SPaolo Bonzini int fd; 1189baacf047SPaolo Bonzini 11902d32addaSEric Blake switch (addr->type) { 1191bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_INET: 1192b2587932SCao jin fd = inet_connect_saddr(&addr->u.inet, errp); 1193baacf047SPaolo Bonzini break; 1194baacf047SPaolo Bonzini 1195bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_UNIX: 1196b2587932SCao jin fd = unix_connect_saddr(&addr->u.q_unix, errp); 1197baacf047SPaolo Bonzini break; 1198baacf047SPaolo Bonzini 1199bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_FD: 120037179e9eSStefan Hajnoczi fd = socket_get_fd(addr->u.fd.str, errp); 1201baacf047SPaolo Bonzini break; 1202baacf047SPaolo Bonzini 1203bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_VSOCK: 1204b2587932SCao jin fd = vsock_connect_saddr(&addr->u.vsock, errp); 12056a02c806SStefan Hajnoczi break; 12066a02c806SStefan Hajnoczi 1207baacf047SPaolo Bonzini default: 1208baacf047SPaolo Bonzini abort(); 1209baacf047SPaolo Bonzini } 1210baacf047SPaolo Bonzini return fd; 1211baacf047SPaolo Bonzini } 1212baacf047SPaolo Bonzini 1213e5b6353cSJuan Quintela int socket_listen(SocketAddress *addr, int num, Error **errp) 1214baacf047SPaolo Bonzini { 1215baacf047SPaolo Bonzini int fd; 1216baacf047SPaolo Bonzini 1217e5b6353cSJuan Quintela trace_socket_listen(num); 12182d32addaSEric Blake switch (addr->type) { 1219bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_INET: 1220e5b6353cSJuan Quintela fd = inet_listen_saddr(&addr->u.inet, 0, num, errp); 1221baacf047SPaolo Bonzini break; 1222baacf047SPaolo Bonzini 1223bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_UNIX: 1224e5b6353cSJuan Quintela fd = unix_listen_saddr(&addr->u.q_unix, num, errp); 1225baacf047SPaolo Bonzini break; 1226baacf047SPaolo Bonzini 1227bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_FD: 122837179e9eSStefan Hajnoczi fd = socket_get_fd(addr->u.fd.str, errp); 122937179e9eSStefan Hajnoczi if (fd < 0) { 123037179e9eSStefan Hajnoczi return -1; 123137179e9eSStefan Hajnoczi } 123237179e9eSStefan Hajnoczi 123337179e9eSStefan Hajnoczi /* 123437179e9eSStefan Hajnoczi * If the socket is not yet in the listen state, then transition it to 123537179e9eSStefan Hajnoczi * the listen state now. 123637179e9eSStefan Hajnoczi * 123737179e9eSStefan Hajnoczi * If it's already listening then this updates the backlog value as 123837179e9eSStefan Hajnoczi * requested. 123937179e9eSStefan Hajnoczi * 124037179e9eSStefan Hajnoczi * If this socket cannot listen because it's already in another state 124137179e9eSStefan Hajnoczi * (e.g. unbound or connected) then we'll catch the error here. 124237179e9eSStefan Hajnoczi */ 124337179e9eSStefan Hajnoczi if (listen(fd, num) != 0) { 124437179e9eSStefan Hajnoczi error_setg_errno(errp, errno, "Failed to listen on fd socket"); 124537179e9eSStefan Hajnoczi closesocket(fd); 124637179e9eSStefan Hajnoczi return -1; 124737179e9eSStefan Hajnoczi } 1248baacf047SPaolo Bonzini break; 1249baacf047SPaolo Bonzini 1250bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_VSOCK: 1251e5b6353cSJuan Quintela fd = vsock_listen_saddr(&addr->u.vsock, num, errp); 12526a02c806SStefan Hajnoczi break; 12536a02c806SStefan Hajnoczi 1254baacf047SPaolo Bonzini default: 1255baacf047SPaolo Bonzini abort(); 1256baacf047SPaolo Bonzini } 1257baacf047SPaolo Bonzini return fd; 1258baacf047SPaolo Bonzini } 1259baacf047SPaolo Bonzini 126074b6ce43SMarc-André Lureau void socket_listen_cleanup(int fd, Error **errp) 126174b6ce43SMarc-André Lureau { 1262bd269ebcSMarkus Armbruster SocketAddress *addr; 126374b6ce43SMarc-André Lureau 126474b6ce43SMarc-André Lureau addr = socket_local_address(fd, errp); 12652d7ad7c0SDaniel P. Berrange if (!addr) { 12662d7ad7c0SDaniel P. Berrange return; 12672d7ad7c0SDaniel P. Berrange } 126874b6ce43SMarc-André Lureau 1269bd269ebcSMarkus Armbruster if (addr->type == SOCKET_ADDRESS_TYPE_UNIX 1270bd269ebcSMarkus Armbruster && addr->u.q_unix.path) { 1271bd269ebcSMarkus Armbruster if (unlink(addr->u.q_unix.path) < 0 && errno != ENOENT) { 127274b6ce43SMarc-André Lureau error_setg_errno(errp, errno, 127374b6ce43SMarc-André Lureau "Failed to unlink socket %s", 1274bd269ebcSMarkus Armbruster addr->u.q_unix.path); 127574b6ce43SMarc-André Lureau } 127674b6ce43SMarc-André Lureau } 127774b6ce43SMarc-André Lureau 1278bd269ebcSMarkus Armbruster qapi_free_SocketAddress(addr); 127974b6ce43SMarc-André Lureau } 128074b6ce43SMarc-André Lureau 1281bd269ebcSMarkus Armbruster int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp) 12823ecc059dSGerd Hoffmann { 12833ecc059dSGerd Hoffmann int fd; 12843ecc059dSGerd Hoffmann 1285ca0b64e5SMarkus Armbruster /* 1286bd269ebcSMarkus Armbruster * TODO SOCKET_ADDRESS_TYPE_FD when fd is AF_INET or AF_INET6 1287ca0b64e5SMarkus Armbruster * (although other address families can do SOCK_DGRAM, too) 1288ca0b64e5SMarkus Armbruster */ 12892d32addaSEric Blake switch (remote->type) { 1290bd269ebcSMarkus Armbruster case SOCKET_ADDRESS_TYPE_INET: 1291bd269ebcSMarkus Armbruster fd = inet_dgram_saddr(&remote->u.inet, 1292bd269ebcSMarkus Armbruster local ? &local->u.inet : NULL, errp); 12933ecc059dSGerd Hoffmann break; 12943ecc059dSGerd Hoffmann 12953ecc059dSGerd Hoffmann default: 12963ecc059dSGerd Hoffmann error_setg(errp, "socket type unsupported for datagram"); 12977a5b6af1SGerd Hoffmann fd = -1; 12983ecc059dSGerd Hoffmann } 12993ecc059dSGerd Hoffmann return fd; 13003ecc059dSGerd Hoffmann } 130117c55decSDaniel P. Berrange 130217c55decSDaniel P. Berrange 1303bd269ebcSMarkus Armbruster static SocketAddress * 130417c55decSDaniel P. Berrange socket_sockaddr_to_address_inet(struct sockaddr_storage *sa, 130517c55decSDaniel P. Berrange socklen_t salen, 130617c55decSDaniel P. Berrange Error **errp) 130717c55decSDaniel P. Berrange { 130817c55decSDaniel P. Berrange char host[NI_MAXHOST]; 130917c55decSDaniel P. Berrange char serv[NI_MAXSERV]; 1310bd269ebcSMarkus Armbruster SocketAddress *addr; 13110399293eSEric Blake InetSocketAddress *inet; 131217c55decSDaniel P. Berrange int ret; 131317c55decSDaniel P. Berrange 131417c55decSDaniel P. Berrange ret = getnameinfo((struct sockaddr *)sa, salen, 131517c55decSDaniel P. Berrange host, sizeof(host), 131617c55decSDaniel P. Berrange serv, sizeof(serv), 131717c55decSDaniel P. Berrange NI_NUMERICHOST | NI_NUMERICSERV); 131817c55decSDaniel P. Berrange if (ret != 0) { 131917c55decSDaniel P. Berrange error_setg(errp, "Cannot format numeric socket address: %s", 132017c55decSDaniel P. Berrange gai_strerror(ret)); 132117c55decSDaniel P. Berrange return NULL; 132217c55decSDaniel P. Berrange } 132317c55decSDaniel P. Berrange 1324bd269ebcSMarkus Armbruster addr = g_new0(SocketAddress, 1); 1325bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_INET; 1326bd269ebcSMarkus Armbruster inet = &addr->u.inet; 13270399293eSEric Blake inet->host = g_strdup(host); 13280399293eSEric Blake inet->port = g_strdup(serv); 132917c55decSDaniel P. Berrange if (sa->ss_family == AF_INET) { 13300399293eSEric Blake inet->has_ipv4 = inet->ipv4 = true; 133117c55decSDaniel P. Berrange } else { 13320399293eSEric Blake inet->has_ipv6 = inet->ipv6 = true; 133317c55decSDaniel P. Berrange } 133417c55decSDaniel P. Berrange 133517c55decSDaniel P. Berrange return addr; 133617c55decSDaniel P. Berrange } 133717c55decSDaniel P. Berrange 133817c55decSDaniel P. Berrange 133917c55decSDaniel P. Berrange #ifndef WIN32 1340bd269ebcSMarkus Armbruster static SocketAddress * 134117c55decSDaniel P. Berrange socket_sockaddr_to_address_unix(struct sockaddr_storage *sa, 134217c55decSDaniel P. Berrange socklen_t salen, 134317c55decSDaniel P. Berrange Error **errp) 134417c55decSDaniel P. Berrange { 1345bd269ebcSMarkus Armbruster SocketAddress *addr; 134617c55decSDaniel P. Berrange struct sockaddr_un *su = (struct sockaddr_un *)sa; 134717c55decSDaniel P. Berrange 1348bd269ebcSMarkus Armbruster addr = g_new0(SocketAddress, 1); 1349bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_UNIX; 1350118d527fSMichael Tokarev salen -= offsetof(struct sockaddr_un, sun_path); 13513b14b4ecSMarkus Armbruster #ifdef CONFIG_LINUX 1352118d527fSMichael Tokarev if (salen > 0 && !su->sun_path[0]) { 13533b14b4ecSMarkus Armbruster /* Linux abstract socket */ 1354118d527fSMichael Tokarev addr->u.q_unix.path = g_strndup(su->sun_path + 1, salen - 1); 13553b14b4ecSMarkus Armbruster addr->u.q_unix.has_abstract = true; 13563b14b4ecSMarkus Armbruster addr->u.q_unix.abstract = true; 13573b14b4ecSMarkus Armbruster addr->u.q_unix.has_tight = true; 1358118d527fSMichael Tokarev addr->u.q_unix.tight = salen < sizeof(su->sun_path); 13593b14b4ecSMarkus Armbruster return addr; 136017c55decSDaniel P. Berrange } 13613b14b4ecSMarkus Armbruster #endif 136217c55decSDaniel P. Berrange 1363118d527fSMichael Tokarev addr->u.q_unix.path = g_strndup(su->sun_path, salen); 136417c55decSDaniel P. Berrange return addr; 136517c55decSDaniel P. Berrange } 136617c55decSDaniel P. Berrange #endif /* WIN32 */ 136717c55decSDaniel P. Berrange 13686a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 1369bd269ebcSMarkus Armbruster static SocketAddress * 13706a02c806SStefan Hajnoczi socket_sockaddr_to_address_vsock(struct sockaddr_storage *sa, 13716a02c806SStefan Hajnoczi socklen_t salen, 13726a02c806SStefan Hajnoczi Error **errp) 13736a02c806SStefan Hajnoczi { 1374bd269ebcSMarkus Armbruster SocketAddress *addr; 13756a02c806SStefan Hajnoczi VsockSocketAddress *vaddr; 13766a02c806SStefan Hajnoczi struct sockaddr_vm *svm = (struct sockaddr_vm *)sa; 13776a02c806SStefan Hajnoczi 1378bd269ebcSMarkus Armbruster addr = g_new0(SocketAddress, 1); 1379bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_VSOCK; 1380bd269ebcSMarkus Armbruster vaddr = &addr->u.vsock; 13816a02c806SStefan Hajnoczi vaddr->cid = g_strdup_printf("%u", svm->svm_cid); 13826a02c806SStefan Hajnoczi vaddr->port = g_strdup_printf("%u", svm->svm_port); 13836a02c806SStefan Hajnoczi 13846a02c806SStefan Hajnoczi return addr; 13856a02c806SStefan Hajnoczi } 13866a02c806SStefan Hajnoczi #endif /* CONFIG_AF_VSOCK */ 13876a02c806SStefan Hajnoczi 1388bd269ebcSMarkus Armbruster SocketAddress * 138917c55decSDaniel P. Berrange socket_sockaddr_to_address(struct sockaddr_storage *sa, 139017c55decSDaniel P. Berrange socklen_t salen, 139117c55decSDaniel P. Berrange Error **errp) 139217c55decSDaniel P. Berrange { 139317c55decSDaniel P. Berrange switch (sa->ss_family) { 139417c55decSDaniel P. Berrange case AF_INET: 139517c55decSDaniel P. Berrange case AF_INET6: 139617c55decSDaniel P. Berrange return socket_sockaddr_to_address_inet(sa, salen, errp); 139717c55decSDaniel P. Berrange 139817c55decSDaniel P. Berrange #ifndef WIN32 139917c55decSDaniel P. Berrange case AF_UNIX: 140017c55decSDaniel P. Berrange return socket_sockaddr_to_address_unix(sa, salen, errp); 140117c55decSDaniel P. Berrange #endif /* WIN32 */ 140217c55decSDaniel P. Berrange 14036a02c806SStefan Hajnoczi #ifdef CONFIG_AF_VSOCK 14046a02c806SStefan Hajnoczi case AF_VSOCK: 14056a02c806SStefan Hajnoczi return socket_sockaddr_to_address_vsock(sa, salen, errp); 14066a02c806SStefan Hajnoczi #endif 14076a02c806SStefan Hajnoczi 140817c55decSDaniel P. Berrange default: 140917c55decSDaniel P. Berrange error_setg(errp, "socket family %d unsupported", 141017c55decSDaniel P. Berrange sa->ss_family); 141117c55decSDaniel P. Berrange return NULL; 141217c55decSDaniel P. Berrange } 141317c55decSDaniel P. Berrange return 0; 141417c55decSDaniel P. Berrange } 141517c55decSDaniel P. Berrange 141617c55decSDaniel P. Berrange 1417bd269ebcSMarkus Armbruster SocketAddress *socket_local_address(int fd, Error **errp) 141817c55decSDaniel P. Berrange { 141917c55decSDaniel P. Berrange struct sockaddr_storage ss; 142017c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 142117c55decSDaniel P. Berrange 142217c55decSDaniel P. Berrange if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) { 1423b16a44e1SDaniel P. Berrange error_setg_errno(errp, errno, "%s", 142417c55decSDaniel P. Berrange "Unable to query local socket address"); 142517c55decSDaniel P. Berrange return NULL; 142617c55decSDaniel P. Berrange } 142717c55decSDaniel P. Berrange 142817c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 142917c55decSDaniel P. Berrange } 143017c55decSDaniel P. Berrange 143117c55decSDaniel P. Berrange 1432bd269ebcSMarkus Armbruster SocketAddress *socket_remote_address(int fd, Error **errp) 143317c55decSDaniel P. Berrange { 143417c55decSDaniel P. Berrange struct sockaddr_storage ss; 143517c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 143617c55decSDaniel P. Berrange 143717c55decSDaniel P. Berrange if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) { 1438b16a44e1SDaniel P. Berrange error_setg_errno(errp, errno, "%s", 143917c55decSDaniel P. Berrange "Unable to query remote socket address"); 144017c55decSDaniel P. Berrange return NULL; 144117c55decSDaniel P. Berrange } 144217c55decSDaniel P. Berrange 144317c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 144417c55decSDaniel P. Berrange } 14452a8e21c7SDaniel P. Berrange 1446216411b8SMarkus Armbruster 1447bd269ebcSMarkus Armbruster SocketAddress *socket_address_flatten(SocketAddressLegacy *addr_legacy) 1448bd269ebcSMarkus Armbruster { 1449fc0f0059SMarkus Armbruster SocketAddress *addr; 1450bd269ebcSMarkus Armbruster 1451bd269ebcSMarkus Armbruster if (!addr_legacy) { 1452bd269ebcSMarkus Armbruster return NULL; 1453bd269ebcSMarkus Armbruster } 1454bd269ebcSMarkus Armbruster 1455fc0f0059SMarkus Armbruster addr = g_new(SocketAddress, 1); 1456fc0f0059SMarkus Armbruster 1457bd269ebcSMarkus Armbruster switch (addr_legacy->type) { 1458935a867cSMarkus Armbruster case SOCKET_ADDRESS_TYPE_INET: 1459bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_INET; 1460bd269ebcSMarkus Armbruster QAPI_CLONE_MEMBERS(InetSocketAddress, &addr->u.inet, 1461bd269ebcSMarkus Armbruster addr_legacy->u.inet.data); 1462bd269ebcSMarkus Armbruster break; 1463935a867cSMarkus Armbruster case SOCKET_ADDRESS_TYPE_UNIX: 1464bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_UNIX; 1465bd269ebcSMarkus Armbruster QAPI_CLONE_MEMBERS(UnixSocketAddress, &addr->u.q_unix, 1466bd269ebcSMarkus Armbruster addr_legacy->u.q_unix.data); 1467bd269ebcSMarkus Armbruster break; 1468935a867cSMarkus Armbruster case SOCKET_ADDRESS_TYPE_VSOCK: 1469bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_VSOCK; 1470bd269ebcSMarkus Armbruster QAPI_CLONE_MEMBERS(VsockSocketAddress, &addr->u.vsock, 1471bd269ebcSMarkus Armbruster addr_legacy->u.vsock.data); 1472bd269ebcSMarkus Armbruster break; 1473935a867cSMarkus Armbruster case SOCKET_ADDRESS_TYPE_FD: 1474bd269ebcSMarkus Armbruster addr->type = SOCKET_ADDRESS_TYPE_FD; 1475bd269ebcSMarkus Armbruster QAPI_CLONE_MEMBERS(String, &addr->u.fd, addr_legacy->u.fd.data); 1476bd269ebcSMarkus Armbruster break; 1477bd269ebcSMarkus Armbruster default: 1478bd269ebcSMarkus Armbruster abort(); 1479bd269ebcSMarkus Armbruster } 1480bd269ebcSMarkus Armbruster 1481bd269ebcSMarkus Armbruster return addr; 1482bd269ebcSMarkus Armbruster } 1483