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 20baacf047SPaolo Bonzini #include "monitor/monitor.h" 21*da34e65cSMarkus Armbruster #include "qapi/error.h" 22baacf047SPaolo Bonzini #include "qemu/sockets.h" 23baacf047SPaolo Bonzini #include "qemu/main-loop.h" 242a8e21c7SDaniel P. Berrange #include "qapi/qmp-input-visitor.h" 252a8e21c7SDaniel P. Berrange #include "qapi/qmp-output-visitor.h" 262a8e21c7SDaniel P. Berrange #include "qapi-visit.h" 27baacf047SPaolo Bonzini 28baacf047SPaolo Bonzini #ifndef AI_ADDRCONFIG 29baacf047SPaolo Bonzini # define AI_ADDRCONFIG 0 30baacf047SPaolo Bonzini #endif 313de3d698SWolfgang Bumiller #ifndef AI_V4MAPPED 323de3d698SWolfgang Bumiller # define AI_V4MAPPED 0 333de3d698SWolfgang Bumiller #endif 34baacf047SPaolo Bonzini 35baacf047SPaolo Bonzini 36baacf047SPaolo Bonzini static int inet_getport(struct addrinfo *e) 37baacf047SPaolo Bonzini { 38baacf047SPaolo Bonzini struct sockaddr_in *i4; 39baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 40baacf047SPaolo Bonzini 41baacf047SPaolo Bonzini switch (e->ai_family) { 42baacf047SPaolo Bonzini case PF_INET6: 43baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 44baacf047SPaolo Bonzini return ntohs(i6->sin6_port); 45baacf047SPaolo Bonzini case PF_INET: 46baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 47baacf047SPaolo Bonzini return ntohs(i4->sin_port); 48baacf047SPaolo Bonzini default: 49baacf047SPaolo Bonzini return 0; 50baacf047SPaolo Bonzini } 51baacf047SPaolo Bonzini } 52baacf047SPaolo Bonzini 53baacf047SPaolo Bonzini static void inet_setport(struct addrinfo *e, int port) 54baacf047SPaolo Bonzini { 55baacf047SPaolo Bonzini struct sockaddr_in *i4; 56baacf047SPaolo Bonzini struct sockaddr_in6 *i6; 57baacf047SPaolo Bonzini 58baacf047SPaolo Bonzini switch (e->ai_family) { 59baacf047SPaolo Bonzini case PF_INET6: 60baacf047SPaolo Bonzini i6 = (void*)e->ai_addr; 61baacf047SPaolo Bonzini i6->sin6_port = htons(port); 62baacf047SPaolo Bonzini break; 63baacf047SPaolo Bonzini case PF_INET: 64baacf047SPaolo Bonzini i4 = (void*)e->ai_addr; 65baacf047SPaolo Bonzini i4->sin_port = htons(port); 66baacf047SPaolo Bonzini break; 67baacf047SPaolo Bonzini } 68baacf047SPaolo Bonzini } 69baacf047SPaolo Bonzini 70a589569fSWenchao Xia NetworkAddressFamily inet_netfamily(int family) 71a589569fSWenchao Xia { 72a589569fSWenchao Xia switch (family) { 73a589569fSWenchao Xia case PF_INET6: return NETWORK_ADDRESS_FAMILY_IPV6; 74a589569fSWenchao Xia case PF_INET: return NETWORK_ADDRESS_FAMILY_IPV4; 75a589569fSWenchao Xia case PF_UNIX: return NETWORK_ADDRESS_FAMILY_UNIX; 76a589569fSWenchao Xia } 77a589569fSWenchao Xia return NETWORK_ADDRESS_FAMILY_UNKNOWN; 78a589569fSWenchao Xia } 79a589569fSWenchao Xia 801856835dSDaniel P. Berrange /* 811856835dSDaniel P. Berrange * Matrix we're trying to apply 821856835dSDaniel P. Berrange * 831856835dSDaniel P. Berrange * ipv4 ipv6 family 841856835dSDaniel P. Berrange * - - PF_UNSPEC 851856835dSDaniel P. Berrange * - f PF_INET 861856835dSDaniel P. Berrange * - t PF_INET6 871856835dSDaniel P. Berrange * f - PF_INET6 881856835dSDaniel P. Berrange * f f <error> 891856835dSDaniel P. Berrange * f t PF_INET6 901856835dSDaniel P. Berrange * t - PF_INET 911856835dSDaniel P. Berrange * t f PF_INET 921856835dSDaniel P. Berrange * t t PF_INET6 931856835dSDaniel P. Berrange * 941856835dSDaniel P. Berrange * NB, this matrix is only about getting the neccessary results 951856835dSDaniel P. Berrange * from getaddrinfo(). Some of the cases require further work 961856835dSDaniel P. Berrange * after reading results from getaddrinfo in order to fully 971856835dSDaniel P. Berrange * apply the logic the end user wants. eg with the last case 981856835dSDaniel P. Berrange * ipv4=t + ipv6=t + PF_INET6, getaddrinfo alone can only 991856835dSDaniel P. Berrange * guarantee the ipv6=t part of the request - we need more 1001856835dSDaniel P. Berrange * checks to provide ipv4=t part of the guarantee. This is 1011856835dSDaniel P. Berrange * outside scope of this method and not currently handled by 1021856835dSDaniel P. Berrange * callers at all. 1031856835dSDaniel P. Berrange */ 1041856835dSDaniel P. Berrange static int inet_ai_family_from_address(InetSocketAddress *addr, 1051856835dSDaniel P. Berrange Error **errp) 1061856835dSDaniel P. Berrange { 1071856835dSDaniel P. Berrange if (addr->has_ipv6 && addr->has_ipv4 && 1081856835dSDaniel P. Berrange !addr->ipv6 && !addr->ipv4) { 1091856835dSDaniel P. Berrange error_setg(errp, "Cannot disable IPv4 and IPv6 at same time"); 1101856835dSDaniel P. Berrange return PF_UNSPEC; 1111856835dSDaniel P. Berrange } 1121856835dSDaniel P. Berrange if ((addr->has_ipv6 && addr->ipv6) || (addr->has_ipv4 && !addr->ipv4)) { 1131856835dSDaniel P. Berrange return PF_INET6; 1141856835dSDaniel P. Berrange } 1151856835dSDaniel P. Berrange if ((addr->has_ipv4 && addr->ipv4) || (addr->has_ipv6 && !addr->ipv6)) { 1161856835dSDaniel P. Berrange return PF_INET; 1171856835dSDaniel P. Berrange } 1181856835dSDaniel P. Berrange return PF_UNSPEC; 1191856835dSDaniel P. Berrange } 1201856835dSDaniel P. Berrange 1211856835dSDaniel P. Berrange static int inet_listen_saddr(InetSocketAddress *saddr, 1221856835dSDaniel P. Berrange int port_offset, 1231856835dSDaniel P. Berrange bool update_addr, 1241856835dSDaniel P. Berrange Error **errp) 125baacf047SPaolo Bonzini { 126baacf047SPaolo Bonzini struct addrinfo ai,*res,*e; 127baacf047SPaolo Bonzini char port[33]; 128baacf047SPaolo Bonzini char uaddr[INET6_ADDRSTRLEN+1]; 129baacf047SPaolo Bonzini char uport[33]; 1301856835dSDaniel P. Berrange int slisten, rc, port_min, port_max, p; 1311856835dSDaniel P. Berrange Error *err = NULL; 132baacf047SPaolo Bonzini 133baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 1343de3d698SWolfgang Bumiller ai.ai_flags = AI_PASSIVE; 1351856835dSDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(saddr, &err); 136baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 137baacf047SPaolo Bonzini 1381856835dSDaniel P. Berrange if (err) { 1391856835dSDaniel P. Berrange error_propagate(errp, err); 1401856835dSDaniel P. Berrange return -1; 1411856835dSDaniel P. Berrange } 1421856835dSDaniel P. Berrange 1431856835dSDaniel P. Berrange if (saddr->host == NULL) { 1440983f5e6SDaniel P. Berrange error_setg(errp, "host not specified"); 145baacf047SPaolo Bonzini return -1; 146baacf047SPaolo Bonzini } 1471856835dSDaniel P. Berrange if (saddr->port != NULL) { 1481856835dSDaniel P. Berrange pstrcpy(port, sizeof(port), saddr->port); 1490983f5e6SDaniel P. Berrange } else { 1500983f5e6SDaniel P. Berrange port[0] = '\0'; 1510983f5e6SDaniel P. Berrange } 152baacf047SPaolo Bonzini 153baacf047SPaolo Bonzini /* lookup */ 1548bc89127SGerd Hoffmann if (port_offset) { 1558bc89127SGerd Hoffmann unsigned long long baseport; 1560983f5e6SDaniel P. Berrange if (strlen(port) == 0) { 1570983f5e6SDaniel P. Berrange error_setg(errp, "port not specified"); 1580983f5e6SDaniel P. Berrange return -1; 1590983f5e6SDaniel P. Berrange } 1608bc89127SGerd Hoffmann if (parse_uint_full(port, &baseport, 10) < 0) { 1618bc89127SGerd Hoffmann error_setg(errp, "can't convert to a number: %s", port); 1628bc89127SGerd Hoffmann return -1; 1638bc89127SGerd Hoffmann } 1648bc89127SGerd Hoffmann if (baseport > 65535 || 1658bc89127SGerd Hoffmann baseport + port_offset > 65535) { 1668bc89127SGerd Hoffmann error_setg(errp, "port %s out of range", port); 1678bc89127SGerd Hoffmann return -1; 1688bc89127SGerd Hoffmann } 1698bc89127SGerd Hoffmann snprintf(port, sizeof(port), "%d", (int)baseport + port_offset); 1708bc89127SGerd Hoffmann } 1711856835dSDaniel P. Berrange rc = getaddrinfo(strlen(saddr->host) ? saddr->host : NULL, 1720983f5e6SDaniel P. Berrange strlen(port) ? port : NULL, &ai, &res); 173baacf047SPaolo Bonzini if (rc != 0) { 1741856835dSDaniel P. Berrange error_setg(errp, "address resolution failed for %s:%s: %s", 1751856835dSDaniel P. Berrange saddr->host, port, gai_strerror(rc)); 176baacf047SPaolo Bonzini return -1; 177baacf047SPaolo Bonzini } 178baacf047SPaolo Bonzini 179baacf047SPaolo Bonzini /* create socket + bind */ 180baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 181baacf047SPaolo Bonzini getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, 182baacf047SPaolo Bonzini uaddr,INET6_ADDRSTRLEN,uport,32, 183baacf047SPaolo Bonzini NI_NUMERICHOST | NI_NUMERICSERV); 184baacf047SPaolo Bonzini slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); 185baacf047SPaolo Bonzini if (slisten < 0) { 186baacf047SPaolo Bonzini if (!e->ai_next) { 187235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 188baacf047SPaolo Bonzini } 189baacf047SPaolo Bonzini continue; 190baacf047SPaolo Bonzini } 191baacf047SPaolo Bonzini 19204fd1c78SSebastian Ottlik socket_set_fast_reuse(slisten); 193baacf047SPaolo Bonzini #ifdef IPV6_V6ONLY 194baacf047SPaolo Bonzini if (e->ai_family == PF_INET6) { 195baacf047SPaolo Bonzini /* listen on both ipv4 and ipv6 */ 196f9b5426fSPeter Maydell const int off = 0; 1979957fc7fSStefan Weil qemu_setsockopt(slisten, IPPROTO_IPV6, IPV6_V6ONLY, &off, 198baacf047SPaolo Bonzini sizeof(off)); 199baacf047SPaolo Bonzini } 200baacf047SPaolo Bonzini #endif 201baacf047SPaolo Bonzini 202baacf047SPaolo Bonzini port_min = inet_getport(e); 2031856835dSDaniel P. Berrange port_max = saddr->has_to ? saddr->to + port_offset : port_min; 204baacf047SPaolo Bonzini for (p = port_min; p <= port_max; p++) { 205baacf047SPaolo Bonzini inet_setport(e, p); 206baacf047SPaolo Bonzini if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) { 207baacf047SPaolo Bonzini goto listen; 208baacf047SPaolo Bonzini } 209baacf047SPaolo Bonzini if (p == port_max) { 210baacf047SPaolo Bonzini if (!e->ai_next) { 211235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to bind socket"); 212baacf047SPaolo Bonzini } 213baacf047SPaolo Bonzini } 214baacf047SPaolo Bonzini } 215baacf047SPaolo Bonzini closesocket(slisten); 216baacf047SPaolo Bonzini } 217baacf047SPaolo Bonzini freeaddrinfo(res); 218baacf047SPaolo Bonzini return -1; 219baacf047SPaolo Bonzini 220baacf047SPaolo Bonzini listen: 221baacf047SPaolo Bonzini if (listen(slisten,1) != 0) { 222235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to listen on socket"); 223baacf047SPaolo Bonzini closesocket(slisten); 224baacf047SPaolo Bonzini freeaddrinfo(res); 225baacf047SPaolo Bonzini return -1; 226baacf047SPaolo Bonzini } 2271856835dSDaniel P. Berrange if (update_addr) { 2281856835dSDaniel P. Berrange g_free(saddr->host); 2291856835dSDaniel P. Berrange saddr->host = g_strdup(uaddr); 2301856835dSDaniel P. Berrange g_free(saddr->port); 2311856835dSDaniel P. Berrange saddr->port = g_strdup_printf("%d", 2321856835dSDaniel P. Berrange inet_getport(e) - port_offset); 2331856835dSDaniel P. Berrange saddr->has_ipv6 = saddr->ipv6 = e->ai_family == PF_INET6; 2341856835dSDaniel P. Berrange saddr->has_ipv4 = saddr->ipv4 = e->ai_family != PF_INET6; 2351856835dSDaniel P. Berrange } 236baacf047SPaolo Bonzini freeaddrinfo(res); 237baacf047SPaolo Bonzini return slisten; 238baacf047SPaolo Bonzini } 239baacf047SPaolo Bonzini 240baacf047SPaolo Bonzini #ifdef _WIN32 241baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 242baacf047SPaolo Bonzini ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY) 243baacf047SPaolo Bonzini #else 244baacf047SPaolo Bonzini #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 245baacf047SPaolo Bonzini ((rc) == -EINPROGRESS) 246baacf047SPaolo Bonzini #endif 247baacf047SPaolo Bonzini 248baacf047SPaolo Bonzini /* Struct to store connect state for non blocking connect */ 249baacf047SPaolo Bonzini typedef struct ConnectState { 250baacf047SPaolo Bonzini int fd; 251baacf047SPaolo Bonzini struct addrinfo *addr_list; 252baacf047SPaolo Bonzini struct addrinfo *current_addr; 253baacf047SPaolo Bonzini NonBlockingConnectHandler *callback; 254baacf047SPaolo Bonzini void *opaque; 255baacf047SPaolo Bonzini } ConnectState; 256baacf047SPaolo Bonzini 257baacf047SPaolo Bonzini static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, 258baacf047SPaolo Bonzini ConnectState *connect_state, Error **errp); 259baacf047SPaolo Bonzini 260baacf047SPaolo Bonzini static void wait_for_connect(void *opaque) 261baacf047SPaolo Bonzini { 262baacf047SPaolo Bonzini ConnectState *s = opaque; 263baacf047SPaolo Bonzini int val = 0, rc = 0; 264baacf047SPaolo Bonzini socklen_t valsize = sizeof(val); 265baacf047SPaolo Bonzini bool in_progress; 26651795029SCorey Minyard Error *err = NULL; 267baacf047SPaolo Bonzini 26882e1cc4bSFam Zheng qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 269baacf047SPaolo Bonzini 270baacf047SPaolo Bonzini do { 2719957fc7fSStefan Weil rc = qemu_getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize); 272b16a44e1SDaniel P. Berrange } while (rc == -1 && errno == EINTR); 273baacf047SPaolo Bonzini 274baacf047SPaolo Bonzini /* update rc to contain error */ 275baacf047SPaolo Bonzini if (!rc && val) { 276baacf047SPaolo Bonzini rc = -1; 27751795029SCorey Minyard errno = val; 278baacf047SPaolo Bonzini } 279baacf047SPaolo Bonzini 280baacf047SPaolo Bonzini /* connect error */ 281baacf047SPaolo Bonzini if (rc < 0) { 28251795029SCorey Minyard error_setg_errno(&err, errno, "Error connecting to socket"); 283baacf047SPaolo Bonzini closesocket(s->fd); 284baacf047SPaolo Bonzini s->fd = rc; 285baacf047SPaolo Bonzini } 286baacf047SPaolo Bonzini 287baacf047SPaolo Bonzini /* try to connect to the next address on the list */ 288baacf047SPaolo Bonzini if (s->current_addr) { 289baacf047SPaolo Bonzini while (s->current_addr->ai_next != NULL && s->fd < 0) { 290baacf047SPaolo Bonzini s->current_addr = s->current_addr->ai_next; 291baacf047SPaolo Bonzini s->fd = inet_connect_addr(s->current_addr, &in_progress, s, NULL); 29251795029SCorey Minyard if (s->fd < 0) { 29351795029SCorey Minyard error_free(err); 29451795029SCorey Minyard err = NULL; 29551795029SCorey Minyard error_setg_errno(&err, errno, "Unable to start socket connect"); 29651795029SCorey Minyard } 297baacf047SPaolo Bonzini /* connect in progress */ 298baacf047SPaolo Bonzini if (in_progress) { 29951795029SCorey Minyard goto out; 300baacf047SPaolo Bonzini } 301baacf047SPaolo Bonzini } 302baacf047SPaolo Bonzini 303baacf047SPaolo Bonzini freeaddrinfo(s->addr_list); 304baacf047SPaolo Bonzini } 305baacf047SPaolo Bonzini 306baacf047SPaolo Bonzini if (s->callback) { 30751795029SCorey Minyard s->callback(s->fd, err, s->opaque); 308baacf047SPaolo Bonzini } 309baacf047SPaolo Bonzini g_free(s); 31051795029SCorey Minyard out: 31151795029SCorey Minyard error_free(err); 312baacf047SPaolo Bonzini } 313baacf047SPaolo Bonzini 314baacf047SPaolo Bonzini static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, 315baacf047SPaolo Bonzini ConnectState *connect_state, Error **errp) 316baacf047SPaolo Bonzini { 317baacf047SPaolo Bonzini int sock, rc; 318baacf047SPaolo Bonzini 319baacf047SPaolo Bonzini *in_progress = false; 320baacf047SPaolo Bonzini 321baacf047SPaolo Bonzini sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); 322baacf047SPaolo Bonzini if (sock < 0) { 323235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 324baacf047SPaolo Bonzini return -1; 325baacf047SPaolo Bonzini } 32604fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 327baacf047SPaolo Bonzini if (connect_state != NULL) { 328f9e8caccSStefan Hajnoczi qemu_set_nonblock(sock); 329baacf047SPaolo Bonzini } 330baacf047SPaolo Bonzini /* connect to peer */ 331baacf047SPaolo Bonzini do { 332baacf047SPaolo Bonzini rc = 0; 333baacf047SPaolo Bonzini if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) { 334b16a44e1SDaniel P. Berrange rc = -errno; 335baacf047SPaolo Bonzini } 336baacf047SPaolo Bonzini } while (rc == -EINTR); 337baacf047SPaolo Bonzini 338baacf047SPaolo Bonzini if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 339baacf047SPaolo Bonzini connect_state->fd = sock; 34082e1cc4bSFam Zheng qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state); 341baacf047SPaolo Bonzini *in_progress = true; 342baacf047SPaolo Bonzini } else if (rc < 0) { 343235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to connect socket"); 344baacf047SPaolo Bonzini closesocket(sock); 345baacf047SPaolo Bonzini return -1; 346baacf047SPaolo Bonzini } 347baacf047SPaolo Bonzini return sock; 348baacf047SPaolo Bonzini } 349baacf047SPaolo Bonzini 3502942e420SDaniel P. Berrange static struct addrinfo *inet_parse_connect_saddr(InetSocketAddress *saddr, 3512942e420SDaniel P. Berrange Error **errp) 352baacf047SPaolo Bonzini { 353baacf047SPaolo Bonzini struct addrinfo ai, *res; 354baacf047SPaolo Bonzini int rc; 3552942e420SDaniel P. Berrange Error *err = NULL; 356baacf047SPaolo Bonzini 357baacf047SPaolo Bonzini memset(&ai, 0, sizeof(ai)); 358baacf047SPaolo Bonzini 3593de3d698SWolfgang Bumiller ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG; 3602942e420SDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(saddr, &err); 361baacf047SPaolo Bonzini ai.ai_socktype = SOCK_STREAM; 362baacf047SPaolo Bonzini 3632942e420SDaniel P. Berrange if (err) { 3642942e420SDaniel P. Berrange error_propagate(errp, err); 3652942e420SDaniel P. Berrange return NULL; 3662942e420SDaniel P. Berrange } 3672942e420SDaniel P. Berrange 3682942e420SDaniel P. Berrange if (saddr->host == NULL || saddr->port == NULL) { 369baacf047SPaolo Bonzini error_setg(errp, "host and/or port not specified"); 370baacf047SPaolo Bonzini return NULL; 371baacf047SPaolo Bonzini } 372baacf047SPaolo Bonzini 373baacf047SPaolo Bonzini /* lookup */ 3742942e420SDaniel P. Berrange rc = getaddrinfo(saddr->host, saddr->port, &ai, &res); 375baacf047SPaolo Bonzini if (rc != 0) { 3762942e420SDaniel P. Berrange error_setg(errp, "address resolution failed for %s:%s: %s", 3772942e420SDaniel P. Berrange saddr->host, saddr->port, gai_strerror(rc)); 378baacf047SPaolo Bonzini return NULL; 379baacf047SPaolo Bonzini } 380baacf047SPaolo Bonzini return res; 381baacf047SPaolo Bonzini } 382baacf047SPaolo Bonzini 383baacf047SPaolo Bonzini /** 384baacf047SPaolo Bonzini * Create a socket and connect it to an address. 385baacf047SPaolo Bonzini * 3862942e420SDaniel P. Berrange * @saddr: Inet socket address specification 387baacf047SPaolo Bonzini * @errp: set on error 388baacf047SPaolo Bonzini * @callback: callback function for non-blocking connect 389baacf047SPaolo Bonzini * @opaque: opaque for callback function 390baacf047SPaolo Bonzini * 391baacf047SPaolo Bonzini * Returns: -1 on error, file descriptor on success. 392baacf047SPaolo Bonzini * 393baacf047SPaolo Bonzini * If @callback is non-null, the connect is non-blocking. If this 394baacf047SPaolo Bonzini * function succeeds, callback will be called when the connection 395baacf047SPaolo Bonzini * completes, with the file descriptor on success, or -1 on error. 396baacf047SPaolo Bonzini */ 3972942e420SDaniel P. Berrange static int inet_connect_saddr(InetSocketAddress *saddr, Error **errp, 398baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 399baacf047SPaolo Bonzini { 4003f9286b7SMarkus Armbruster Error *local_err = NULL; 401baacf047SPaolo Bonzini struct addrinfo *res, *e; 402baacf047SPaolo Bonzini int sock = -1; 403baacf047SPaolo Bonzini bool in_progress; 404baacf047SPaolo Bonzini ConnectState *connect_state = NULL; 405baacf047SPaolo Bonzini 4062942e420SDaniel P. Berrange res = inet_parse_connect_saddr(saddr, errp); 407baacf047SPaolo Bonzini if (!res) { 408baacf047SPaolo Bonzini return -1; 409baacf047SPaolo Bonzini } 410baacf047SPaolo Bonzini 411baacf047SPaolo Bonzini if (callback != NULL) { 412baacf047SPaolo Bonzini connect_state = g_malloc0(sizeof(*connect_state)); 413baacf047SPaolo Bonzini connect_state->addr_list = res; 414baacf047SPaolo Bonzini connect_state->callback = callback; 415baacf047SPaolo Bonzini connect_state->opaque = opaque; 416baacf047SPaolo Bonzini } 417baacf047SPaolo Bonzini 418baacf047SPaolo Bonzini for (e = res; e != NULL; e = e->ai_next) { 4193f9286b7SMarkus Armbruster error_free(local_err); 4203f9286b7SMarkus Armbruster local_err = NULL; 421baacf047SPaolo Bonzini if (connect_state != NULL) { 422baacf047SPaolo Bonzini connect_state->current_addr = e; 423baacf047SPaolo Bonzini } 4243f9286b7SMarkus Armbruster sock = inet_connect_addr(e, &in_progress, connect_state, &local_err); 4253f9286b7SMarkus Armbruster if (sock >= 0) { 426baacf047SPaolo Bonzini break; 427baacf047SPaolo Bonzini } 428baacf047SPaolo Bonzini } 4293f9286b7SMarkus Armbruster 4303f9286b7SMarkus Armbruster if (sock < 0) { 4313f9286b7SMarkus Armbruster error_propagate(errp, local_err); 4323f9286b7SMarkus Armbruster } else if (in_progress) { 4333f9286b7SMarkus Armbruster /* wait_for_connect() will do the rest */ 4343f9286b7SMarkus Armbruster return sock; 4353f9286b7SMarkus Armbruster } else { 4363f9286b7SMarkus Armbruster if (callback) { 43751795029SCorey Minyard callback(sock, NULL, opaque); 4383f9286b7SMarkus Armbruster } 4393f9286b7SMarkus Armbruster } 440baacf047SPaolo Bonzini g_free(connect_state); 441baacf047SPaolo Bonzini freeaddrinfo(res); 442baacf047SPaolo Bonzini return sock; 443baacf047SPaolo Bonzini } 444baacf047SPaolo Bonzini 4458b39910eSDaniel P. Berrange static int inet_dgram_saddr(InetSocketAddress *sraddr, 4468b39910eSDaniel P. Berrange InetSocketAddress *sladdr, 4478b39910eSDaniel P. Berrange Error **errp) 448baacf047SPaolo Bonzini { 449baacf047SPaolo Bonzini struct addrinfo ai, *peer = NULL, *local = NULL; 450baacf047SPaolo Bonzini const char *addr; 451baacf047SPaolo Bonzini const char *port; 452baacf047SPaolo Bonzini int sock = -1, rc; 4538b39910eSDaniel P. Berrange Error *err = NULL; 454baacf047SPaolo Bonzini 455baacf047SPaolo Bonzini /* lookup peer addr */ 456baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 4573de3d698SWolfgang Bumiller ai.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ADDRCONFIG; 4588b39910eSDaniel P. Berrange ai.ai_family = inet_ai_family_from_address(sraddr, &err); 459baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 460baacf047SPaolo Bonzini 4618b39910eSDaniel P. Berrange if (err) { 4628b39910eSDaniel P. Berrange error_propagate(errp, err); 46358c652c0SPaolo Bonzini goto err; 4648b39910eSDaniel P. Berrange } 4658b39910eSDaniel P. Berrange 4668b39910eSDaniel P. Berrange addr = sraddr->host; 4678b39910eSDaniel P. Berrange port = sraddr->port; 468baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 469baacf047SPaolo Bonzini addr = "localhost"; 470baacf047SPaolo Bonzini } 471baacf047SPaolo Bonzini if (port == NULL || strlen(port) == 0) { 472baacf047SPaolo Bonzini error_setg(errp, "remote port not specified"); 47358c652c0SPaolo Bonzini goto err; 474baacf047SPaolo Bonzini } 475baacf047SPaolo Bonzini 476baacf047SPaolo Bonzini if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) { 477baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 478baacf047SPaolo Bonzini gai_strerror(rc)); 47958c652c0SPaolo Bonzini goto err; 480baacf047SPaolo Bonzini } 481baacf047SPaolo Bonzini 482baacf047SPaolo Bonzini /* lookup local addr */ 483baacf047SPaolo Bonzini memset(&ai,0, sizeof(ai)); 484baacf047SPaolo Bonzini ai.ai_flags = AI_PASSIVE; 485baacf047SPaolo Bonzini ai.ai_family = peer->ai_family; 486baacf047SPaolo Bonzini ai.ai_socktype = SOCK_DGRAM; 487baacf047SPaolo Bonzini 4888b39910eSDaniel P. Berrange if (sladdr) { 4898b39910eSDaniel P. Berrange addr = sladdr->host; 4908b39910eSDaniel P. Berrange port = sladdr->port; 491baacf047SPaolo Bonzini if (addr == NULL || strlen(addr) == 0) { 492baacf047SPaolo Bonzini addr = NULL; 493baacf047SPaolo Bonzini } 4948b39910eSDaniel P. Berrange if (!port || strlen(port) == 0) { 495baacf047SPaolo Bonzini port = "0"; 4968b39910eSDaniel P. Berrange } 4978b39910eSDaniel P. Berrange } else { 4988b39910eSDaniel P. Berrange addr = NULL; 4998b39910eSDaniel P. Berrange port = "0"; 5008b39910eSDaniel P. Berrange } 501baacf047SPaolo Bonzini 502baacf047SPaolo Bonzini if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) { 503baacf047SPaolo Bonzini error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 504baacf047SPaolo Bonzini gai_strerror(rc)); 505baacf047SPaolo Bonzini goto err; 506baacf047SPaolo Bonzini } 507baacf047SPaolo Bonzini 508baacf047SPaolo Bonzini /* create socket */ 509baacf047SPaolo Bonzini sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); 510baacf047SPaolo Bonzini if (sock < 0) { 511235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 512baacf047SPaolo Bonzini goto err; 513baacf047SPaolo Bonzini } 51404fd1c78SSebastian Ottlik socket_set_fast_reuse(sock); 515baacf047SPaolo Bonzini 516baacf047SPaolo Bonzini /* bind socket */ 517baacf047SPaolo Bonzini if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { 518235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to bind socket"); 519baacf047SPaolo Bonzini goto err; 520baacf047SPaolo Bonzini } 521baacf047SPaolo Bonzini 522baacf047SPaolo Bonzini /* connect to peer */ 523baacf047SPaolo Bonzini if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { 524235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to connect socket"); 525baacf047SPaolo Bonzini goto err; 526baacf047SPaolo Bonzini } 527baacf047SPaolo Bonzini 528baacf047SPaolo Bonzini freeaddrinfo(local); 529baacf047SPaolo Bonzini freeaddrinfo(peer); 530baacf047SPaolo Bonzini return sock; 531baacf047SPaolo Bonzini 532baacf047SPaolo Bonzini err: 533baacf047SPaolo Bonzini if (-1 != sock) 534baacf047SPaolo Bonzini closesocket(sock); 535baacf047SPaolo Bonzini if (local) 536baacf047SPaolo Bonzini freeaddrinfo(local); 537baacf047SPaolo Bonzini if (peer) 538baacf047SPaolo Bonzini freeaddrinfo(peer); 539baacf047SPaolo Bonzini return -1; 540baacf047SPaolo Bonzini } 541baacf047SPaolo Bonzini 542baacf047SPaolo Bonzini /* compatibility wrapper */ 543f17c90beSKevin Wolf InetSocketAddress *inet_parse(const char *str, Error **errp) 544baacf047SPaolo Bonzini { 545baacf047SPaolo Bonzini InetSocketAddress *addr; 546baacf047SPaolo Bonzini const char *optstr, *h; 54755a10996SKevin Wolf char host[65]; 548baacf047SPaolo Bonzini char port[33]; 549baacf047SPaolo Bonzini int to; 550baacf047SPaolo Bonzini int pos; 551baacf047SPaolo Bonzini 552baacf047SPaolo Bonzini addr = g_new0(InetSocketAddress, 1); 553baacf047SPaolo Bonzini 554baacf047SPaolo Bonzini /* parse address */ 555baacf047SPaolo Bonzini if (str[0] == ':') { 556baacf047SPaolo Bonzini /* no host given */ 557baacf047SPaolo Bonzini host[0] = '\0'; 558baacf047SPaolo Bonzini if (1 != sscanf(str, ":%32[^,]%n", port, &pos)) { 559baacf047SPaolo Bonzini error_setg(errp, "error parsing port in address '%s'", str); 560baacf047SPaolo Bonzini goto fail; 561baacf047SPaolo Bonzini } 562baacf047SPaolo Bonzini } else if (str[0] == '[') { 563baacf047SPaolo Bonzini /* IPv6 addr */ 564baacf047SPaolo Bonzini if (2 != sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos)) { 565baacf047SPaolo Bonzini error_setg(errp, "error parsing IPv6 address '%s'", str); 566baacf047SPaolo Bonzini goto fail; 567baacf047SPaolo Bonzini } 568baacf047SPaolo Bonzini addr->ipv6 = addr->has_ipv6 = true; 569baacf047SPaolo Bonzini } else { 570391b7b97SJán Tomko /* hostname or IPv4 addr */ 571baacf047SPaolo Bonzini if (2 != sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos)) { 572baacf047SPaolo Bonzini error_setg(errp, "error parsing address '%s'", str); 573baacf047SPaolo Bonzini goto fail; 574baacf047SPaolo Bonzini } 575391b7b97SJán Tomko if (host[strspn(host, "0123456789.")] == '\0') { 576391b7b97SJán Tomko addr->ipv4 = addr->has_ipv4 = true; 577391b7b97SJán Tomko } 578baacf047SPaolo Bonzini } 579baacf047SPaolo Bonzini 580baacf047SPaolo Bonzini addr->host = g_strdup(host); 581baacf047SPaolo Bonzini addr->port = g_strdup(port); 582baacf047SPaolo Bonzini 583baacf047SPaolo Bonzini /* parse options */ 584baacf047SPaolo Bonzini optstr = str + pos; 585baacf047SPaolo Bonzini h = strstr(optstr, ",to="); 586baacf047SPaolo Bonzini if (h) { 587baacf047SPaolo Bonzini h += 4; 588baacf047SPaolo Bonzini if (sscanf(h, "%d%n", &to, &pos) != 1 || 589baacf047SPaolo Bonzini (h[pos] != '\0' && h[pos] != ',')) { 590baacf047SPaolo Bonzini error_setg(errp, "error parsing to= argument"); 591baacf047SPaolo Bonzini goto fail; 592baacf047SPaolo Bonzini } 593baacf047SPaolo Bonzini addr->has_to = true; 594baacf047SPaolo Bonzini addr->to = to; 595baacf047SPaolo Bonzini } 596baacf047SPaolo Bonzini if (strstr(optstr, ",ipv4")) { 597baacf047SPaolo Bonzini addr->ipv4 = addr->has_ipv4 = true; 598baacf047SPaolo Bonzini } 599baacf047SPaolo Bonzini if (strstr(optstr, ",ipv6")) { 600baacf047SPaolo Bonzini addr->ipv6 = addr->has_ipv6 = true; 601baacf047SPaolo Bonzini } 602baacf047SPaolo Bonzini return addr; 603baacf047SPaolo Bonzini 604baacf047SPaolo Bonzini fail: 605baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 606baacf047SPaolo Bonzini return NULL; 607baacf047SPaolo Bonzini } 608baacf047SPaolo Bonzini 609baacf047SPaolo Bonzini int inet_listen(const char *str, char *ostr, int olen, 610baacf047SPaolo Bonzini int socktype, int port_offset, Error **errp) 611baacf047SPaolo Bonzini { 612baacf047SPaolo Bonzini char *optstr; 613baacf047SPaolo Bonzini int sock = -1; 614baacf047SPaolo Bonzini InetSocketAddress *addr; 615baacf047SPaolo Bonzini 616baacf047SPaolo Bonzini addr = inet_parse(str, errp); 617baacf047SPaolo Bonzini if (addr != NULL) { 6181856835dSDaniel P. Berrange sock = inet_listen_saddr(addr, port_offset, true, errp); 619baacf047SPaolo Bonzini if (sock != -1 && ostr) { 620baacf047SPaolo Bonzini optstr = strchr(str, ','); 6211856835dSDaniel P. Berrange if (addr->ipv6) { 622baacf047SPaolo Bonzini snprintf(ostr, olen, "[%s]:%s%s", 6231856835dSDaniel P. Berrange addr->host, 6241856835dSDaniel P. Berrange addr->port, 625baacf047SPaolo Bonzini optstr ? optstr : ""); 626baacf047SPaolo Bonzini } else { 627baacf047SPaolo Bonzini snprintf(ostr, olen, "%s:%s%s", 6281856835dSDaniel P. Berrange addr->host, 6291856835dSDaniel P. Berrange addr->port, 630baacf047SPaolo Bonzini optstr ? optstr : ""); 631baacf047SPaolo Bonzini } 632baacf047SPaolo Bonzini } 6331856835dSDaniel P. Berrange qapi_free_InetSocketAddress(addr); 634baacf047SPaolo Bonzini } 635baacf047SPaolo Bonzini return sock; 636baacf047SPaolo Bonzini } 637baacf047SPaolo Bonzini 638baacf047SPaolo Bonzini /** 639baacf047SPaolo Bonzini * Create a blocking socket and connect it to an address. 640baacf047SPaolo Bonzini * 641baacf047SPaolo Bonzini * @str: address string 642baacf047SPaolo Bonzini * @errp: set in case of an error 643baacf047SPaolo Bonzini * 644baacf047SPaolo Bonzini * Returns -1 in case of error, file descriptor on success 645baacf047SPaolo Bonzini **/ 646baacf047SPaolo Bonzini int inet_connect(const char *str, Error **errp) 647baacf047SPaolo Bonzini { 648baacf047SPaolo Bonzini int sock = -1; 649baacf047SPaolo Bonzini InetSocketAddress *addr; 650baacf047SPaolo Bonzini 651baacf047SPaolo Bonzini addr = inet_parse(str, errp); 652baacf047SPaolo Bonzini if (addr != NULL) { 6532942e420SDaniel P. Berrange sock = inet_connect_saddr(addr, errp, NULL, NULL); 654baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 655baacf047SPaolo Bonzini } 656baacf047SPaolo Bonzini return sock; 657baacf047SPaolo Bonzini } 658baacf047SPaolo Bonzini 659baacf047SPaolo Bonzini /** 660baacf047SPaolo Bonzini * Create a non-blocking socket and connect it to an address. 661baacf047SPaolo Bonzini * Calls the callback function with fd in case of success or -1 in case of 662baacf047SPaolo Bonzini * error. 663baacf047SPaolo Bonzini * 664baacf047SPaolo Bonzini * @str: address string 665baacf047SPaolo Bonzini * @callback: callback function that is called when connect completes, 666baacf047SPaolo Bonzini * cannot be NULL. 667baacf047SPaolo Bonzini * @opaque: opaque for callback function 668baacf047SPaolo Bonzini * @errp: set in case of an error 669baacf047SPaolo Bonzini * 670baacf047SPaolo Bonzini * Returns: -1 on immediate error, file descriptor on success. 671baacf047SPaolo Bonzini **/ 672baacf047SPaolo Bonzini int inet_nonblocking_connect(const char *str, 673baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, 674baacf047SPaolo Bonzini void *opaque, Error **errp) 675baacf047SPaolo Bonzini { 676baacf047SPaolo Bonzini int sock = -1; 677baacf047SPaolo Bonzini InetSocketAddress *addr; 678baacf047SPaolo Bonzini 679baacf047SPaolo Bonzini g_assert(callback != NULL); 680baacf047SPaolo Bonzini 681baacf047SPaolo Bonzini addr = inet_parse(str, errp); 682baacf047SPaolo Bonzini if (addr != NULL) { 6832942e420SDaniel P. Berrange sock = inet_connect_saddr(addr, errp, callback, opaque); 684baacf047SPaolo Bonzini qapi_free_InetSocketAddress(addr); 685baacf047SPaolo Bonzini } 686baacf047SPaolo Bonzini return sock; 687baacf047SPaolo Bonzini } 688baacf047SPaolo Bonzini 689baacf047SPaolo Bonzini #ifndef _WIN32 690baacf047SPaolo Bonzini 6911856835dSDaniel P. Berrange static int unix_listen_saddr(UnixSocketAddress *saddr, 6921856835dSDaniel P. Berrange bool update_addr, 6931856835dSDaniel P. Berrange Error **errp) 694baacf047SPaolo Bonzini { 695baacf047SPaolo Bonzini struct sockaddr_un un; 696baacf047SPaolo Bonzini int sock, fd; 697baacf047SPaolo Bonzini 698baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 699baacf047SPaolo Bonzini if (sock < 0) { 700b658c53dSPaolo Bonzini error_setg_errno(errp, errno, "Failed to create Unix socket"); 701baacf047SPaolo Bonzini return -1; 702baacf047SPaolo Bonzini } 703baacf047SPaolo Bonzini 704baacf047SPaolo Bonzini memset(&un, 0, sizeof(un)); 705baacf047SPaolo Bonzini un.sun_family = AF_UNIX; 7061856835dSDaniel P. Berrange if (saddr->path && strlen(saddr->path)) { 7071856835dSDaniel P. Berrange snprintf(un.sun_path, sizeof(un.sun_path), "%s", saddr->path); 708baacf047SPaolo Bonzini } else { 709b658c53dSPaolo Bonzini const char *tmpdir = getenv("TMPDIR"); 710b658c53dSPaolo Bonzini tmpdir = tmpdir ? tmpdir : "/tmp"; 711b658c53dSPaolo Bonzini if (snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX", 712b658c53dSPaolo Bonzini tmpdir) >= sizeof(un.sun_path)) { 713b658c53dSPaolo Bonzini error_setg_errno(errp, errno, 714b658c53dSPaolo Bonzini "TMPDIR environment variable (%s) too large", tmpdir); 715b658c53dSPaolo Bonzini goto err; 716b658c53dSPaolo Bonzini } 717b658c53dSPaolo Bonzini 718baacf047SPaolo Bonzini /* 719baacf047SPaolo Bonzini * This dummy fd usage silences the mktemp() unsecure warning. 720baacf047SPaolo Bonzini * Using mkstemp() doesn't make things more secure here 721baacf047SPaolo Bonzini * though. bind() complains about existing files, so we have 722baacf047SPaolo Bonzini * to unlink first and thus re-open the race window. The 723baacf047SPaolo Bonzini * worst case possible is bind() failing, i.e. a DoS attack. 724baacf047SPaolo Bonzini */ 725b658c53dSPaolo Bonzini fd = mkstemp(un.sun_path); 726b658c53dSPaolo Bonzini if (fd < 0) { 727b658c53dSPaolo Bonzini error_setg_errno(errp, errno, 728b658c53dSPaolo Bonzini "Failed to make a temporary socket name in %s", tmpdir); 729b658c53dSPaolo Bonzini goto err; 730b658c53dSPaolo Bonzini } 731b658c53dSPaolo Bonzini close(fd); 7321856835dSDaniel P. Berrange if (update_addr) { 7331856835dSDaniel P. Berrange g_free(saddr->path); 7341856835dSDaniel P. Berrange saddr->path = g_strdup(un.sun_path); 7351856835dSDaniel P. Berrange } 736baacf047SPaolo Bonzini } 737baacf047SPaolo Bonzini 738a2f31f18SPaolo Bonzini if (unlink(un.sun_path) < 0 && errno != ENOENT) { 7390ef705a2SCole Robinson error_setg_errno(errp, errno, 7400ef705a2SCole Robinson "Failed to unlink socket %s", un.sun_path); 7410ef705a2SCole Robinson goto err; 7420ef705a2SCole Robinson } 743baacf047SPaolo Bonzini if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { 744b658c53dSPaolo Bonzini error_setg_errno(errp, errno, "Failed to bind socket to %s", un.sun_path); 745baacf047SPaolo Bonzini goto err; 746baacf047SPaolo Bonzini } 747baacf047SPaolo Bonzini if (listen(sock, 1) < 0) { 748235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to listen on socket"); 749baacf047SPaolo Bonzini goto err; 750baacf047SPaolo Bonzini } 751baacf047SPaolo Bonzini 752baacf047SPaolo Bonzini return sock; 753baacf047SPaolo Bonzini 754baacf047SPaolo Bonzini err: 755baacf047SPaolo Bonzini closesocket(sock); 756baacf047SPaolo Bonzini return -1; 757baacf047SPaolo Bonzini } 758baacf047SPaolo Bonzini 7592942e420SDaniel P. Berrange static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp, 760baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 761baacf047SPaolo Bonzini { 762baacf047SPaolo Bonzini struct sockaddr_un un; 763baacf047SPaolo Bonzini ConnectState *connect_state = NULL; 764baacf047SPaolo Bonzini int sock, rc; 765baacf047SPaolo Bonzini 7662942e420SDaniel P. Berrange if (saddr->path == NULL) { 767312fd5f2SMarkus Armbruster error_setg(errp, "unix connect: no path specified"); 768baacf047SPaolo Bonzini return -1; 769baacf047SPaolo Bonzini } 770baacf047SPaolo Bonzini 771baacf047SPaolo Bonzini sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 772baacf047SPaolo Bonzini if (sock < 0) { 773235256a2SMarkus Armbruster error_setg_errno(errp, errno, "Failed to create socket"); 774baacf047SPaolo Bonzini return -1; 775baacf047SPaolo Bonzini } 776baacf047SPaolo Bonzini if (callback != NULL) { 777baacf047SPaolo Bonzini connect_state = g_malloc0(sizeof(*connect_state)); 778baacf047SPaolo Bonzini connect_state->callback = callback; 779baacf047SPaolo Bonzini connect_state->opaque = opaque; 780f9e8caccSStefan Hajnoczi qemu_set_nonblock(sock); 781baacf047SPaolo Bonzini } 782baacf047SPaolo Bonzini 783baacf047SPaolo Bonzini memset(&un, 0, sizeof(un)); 784baacf047SPaolo Bonzini un.sun_family = AF_UNIX; 7852942e420SDaniel P. Berrange snprintf(un.sun_path, sizeof(un.sun_path), "%s", saddr->path); 786baacf047SPaolo Bonzini 787baacf047SPaolo Bonzini /* connect to peer */ 788baacf047SPaolo Bonzini do { 789baacf047SPaolo Bonzini rc = 0; 790baacf047SPaolo Bonzini if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { 791b16a44e1SDaniel P. Berrange rc = -errno; 792baacf047SPaolo Bonzini } 793baacf047SPaolo Bonzini } while (rc == -EINTR); 794baacf047SPaolo Bonzini 795baacf047SPaolo Bonzini if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 796baacf047SPaolo Bonzini connect_state->fd = sock; 79782e1cc4bSFam Zheng qemu_set_fd_handler(sock, NULL, wait_for_connect, connect_state); 798baacf047SPaolo Bonzini return sock; 799baacf047SPaolo Bonzini } else if (rc >= 0) { 800baacf047SPaolo Bonzini /* non blocking socket immediate success, call callback */ 801baacf047SPaolo Bonzini if (callback != NULL) { 80251795029SCorey Minyard callback(sock, NULL, opaque); 803baacf047SPaolo Bonzini } 804baacf047SPaolo Bonzini } 805baacf047SPaolo Bonzini 806baacf047SPaolo Bonzini if (rc < 0) { 807235256a2SMarkus Armbruster error_setg_errno(errp, -rc, "Failed to connect socket"); 808baacf047SPaolo Bonzini close(sock); 809baacf047SPaolo Bonzini sock = -1; 810baacf047SPaolo Bonzini } 811baacf047SPaolo Bonzini 812baacf047SPaolo Bonzini g_free(connect_state); 813baacf047SPaolo Bonzini return sock; 814baacf047SPaolo Bonzini } 815baacf047SPaolo Bonzini 816baacf047SPaolo Bonzini #else 817baacf047SPaolo Bonzini 8181856835dSDaniel P. Berrange static int unix_listen_saddr(UnixSocketAddress *saddr, 8191856835dSDaniel P. Berrange bool update_addr, 8201856835dSDaniel P. Berrange Error **errp) 821baacf047SPaolo Bonzini { 822baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 823baacf047SPaolo Bonzini errno = ENOTSUP; 824baacf047SPaolo Bonzini return -1; 825baacf047SPaolo Bonzini } 826baacf047SPaolo Bonzini 8272942e420SDaniel P. Berrange static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp, 828baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 829baacf047SPaolo Bonzini { 830baacf047SPaolo Bonzini error_setg(errp, "unix sockets are not available on windows"); 831baacf047SPaolo Bonzini errno = ENOTSUP; 832baacf047SPaolo Bonzini return -1; 833baacf047SPaolo Bonzini } 834baacf047SPaolo Bonzini #endif 835baacf047SPaolo Bonzini 836baacf047SPaolo Bonzini /* compatibility wrapper */ 837baacf047SPaolo Bonzini int unix_listen(const char *str, char *ostr, int olen, Error **errp) 838baacf047SPaolo Bonzini { 839baacf047SPaolo Bonzini char *path, *optstr; 840baacf047SPaolo Bonzini int sock, len; 8411856835dSDaniel P. Berrange UnixSocketAddress *saddr; 842baacf047SPaolo Bonzini 8431856835dSDaniel P. Berrange saddr = g_new0(UnixSocketAddress, 1); 844baacf047SPaolo Bonzini 845baacf047SPaolo Bonzini optstr = strchr(str, ','); 846baacf047SPaolo Bonzini if (optstr) { 847baacf047SPaolo Bonzini len = optstr - str; 848baacf047SPaolo Bonzini if (len) { 849baacf047SPaolo Bonzini path = g_malloc(len+1); 850baacf047SPaolo Bonzini snprintf(path, len+1, "%.*s", len, str); 8511856835dSDaniel P. Berrange saddr->path = path; 852baacf047SPaolo Bonzini } 853baacf047SPaolo Bonzini } else { 8541856835dSDaniel P. Berrange saddr->path = g_strdup(str); 855baacf047SPaolo Bonzini } 856baacf047SPaolo Bonzini 8571856835dSDaniel P. Berrange sock = unix_listen_saddr(saddr, true, errp); 858baacf047SPaolo Bonzini 859baacf047SPaolo Bonzini if (sock != -1 && ostr) 8601856835dSDaniel P. Berrange snprintf(ostr, olen, "%s%s", saddr->path, optstr ? optstr : ""); 8611856835dSDaniel P. Berrange qapi_free_UnixSocketAddress(saddr); 862baacf047SPaolo Bonzini return sock; 863baacf047SPaolo Bonzini } 864baacf047SPaolo Bonzini 865baacf047SPaolo Bonzini int unix_connect(const char *path, Error **errp) 866baacf047SPaolo Bonzini { 8672942e420SDaniel P. Berrange UnixSocketAddress *saddr; 868baacf047SPaolo Bonzini int sock; 869baacf047SPaolo Bonzini 8702942e420SDaniel P. Berrange saddr = g_new0(UnixSocketAddress, 1); 8712942e420SDaniel P. Berrange saddr->path = g_strdup(path); 8722942e420SDaniel P. Berrange sock = unix_connect_saddr(saddr, errp, NULL, NULL); 8732942e420SDaniel P. Berrange qapi_free_UnixSocketAddress(saddr); 874baacf047SPaolo Bonzini return sock; 875baacf047SPaolo Bonzini } 876baacf047SPaolo Bonzini 877baacf047SPaolo Bonzini 878baacf047SPaolo Bonzini int unix_nonblocking_connect(const char *path, 879baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, 880baacf047SPaolo Bonzini void *opaque, Error **errp) 881baacf047SPaolo Bonzini { 8822942e420SDaniel P. Berrange UnixSocketAddress *saddr; 883baacf047SPaolo Bonzini int sock = -1; 884baacf047SPaolo Bonzini 885baacf047SPaolo Bonzini g_assert(callback != NULL); 886baacf047SPaolo Bonzini 8872942e420SDaniel P. Berrange saddr = g_new0(UnixSocketAddress, 1); 8882942e420SDaniel P. Berrange saddr->path = g_strdup(path); 8892942e420SDaniel P. Berrange sock = unix_connect_saddr(saddr, errp, callback, opaque); 8902942e420SDaniel P. Berrange qapi_free_UnixSocketAddress(saddr); 891baacf047SPaolo Bonzini return sock; 892baacf047SPaolo Bonzini } 893baacf047SPaolo Bonzini 894baacf047SPaolo Bonzini SocketAddress *socket_parse(const char *str, Error **errp) 895baacf047SPaolo Bonzini { 896afde3f8bSGerd Hoffmann SocketAddress *addr; 897baacf047SPaolo Bonzini 898afde3f8bSGerd Hoffmann addr = g_new0(SocketAddress, 1); 899baacf047SPaolo Bonzini if (strstart(str, "unix:", NULL)) { 900baacf047SPaolo Bonzini if (str[5] == '\0') { 901312fd5f2SMarkus Armbruster error_setg(errp, "invalid Unix socket address"); 902baacf047SPaolo Bonzini goto fail; 903baacf047SPaolo Bonzini } else { 9042d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_UNIX; 90532bafa8fSEric Blake addr->u.q_unix.data = g_new(UnixSocketAddress, 1); 90632bafa8fSEric Blake addr->u.q_unix.data->path = g_strdup(str + 5); 907baacf047SPaolo Bonzini } 908baacf047SPaolo Bonzini } else if (strstart(str, "fd:", NULL)) { 909baacf047SPaolo Bonzini if (str[3] == '\0') { 910312fd5f2SMarkus Armbruster error_setg(errp, "invalid file descriptor address"); 911baacf047SPaolo Bonzini goto fail; 912baacf047SPaolo Bonzini } else { 9132d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_FD; 91432bafa8fSEric Blake addr->u.fd.data = g_new(String, 1); 91532bafa8fSEric Blake addr->u.fd.data->str = g_strdup(str + 3); 916baacf047SPaolo Bonzini } 917baacf047SPaolo Bonzini } else { 9182d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_INET; 91932bafa8fSEric Blake addr->u.inet.data = inet_parse(str, errp); 92032bafa8fSEric Blake if (addr->u.inet.data == NULL) { 921baacf047SPaolo Bonzini goto fail; 922baacf047SPaolo Bonzini } 923baacf047SPaolo Bonzini } 924baacf047SPaolo Bonzini return addr; 925baacf047SPaolo Bonzini 926baacf047SPaolo Bonzini fail: 927baacf047SPaolo Bonzini qapi_free_SocketAddress(addr); 928baacf047SPaolo Bonzini return NULL; 929baacf047SPaolo Bonzini } 930baacf047SPaolo Bonzini 931baacf047SPaolo Bonzini int socket_connect(SocketAddress *addr, Error **errp, 932baacf047SPaolo Bonzini NonBlockingConnectHandler *callback, void *opaque) 933baacf047SPaolo Bonzini { 934baacf047SPaolo Bonzini int fd; 935baacf047SPaolo Bonzini 9362d32addaSEric Blake switch (addr->type) { 937baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_INET: 93832bafa8fSEric Blake fd = inet_connect_saddr(addr->u.inet.data, errp, callback, opaque); 939baacf047SPaolo Bonzini break; 940baacf047SPaolo Bonzini 941baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_UNIX: 94232bafa8fSEric Blake fd = unix_connect_saddr(addr->u.q_unix.data, errp, callback, opaque); 943baacf047SPaolo Bonzini break; 944baacf047SPaolo Bonzini 945baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_FD: 94632bafa8fSEric Blake fd = monitor_get_fd(cur_mon, addr->u.fd.data->str, errp); 947d1ec72a4SGerd Hoffmann if (fd >= 0 && callback) { 9481a751ebfSStefan Hajnoczi qemu_set_nonblock(fd); 94951795029SCorey Minyard callback(fd, NULL, opaque); 950baacf047SPaolo Bonzini } 951baacf047SPaolo Bonzini break; 952baacf047SPaolo Bonzini 953baacf047SPaolo Bonzini default: 954baacf047SPaolo Bonzini abort(); 955baacf047SPaolo Bonzini } 956baacf047SPaolo Bonzini return fd; 957baacf047SPaolo Bonzini } 958baacf047SPaolo Bonzini 959baacf047SPaolo Bonzini int socket_listen(SocketAddress *addr, Error **errp) 960baacf047SPaolo Bonzini { 961baacf047SPaolo Bonzini int fd; 962baacf047SPaolo Bonzini 9632d32addaSEric Blake switch (addr->type) { 964baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_INET: 96532bafa8fSEric Blake fd = inet_listen_saddr(addr->u.inet.data, 0, false, errp); 966baacf047SPaolo Bonzini break; 967baacf047SPaolo Bonzini 968baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_UNIX: 96932bafa8fSEric Blake fd = unix_listen_saddr(addr->u.q_unix.data, false, errp); 970baacf047SPaolo Bonzini break; 971baacf047SPaolo Bonzini 972baacf047SPaolo Bonzini case SOCKET_ADDRESS_KIND_FD: 97332bafa8fSEric Blake fd = monitor_get_fd(cur_mon, addr->u.fd.data->str, errp); 974baacf047SPaolo Bonzini break; 975baacf047SPaolo Bonzini 976baacf047SPaolo Bonzini default: 977baacf047SPaolo Bonzini abort(); 978baacf047SPaolo Bonzini } 979baacf047SPaolo Bonzini return fd; 980baacf047SPaolo Bonzini } 981baacf047SPaolo Bonzini 9823ecc059dSGerd Hoffmann int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp) 9833ecc059dSGerd Hoffmann { 9843ecc059dSGerd Hoffmann int fd; 9853ecc059dSGerd Hoffmann 9862d32addaSEric Blake switch (remote->type) { 9873ecc059dSGerd Hoffmann case SOCKET_ADDRESS_KIND_INET: 98832bafa8fSEric Blake fd = inet_dgram_saddr(remote->u.inet.data, 98932bafa8fSEric Blake local ? local->u.inet.data : NULL, errp); 9903ecc059dSGerd Hoffmann break; 9913ecc059dSGerd Hoffmann 9923ecc059dSGerd Hoffmann default: 9933ecc059dSGerd Hoffmann error_setg(errp, "socket type unsupported for datagram"); 9947a5b6af1SGerd Hoffmann fd = -1; 9953ecc059dSGerd Hoffmann } 9963ecc059dSGerd Hoffmann return fd; 9973ecc059dSGerd Hoffmann } 99817c55decSDaniel P. Berrange 99917c55decSDaniel P. Berrange 100017c55decSDaniel P. Berrange static SocketAddress * 100117c55decSDaniel P. Berrange socket_sockaddr_to_address_inet(struct sockaddr_storage *sa, 100217c55decSDaniel P. Berrange socklen_t salen, 100317c55decSDaniel P. Berrange Error **errp) 100417c55decSDaniel P. Berrange { 100517c55decSDaniel P. Berrange char host[NI_MAXHOST]; 100617c55decSDaniel P. Berrange char serv[NI_MAXSERV]; 100717c55decSDaniel P. Berrange SocketAddress *addr; 10080399293eSEric Blake InetSocketAddress *inet; 100917c55decSDaniel P. Berrange int ret; 101017c55decSDaniel P. Berrange 101117c55decSDaniel P. Berrange ret = getnameinfo((struct sockaddr *)sa, salen, 101217c55decSDaniel P. Berrange host, sizeof(host), 101317c55decSDaniel P. Berrange serv, sizeof(serv), 101417c55decSDaniel P. Berrange NI_NUMERICHOST | NI_NUMERICSERV); 101517c55decSDaniel P. Berrange if (ret != 0) { 101617c55decSDaniel P. Berrange error_setg(errp, "Cannot format numeric socket address: %s", 101717c55decSDaniel P. Berrange gai_strerror(ret)); 101817c55decSDaniel P. Berrange return NULL; 101917c55decSDaniel P. Berrange } 102017c55decSDaniel P. Berrange 102117c55decSDaniel P. Berrange addr = g_new0(SocketAddress, 1); 10222d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_INET; 102332bafa8fSEric Blake inet = addr->u.inet.data = g_new0(InetSocketAddress, 1); 10240399293eSEric Blake inet->host = g_strdup(host); 10250399293eSEric Blake inet->port = g_strdup(serv); 102617c55decSDaniel P. Berrange if (sa->ss_family == AF_INET) { 10270399293eSEric Blake inet->has_ipv4 = inet->ipv4 = true; 102817c55decSDaniel P. Berrange } else { 10290399293eSEric Blake inet->has_ipv6 = inet->ipv6 = true; 103017c55decSDaniel P. Berrange } 103117c55decSDaniel P. Berrange 103217c55decSDaniel P. Berrange return addr; 103317c55decSDaniel P. Berrange } 103417c55decSDaniel P. Berrange 103517c55decSDaniel P. Berrange 103617c55decSDaniel P. Berrange #ifndef WIN32 103717c55decSDaniel P. Berrange static SocketAddress * 103817c55decSDaniel P. Berrange socket_sockaddr_to_address_unix(struct sockaddr_storage *sa, 103917c55decSDaniel P. Berrange socklen_t salen, 104017c55decSDaniel P. Berrange Error **errp) 104117c55decSDaniel P. Berrange { 104217c55decSDaniel P. Berrange SocketAddress *addr; 104317c55decSDaniel P. Berrange struct sockaddr_un *su = (struct sockaddr_un *)sa; 104417c55decSDaniel P. Berrange 104517c55decSDaniel P. Berrange addr = g_new0(SocketAddress, 1); 10462d32addaSEric Blake addr->type = SOCKET_ADDRESS_KIND_UNIX; 104732bafa8fSEric Blake addr->u.q_unix.data = g_new0(UnixSocketAddress, 1); 104817c55decSDaniel P. Berrange if (su->sun_path[0]) { 104932bafa8fSEric Blake addr->u.q_unix.data->path = g_strndup(su->sun_path, 105017c55decSDaniel P. Berrange sizeof(su->sun_path)); 105117c55decSDaniel P. Berrange } 105217c55decSDaniel P. Berrange 105317c55decSDaniel P. Berrange return addr; 105417c55decSDaniel P. Berrange } 105517c55decSDaniel P. Berrange #endif /* WIN32 */ 105617c55decSDaniel P. Berrange 1057559607eaSDaniel P. Berrange SocketAddress * 105817c55decSDaniel P. Berrange socket_sockaddr_to_address(struct sockaddr_storage *sa, 105917c55decSDaniel P. Berrange socklen_t salen, 106017c55decSDaniel P. Berrange Error **errp) 106117c55decSDaniel P. Berrange { 106217c55decSDaniel P. Berrange switch (sa->ss_family) { 106317c55decSDaniel P. Berrange case AF_INET: 106417c55decSDaniel P. Berrange case AF_INET6: 106517c55decSDaniel P. Berrange return socket_sockaddr_to_address_inet(sa, salen, errp); 106617c55decSDaniel P. Berrange 106717c55decSDaniel P. Berrange #ifndef WIN32 106817c55decSDaniel P. Berrange case AF_UNIX: 106917c55decSDaniel P. Berrange return socket_sockaddr_to_address_unix(sa, salen, errp); 107017c55decSDaniel P. Berrange #endif /* WIN32 */ 107117c55decSDaniel P. Berrange 107217c55decSDaniel P. Berrange default: 107317c55decSDaniel P. Berrange error_setg(errp, "socket family %d unsupported", 107417c55decSDaniel P. Berrange sa->ss_family); 107517c55decSDaniel P. Berrange return NULL; 107617c55decSDaniel P. Berrange } 107717c55decSDaniel P. Berrange return 0; 107817c55decSDaniel P. Berrange } 107917c55decSDaniel P. Berrange 108017c55decSDaniel P. Berrange 108117c55decSDaniel P. Berrange SocketAddress *socket_local_address(int fd, Error **errp) 108217c55decSDaniel P. Berrange { 108317c55decSDaniel P. Berrange struct sockaddr_storage ss; 108417c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 108517c55decSDaniel P. Berrange 108617c55decSDaniel P. Berrange if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) { 1087b16a44e1SDaniel P. Berrange error_setg_errno(errp, errno, "%s", 108817c55decSDaniel P. Berrange "Unable to query local socket address"); 108917c55decSDaniel P. Berrange return NULL; 109017c55decSDaniel P. Berrange } 109117c55decSDaniel P. Berrange 109217c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 109317c55decSDaniel P. Berrange } 109417c55decSDaniel P. Berrange 109517c55decSDaniel P. Berrange 109617c55decSDaniel P. Berrange SocketAddress *socket_remote_address(int fd, Error **errp) 109717c55decSDaniel P. Berrange { 109817c55decSDaniel P. Berrange struct sockaddr_storage ss; 109917c55decSDaniel P. Berrange socklen_t sslen = sizeof(ss); 110017c55decSDaniel P. Berrange 110117c55decSDaniel P. Berrange if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) { 1102b16a44e1SDaniel P. Berrange error_setg_errno(errp, errno, "%s", 110317c55decSDaniel P. Berrange "Unable to query remote socket address"); 110417c55decSDaniel P. Berrange return NULL; 110517c55decSDaniel P. Berrange } 110617c55decSDaniel P. Berrange 110717c55decSDaniel P. Berrange return socket_sockaddr_to_address(&ss, sslen, errp); 110817c55decSDaniel P. Berrange } 11092a8e21c7SDaniel P. Berrange 11102a8e21c7SDaniel P. Berrange 11112a8e21c7SDaniel P. Berrange void qapi_copy_SocketAddress(SocketAddress **p_dest, 11122a8e21c7SDaniel P. Berrange SocketAddress *src) 11132a8e21c7SDaniel P. Berrange { 11142a8e21c7SDaniel P. Berrange QmpOutputVisitor *qov; 11152a8e21c7SDaniel P. Berrange QmpInputVisitor *qiv; 11162a8e21c7SDaniel P. Berrange Visitor *ov, *iv; 11172a8e21c7SDaniel P. Berrange QObject *obj; 11182a8e21c7SDaniel P. Berrange 11192a8e21c7SDaniel P. Berrange *p_dest = NULL; 11202a8e21c7SDaniel P. Berrange 11212a8e21c7SDaniel P. Berrange qov = qmp_output_visitor_new(); 11222a8e21c7SDaniel P. Berrange ov = qmp_output_get_visitor(qov); 112351e72bc1SEric Blake visit_type_SocketAddress(ov, NULL, &src, &error_abort); 11242a8e21c7SDaniel P. Berrange obj = qmp_output_get_qobject(qov); 11252a8e21c7SDaniel P. Berrange qmp_output_visitor_cleanup(qov); 11262a8e21c7SDaniel P. Berrange if (!obj) { 11272a8e21c7SDaniel P. Berrange return; 11282a8e21c7SDaniel P. Berrange } 11292a8e21c7SDaniel P. Berrange 11302a8e21c7SDaniel P. Berrange qiv = qmp_input_visitor_new(obj); 11312a8e21c7SDaniel P. Berrange iv = qmp_input_get_visitor(qiv); 113251e72bc1SEric Blake visit_type_SocketAddress(iv, NULL, p_dest, &error_abort); 11332a8e21c7SDaniel P. Berrange qmp_input_visitor_cleanup(qiv); 11342a8e21c7SDaniel P. Berrange qobject_decref(obj); 11352a8e21c7SDaniel P. Berrange } 1136