1 /* 2 * inet and unix socket functions for qemu 3 * 4 * (c) 2008 Gerd Hoffmann <kraxel@redhat.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; under version 2 of the License. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * Contributions after 2012-01-13 are licensed under the terms of the 16 * GNU GPL, version 2 or (at your option) any later version. 17 */ 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <ctype.h> 22 #include <errno.h> 23 #include <unistd.h> 24 25 #include "monitor/monitor.h" 26 #include "qemu/sockets.h" 27 #include "qemu/main-loop.h" 28 29 #ifndef AI_ADDRCONFIG 30 # define AI_ADDRCONFIG 0 31 #endif 32 33 static const int on=1, off=0; 34 35 /* used temporarily until all users are converted to QemuOpts */ 36 QemuOptsList socket_optslist = { 37 .name = "socket", 38 .head = QTAILQ_HEAD_INITIALIZER(socket_optslist.head), 39 .desc = { 40 { 41 .name = "path", 42 .type = QEMU_OPT_STRING, 43 },{ 44 .name = "host", 45 .type = QEMU_OPT_STRING, 46 },{ 47 .name = "port", 48 .type = QEMU_OPT_STRING, 49 },{ 50 .name = "to", 51 .type = QEMU_OPT_NUMBER, 52 },{ 53 .name = "ipv4", 54 .type = QEMU_OPT_BOOL, 55 },{ 56 .name = "ipv6", 57 .type = QEMU_OPT_BOOL, 58 }, 59 { /* end if list */ } 60 }, 61 }; 62 63 static int inet_getport(struct addrinfo *e) 64 { 65 struct sockaddr_in *i4; 66 struct sockaddr_in6 *i6; 67 68 switch (e->ai_family) { 69 case PF_INET6: 70 i6 = (void*)e->ai_addr; 71 return ntohs(i6->sin6_port); 72 case PF_INET: 73 i4 = (void*)e->ai_addr; 74 return ntohs(i4->sin_port); 75 default: 76 return 0; 77 } 78 } 79 80 static void inet_setport(struct addrinfo *e, int port) 81 { 82 struct sockaddr_in *i4; 83 struct sockaddr_in6 *i6; 84 85 switch (e->ai_family) { 86 case PF_INET6: 87 i6 = (void*)e->ai_addr; 88 i6->sin6_port = htons(port); 89 break; 90 case PF_INET: 91 i4 = (void*)e->ai_addr; 92 i4->sin_port = htons(port); 93 break; 94 } 95 } 96 97 const char *inet_strfamily(int family) 98 { 99 switch (family) { 100 case PF_INET6: return "ipv6"; 101 case PF_INET: return "ipv4"; 102 case PF_UNIX: return "unix"; 103 } 104 return "unknown"; 105 } 106 107 int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp) 108 { 109 struct addrinfo ai,*res,*e; 110 const char *addr; 111 char port[33]; 112 char uaddr[INET6_ADDRSTRLEN+1]; 113 char uport[33]; 114 int slisten, rc, to, port_min, port_max, p; 115 116 memset(&ai,0, sizeof(ai)); 117 ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; 118 ai.ai_family = PF_UNSPEC; 119 ai.ai_socktype = SOCK_STREAM; 120 121 if ((qemu_opt_get(opts, "host") == NULL) || 122 (qemu_opt_get(opts, "port") == NULL)) { 123 error_setg(errp, "host and/or port not specified"); 124 return -1; 125 } 126 pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port")); 127 addr = qemu_opt_get(opts, "host"); 128 129 to = qemu_opt_get_number(opts, "to", 0); 130 if (qemu_opt_get_bool(opts, "ipv4", 0)) 131 ai.ai_family = PF_INET; 132 if (qemu_opt_get_bool(opts, "ipv6", 0)) 133 ai.ai_family = PF_INET6; 134 135 /* lookup */ 136 if (port_offset) 137 snprintf(port, sizeof(port), "%d", atoi(port) + port_offset); 138 rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res); 139 if (rc != 0) { 140 error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 141 gai_strerror(rc)); 142 return -1; 143 } 144 145 /* create socket + bind */ 146 for (e = res; e != NULL; e = e->ai_next) { 147 getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, 148 uaddr,INET6_ADDRSTRLEN,uport,32, 149 NI_NUMERICHOST | NI_NUMERICSERV); 150 slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); 151 if (slisten < 0) { 152 if (!e->ai_next) { 153 error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); 154 } 155 continue; 156 } 157 158 socket_set_fast_reuse(slisten); 159 #ifdef IPV6_V6ONLY 160 if (e->ai_family == PF_INET6) { 161 /* listen on both ipv4 and ipv6 */ 162 qemu_setsockopt(slisten, IPPROTO_IPV6, IPV6_V6ONLY, &off, 163 sizeof(off)); 164 } 165 #endif 166 167 port_min = inet_getport(e); 168 port_max = to ? to + port_offset : port_min; 169 for (p = port_min; p <= port_max; p++) { 170 inet_setport(e, p); 171 if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) { 172 goto listen; 173 } 174 if (p == port_max) { 175 if (!e->ai_next) { 176 error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); 177 } 178 } 179 } 180 closesocket(slisten); 181 } 182 freeaddrinfo(res); 183 return -1; 184 185 listen: 186 if (listen(slisten,1) != 0) { 187 error_set_errno(errp, errno, QERR_SOCKET_LISTEN_FAILED); 188 closesocket(slisten); 189 freeaddrinfo(res); 190 return -1; 191 } 192 snprintf(uport, sizeof(uport), "%d", inet_getport(e) - port_offset); 193 qemu_opt_set(opts, "host", uaddr); 194 qemu_opt_set(opts, "port", uport); 195 qemu_opt_set(opts, "ipv6", (e->ai_family == PF_INET6) ? "on" : "off"); 196 qemu_opt_set(opts, "ipv4", (e->ai_family != PF_INET6) ? "on" : "off"); 197 freeaddrinfo(res); 198 return slisten; 199 } 200 201 #ifdef _WIN32 202 #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 203 ((rc) == -EINPROGRESS || (rc) == -EWOULDBLOCK || (rc) == -WSAEALREADY) 204 #else 205 #define QEMU_SOCKET_RC_INPROGRESS(rc) \ 206 ((rc) == -EINPROGRESS) 207 #endif 208 209 /* Struct to store connect state for non blocking connect */ 210 typedef struct ConnectState { 211 int fd; 212 struct addrinfo *addr_list; 213 struct addrinfo *current_addr; 214 NonBlockingConnectHandler *callback; 215 void *opaque; 216 } ConnectState; 217 218 static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, 219 ConnectState *connect_state, Error **errp); 220 221 static void wait_for_connect(void *opaque) 222 { 223 ConnectState *s = opaque; 224 int val = 0, rc = 0; 225 socklen_t valsize = sizeof(val); 226 bool in_progress; 227 228 qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); 229 230 do { 231 rc = qemu_getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize); 232 } while (rc == -1 && socket_error() == EINTR); 233 234 /* update rc to contain error */ 235 if (!rc && val) { 236 rc = -1; 237 } 238 239 /* connect error */ 240 if (rc < 0) { 241 closesocket(s->fd); 242 s->fd = rc; 243 } 244 245 /* try to connect to the next address on the list */ 246 if (s->current_addr) { 247 while (s->current_addr->ai_next != NULL && s->fd < 0) { 248 s->current_addr = s->current_addr->ai_next; 249 s->fd = inet_connect_addr(s->current_addr, &in_progress, s, NULL); 250 /* connect in progress */ 251 if (in_progress) { 252 return; 253 } 254 } 255 256 freeaddrinfo(s->addr_list); 257 } 258 259 if (s->callback) { 260 s->callback(s->fd, s->opaque); 261 } 262 g_free(s); 263 } 264 265 static int inet_connect_addr(struct addrinfo *addr, bool *in_progress, 266 ConnectState *connect_state, Error **errp) 267 { 268 int sock, rc; 269 270 *in_progress = false; 271 272 sock = qemu_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); 273 if (sock < 0) { 274 error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); 275 return -1; 276 } 277 socket_set_fast_reuse(sock); 278 if (connect_state != NULL) { 279 qemu_set_nonblock(sock); 280 } 281 /* connect to peer */ 282 do { 283 rc = 0; 284 if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) { 285 rc = -socket_error(); 286 } 287 } while (rc == -EINTR); 288 289 if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 290 connect_state->fd = sock; 291 qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect, 292 connect_state); 293 *in_progress = true; 294 } else if (rc < 0) { 295 error_set_errno(errp, errno, QERR_SOCKET_CONNECT_FAILED); 296 closesocket(sock); 297 return -1; 298 } 299 return sock; 300 } 301 302 static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp) 303 { 304 struct addrinfo ai, *res; 305 int rc; 306 const char *addr; 307 const char *port; 308 309 memset(&ai, 0, sizeof(ai)); 310 311 ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; 312 ai.ai_family = PF_UNSPEC; 313 ai.ai_socktype = SOCK_STREAM; 314 315 addr = qemu_opt_get(opts, "host"); 316 port = qemu_opt_get(opts, "port"); 317 if (addr == NULL || port == NULL) { 318 error_setg(errp, "host and/or port not specified"); 319 return NULL; 320 } 321 322 if (qemu_opt_get_bool(opts, "ipv4", 0)) { 323 ai.ai_family = PF_INET; 324 } 325 if (qemu_opt_get_bool(opts, "ipv6", 0)) { 326 ai.ai_family = PF_INET6; 327 } 328 329 /* lookup */ 330 rc = getaddrinfo(addr, port, &ai, &res); 331 if (rc != 0) { 332 error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 333 gai_strerror(rc)); 334 return NULL; 335 } 336 return res; 337 } 338 339 /** 340 * Create a socket and connect it to an address. 341 * 342 * @opts: QEMU options, recognized parameters strings "host" and "port", 343 * bools "ipv4" and "ipv6". 344 * @errp: set on error 345 * @callback: callback function for non-blocking connect 346 * @opaque: opaque for callback function 347 * 348 * Returns: -1 on error, file descriptor on success. 349 * 350 * If @callback is non-null, the connect is non-blocking. If this 351 * function succeeds, callback will be called when the connection 352 * completes, with the file descriptor on success, or -1 on error. 353 */ 354 int inet_connect_opts(QemuOpts *opts, Error **errp, 355 NonBlockingConnectHandler *callback, void *opaque) 356 { 357 Error *local_err = NULL; 358 struct addrinfo *res, *e; 359 int sock = -1; 360 bool in_progress; 361 ConnectState *connect_state = NULL; 362 363 res = inet_parse_connect_opts(opts, errp); 364 if (!res) { 365 return -1; 366 } 367 368 if (callback != NULL) { 369 connect_state = g_malloc0(sizeof(*connect_state)); 370 connect_state->addr_list = res; 371 connect_state->callback = callback; 372 connect_state->opaque = opaque; 373 } 374 375 for (e = res; e != NULL; e = e->ai_next) { 376 error_free(local_err); 377 local_err = NULL; 378 if (connect_state != NULL) { 379 connect_state->current_addr = e; 380 } 381 sock = inet_connect_addr(e, &in_progress, connect_state, &local_err); 382 if (sock >= 0) { 383 break; 384 } 385 } 386 387 if (sock < 0) { 388 error_propagate(errp, local_err); 389 } else if (in_progress) { 390 /* wait_for_connect() will do the rest */ 391 return sock; 392 } else { 393 if (callback) { 394 callback(sock, opaque); 395 } 396 } 397 g_free(connect_state); 398 freeaddrinfo(res); 399 return sock; 400 } 401 402 int inet_dgram_opts(QemuOpts *opts, Error **errp) 403 { 404 struct addrinfo ai, *peer = NULL, *local = NULL; 405 const char *addr; 406 const char *port; 407 int sock = -1, rc; 408 409 /* lookup peer addr */ 410 memset(&ai,0, sizeof(ai)); 411 ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; 412 ai.ai_family = PF_UNSPEC; 413 ai.ai_socktype = SOCK_DGRAM; 414 415 addr = qemu_opt_get(opts, "host"); 416 port = qemu_opt_get(opts, "port"); 417 if (addr == NULL || strlen(addr) == 0) { 418 addr = "localhost"; 419 } 420 if (port == NULL || strlen(port) == 0) { 421 error_setg(errp, "remote port not specified"); 422 return -1; 423 } 424 425 if (qemu_opt_get_bool(opts, "ipv4", 0)) 426 ai.ai_family = PF_INET; 427 if (qemu_opt_get_bool(opts, "ipv6", 0)) 428 ai.ai_family = PF_INET6; 429 430 if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) { 431 error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 432 gai_strerror(rc)); 433 return -1; 434 } 435 436 /* lookup local addr */ 437 memset(&ai,0, sizeof(ai)); 438 ai.ai_flags = AI_PASSIVE; 439 ai.ai_family = peer->ai_family; 440 ai.ai_socktype = SOCK_DGRAM; 441 442 addr = qemu_opt_get(opts, "localaddr"); 443 port = qemu_opt_get(opts, "localport"); 444 if (addr == NULL || strlen(addr) == 0) { 445 addr = NULL; 446 } 447 if (!port || strlen(port) == 0) 448 port = "0"; 449 450 if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) { 451 error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 452 gai_strerror(rc)); 453 goto err; 454 } 455 456 /* create socket */ 457 sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); 458 if (sock < 0) { 459 error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); 460 goto err; 461 } 462 socket_set_fast_reuse(sock); 463 464 /* bind socket */ 465 if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { 466 error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); 467 goto err; 468 } 469 470 /* connect to peer */ 471 if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { 472 error_set_errno(errp, errno, QERR_SOCKET_CONNECT_FAILED); 473 goto err; 474 } 475 476 freeaddrinfo(local); 477 freeaddrinfo(peer); 478 return sock; 479 480 err: 481 if (-1 != sock) 482 closesocket(sock); 483 if (local) 484 freeaddrinfo(local); 485 if (peer) 486 freeaddrinfo(peer); 487 return -1; 488 } 489 490 /* compatibility wrapper */ 491 InetSocketAddress *inet_parse(const char *str, Error **errp) 492 { 493 InetSocketAddress *addr; 494 const char *optstr, *h; 495 char host[64]; 496 char port[33]; 497 int to; 498 int pos; 499 500 addr = g_new0(InetSocketAddress, 1); 501 502 /* parse address */ 503 if (str[0] == ':') { 504 /* no host given */ 505 host[0] = '\0'; 506 if (1 != sscanf(str, ":%32[^,]%n", port, &pos)) { 507 error_setg(errp, "error parsing port in address '%s'", str); 508 goto fail; 509 } 510 } else if (str[0] == '[') { 511 /* IPv6 addr */ 512 if (2 != sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos)) { 513 error_setg(errp, "error parsing IPv6 address '%s'", str); 514 goto fail; 515 } 516 addr->ipv6 = addr->has_ipv6 = true; 517 } else { 518 /* hostname or IPv4 addr */ 519 if (2 != sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos)) { 520 error_setg(errp, "error parsing address '%s'", str); 521 goto fail; 522 } 523 if (host[strspn(host, "0123456789.")] == '\0') { 524 addr->ipv4 = addr->has_ipv4 = true; 525 } 526 } 527 528 addr->host = g_strdup(host); 529 addr->port = g_strdup(port); 530 531 /* parse options */ 532 optstr = str + pos; 533 h = strstr(optstr, ",to="); 534 if (h) { 535 h += 4; 536 if (sscanf(h, "%d%n", &to, &pos) != 1 || 537 (h[pos] != '\0' && h[pos] != ',')) { 538 error_setg(errp, "error parsing to= argument"); 539 goto fail; 540 } 541 addr->has_to = true; 542 addr->to = to; 543 } 544 if (strstr(optstr, ",ipv4")) { 545 addr->ipv4 = addr->has_ipv4 = true; 546 } 547 if (strstr(optstr, ",ipv6")) { 548 addr->ipv6 = addr->has_ipv6 = true; 549 } 550 return addr; 551 552 fail: 553 qapi_free_InetSocketAddress(addr); 554 return NULL; 555 } 556 557 static void inet_addr_to_opts(QemuOpts *opts, const InetSocketAddress *addr) 558 { 559 bool ipv4 = addr->ipv4 || !addr->has_ipv4; 560 bool ipv6 = addr->ipv6 || !addr->has_ipv6; 561 562 if (!ipv4 || !ipv6) { 563 qemu_opt_set_bool(opts, "ipv4", ipv4); 564 qemu_opt_set_bool(opts, "ipv6", ipv6); 565 } 566 if (addr->has_to) { 567 char to[20]; 568 snprintf(to, sizeof(to), "%d", addr->to); 569 qemu_opt_set(opts, "to", to); 570 } 571 qemu_opt_set(opts, "host", addr->host); 572 qemu_opt_set(opts, "port", addr->port); 573 } 574 575 int inet_listen(const char *str, char *ostr, int olen, 576 int socktype, int port_offset, Error **errp) 577 { 578 QemuOpts *opts; 579 char *optstr; 580 int sock = -1; 581 InetSocketAddress *addr; 582 583 addr = inet_parse(str, errp); 584 if (addr != NULL) { 585 opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 586 inet_addr_to_opts(opts, addr); 587 qapi_free_InetSocketAddress(addr); 588 sock = inet_listen_opts(opts, port_offset, errp); 589 if (sock != -1 && ostr) { 590 optstr = strchr(str, ','); 591 if (qemu_opt_get_bool(opts, "ipv6", 0)) { 592 snprintf(ostr, olen, "[%s]:%s%s", 593 qemu_opt_get(opts, "host"), 594 qemu_opt_get(opts, "port"), 595 optstr ? optstr : ""); 596 } else { 597 snprintf(ostr, olen, "%s:%s%s", 598 qemu_opt_get(opts, "host"), 599 qemu_opt_get(opts, "port"), 600 optstr ? optstr : ""); 601 } 602 } 603 qemu_opts_del(opts); 604 } 605 return sock; 606 } 607 608 /** 609 * Create a blocking socket and connect it to an address. 610 * 611 * @str: address string 612 * @errp: set in case of an error 613 * 614 * Returns -1 in case of error, file descriptor on success 615 **/ 616 int inet_connect(const char *str, Error **errp) 617 { 618 QemuOpts *opts; 619 int sock = -1; 620 InetSocketAddress *addr; 621 622 addr = inet_parse(str, errp); 623 if (addr != NULL) { 624 opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 625 inet_addr_to_opts(opts, addr); 626 qapi_free_InetSocketAddress(addr); 627 sock = inet_connect_opts(opts, errp, NULL, NULL); 628 qemu_opts_del(opts); 629 } 630 return sock; 631 } 632 633 /** 634 * Create a non-blocking socket and connect it to an address. 635 * Calls the callback function with fd in case of success or -1 in case of 636 * error. 637 * 638 * @str: address string 639 * @callback: callback function that is called when connect completes, 640 * cannot be NULL. 641 * @opaque: opaque for callback function 642 * @errp: set in case of an error 643 * 644 * Returns: -1 on immediate error, file descriptor on success. 645 **/ 646 int inet_nonblocking_connect(const char *str, 647 NonBlockingConnectHandler *callback, 648 void *opaque, Error **errp) 649 { 650 QemuOpts *opts; 651 int sock = -1; 652 InetSocketAddress *addr; 653 654 g_assert(callback != NULL); 655 656 addr = inet_parse(str, errp); 657 if (addr != NULL) { 658 opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 659 inet_addr_to_opts(opts, addr); 660 qapi_free_InetSocketAddress(addr); 661 sock = inet_connect_opts(opts, errp, callback, opaque); 662 qemu_opts_del(opts); 663 } 664 return sock; 665 } 666 667 #ifndef _WIN32 668 669 int unix_listen_opts(QemuOpts *opts, Error **errp) 670 { 671 struct sockaddr_un un; 672 const char *path = qemu_opt_get(opts, "path"); 673 int sock, fd; 674 675 sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 676 if (sock < 0) { 677 error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); 678 return -1; 679 } 680 681 memset(&un, 0, sizeof(un)); 682 un.sun_family = AF_UNIX; 683 if (path && strlen(path)) { 684 snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); 685 } else { 686 char *tmpdir = getenv("TMPDIR"); 687 snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX", 688 tmpdir ? tmpdir : "/tmp"); 689 /* 690 * This dummy fd usage silences the mktemp() unsecure warning. 691 * Using mkstemp() doesn't make things more secure here 692 * though. bind() complains about existing files, so we have 693 * to unlink first and thus re-open the race window. The 694 * worst case possible is bind() failing, i.e. a DoS attack. 695 */ 696 fd = mkstemp(un.sun_path); close(fd); 697 qemu_opt_set(opts, "path", un.sun_path); 698 } 699 700 unlink(un.sun_path); 701 if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { 702 error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); 703 goto err; 704 } 705 if (listen(sock, 1) < 0) { 706 error_set_errno(errp, errno, QERR_SOCKET_LISTEN_FAILED); 707 goto err; 708 } 709 710 return sock; 711 712 err: 713 closesocket(sock); 714 return -1; 715 } 716 717 int unix_connect_opts(QemuOpts *opts, Error **errp, 718 NonBlockingConnectHandler *callback, void *opaque) 719 { 720 struct sockaddr_un un; 721 const char *path = qemu_opt_get(opts, "path"); 722 ConnectState *connect_state = NULL; 723 int sock, rc; 724 725 if (NULL == path) { 726 error_setg(errp, "unix connect: no path specified"); 727 return -1; 728 } 729 730 sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 731 if (sock < 0) { 732 error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); 733 return -1; 734 } 735 if (callback != NULL) { 736 connect_state = g_malloc0(sizeof(*connect_state)); 737 connect_state->callback = callback; 738 connect_state->opaque = opaque; 739 qemu_set_nonblock(sock); 740 } 741 742 memset(&un, 0, sizeof(un)); 743 un.sun_family = AF_UNIX; 744 snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); 745 746 /* connect to peer */ 747 do { 748 rc = 0; 749 if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { 750 rc = -socket_error(); 751 } 752 } while (rc == -EINTR); 753 754 if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 755 connect_state->fd = sock; 756 qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect, 757 connect_state); 758 return sock; 759 } else if (rc >= 0) { 760 /* non blocking socket immediate success, call callback */ 761 if (callback != NULL) { 762 callback(sock, opaque); 763 } 764 } 765 766 if (rc < 0) { 767 error_set_errno(errp, -rc, QERR_SOCKET_CONNECT_FAILED); 768 close(sock); 769 sock = -1; 770 } 771 772 g_free(connect_state); 773 return sock; 774 } 775 776 #else 777 778 int unix_listen_opts(QemuOpts *opts, Error **errp) 779 { 780 error_setg(errp, "unix sockets are not available on windows"); 781 errno = ENOTSUP; 782 return -1; 783 } 784 785 int unix_connect_opts(QemuOpts *opts, Error **errp, 786 NonBlockingConnectHandler *callback, void *opaque) 787 { 788 error_setg(errp, "unix sockets are not available on windows"); 789 errno = ENOTSUP; 790 return -1; 791 } 792 #endif 793 794 /* compatibility wrapper */ 795 int unix_listen(const char *str, char *ostr, int olen, Error **errp) 796 { 797 QemuOpts *opts; 798 char *path, *optstr; 799 int sock, len; 800 801 opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 802 803 optstr = strchr(str, ','); 804 if (optstr) { 805 len = optstr - str; 806 if (len) { 807 path = g_malloc(len+1); 808 snprintf(path, len+1, "%.*s", len, str); 809 qemu_opt_set(opts, "path", path); 810 g_free(path); 811 } 812 } else { 813 qemu_opt_set(opts, "path", str); 814 } 815 816 sock = unix_listen_opts(opts, errp); 817 818 if (sock != -1 && ostr) 819 snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : ""); 820 qemu_opts_del(opts); 821 return sock; 822 } 823 824 int unix_connect(const char *path, Error **errp) 825 { 826 QemuOpts *opts; 827 int sock; 828 829 opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 830 qemu_opt_set(opts, "path", path); 831 sock = unix_connect_opts(opts, errp, NULL, NULL); 832 qemu_opts_del(opts); 833 return sock; 834 } 835 836 837 int unix_nonblocking_connect(const char *path, 838 NonBlockingConnectHandler *callback, 839 void *opaque, Error **errp) 840 { 841 QemuOpts *opts; 842 int sock = -1; 843 844 g_assert(callback != NULL); 845 846 opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 847 qemu_opt_set(opts, "path", path); 848 sock = unix_connect_opts(opts, errp, callback, opaque); 849 qemu_opts_del(opts); 850 return sock; 851 } 852 853 SocketAddress *socket_parse(const char *str, Error **errp) 854 { 855 SocketAddress *addr; 856 857 addr = g_new0(SocketAddress, 1); 858 if (strstart(str, "unix:", NULL)) { 859 if (str[5] == '\0') { 860 error_setg(errp, "invalid Unix socket address"); 861 goto fail; 862 } else { 863 addr->kind = SOCKET_ADDRESS_KIND_UNIX; 864 addr->q_unix = g_new(UnixSocketAddress, 1); 865 addr->q_unix->path = g_strdup(str + 5); 866 } 867 } else if (strstart(str, "fd:", NULL)) { 868 if (str[3] == '\0') { 869 error_setg(errp, "invalid file descriptor address"); 870 goto fail; 871 } else { 872 addr->kind = SOCKET_ADDRESS_KIND_FD; 873 addr->fd = g_new(String, 1); 874 addr->fd->str = g_strdup(str + 3); 875 } 876 } else { 877 addr->kind = SOCKET_ADDRESS_KIND_INET; 878 addr->inet = inet_parse(str, errp); 879 if (addr->inet == NULL) { 880 goto fail; 881 } 882 } 883 return addr; 884 885 fail: 886 qapi_free_SocketAddress(addr); 887 return NULL; 888 } 889 890 int socket_connect(SocketAddress *addr, Error **errp, 891 NonBlockingConnectHandler *callback, void *opaque) 892 { 893 QemuOpts *opts; 894 int fd; 895 896 opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 897 switch (addr->kind) { 898 case SOCKET_ADDRESS_KIND_INET: 899 inet_addr_to_opts(opts, addr->inet); 900 fd = inet_connect_opts(opts, errp, callback, opaque); 901 break; 902 903 case SOCKET_ADDRESS_KIND_UNIX: 904 qemu_opt_set(opts, "path", addr->q_unix->path); 905 fd = unix_connect_opts(opts, errp, callback, opaque); 906 break; 907 908 case SOCKET_ADDRESS_KIND_FD: 909 fd = monitor_get_fd(cur_mon, addr->fd->str, errp); 910 if (fd >= 0 && callback) { 911 qemu_set_nonblock(fd); 912 callback(fd, opaque); 913 } 914 break; 915 916 default: 917 abort(); 918 } 919 qemu_opts_del(opts); 920 return fd; 921 } 922 923 int socket_listen(SocketAddress *addr, Error **errp) 924 { 925 QemuOpts *opts; 926 int fd; 927 928 opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 929 switch (addr->kind) { 930 case SOCKET_ADDRESS_KIND_INET: 931 inet_addr_to_opts(opts, addr->inet); 932 fd = inet_listen_opts(opts, 0, errp); 933 break; 934 935 case SOCKET_ADDRESS_KIND_UNIX: 936 qemu_opt_set(opts, "path", addr->q_unix->path); 937 fd = unix_listen_opts(opts, errp); 938 break; 939 940 case SOCKET_ADDRESS_KIND_FD: 941 fd = monitor_get_fd(cur_mon, addr->fd->str, errp); 942 break; 943 944 default: 945 abort(); 946 } 947 qemu_opts_del(opts); 948 return fd; 949 } 950 951 int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp) 952 { 953 QemuOpts *opts; 954 int fd; 955 956 opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); 957 switch (remote->kind) { 958 case SOCKET_ADDRESS_KIND_INET: 959 qemu_opt_set(opts, "host", remote->inet->host); 960 qemu_opt_set(opts, "port", remote->inet->port); 961 if (local) { 962 qemu_opt_set(opts, "localaddr", local->inet->host); 963 qemu_opt_set(opts, "localport", local->inet->port); 964 } 965 fd = inet_dgram_opts(opts, errp); 966 break; 967 968 default: 969 error_setg(errp, "socket type unsupported for datagram"); 970 fd = -1; 971 } 972 qemu_opts_del(opts); 973 return fd; 974 } 975