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 qemu_setsockopt(slisten, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 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 qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 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 struct addrinfo *res, *e; 358 int sock = -1; 359 bool in_progress; 360 ConnectState *connect_state = NULL; 361 362 res = inet_parse_connect_opts(opts, errp); 363 if (!res) { 364 return -1; 365 } 366 367 if (callback != NULL) { 368 connect_state = g_malloc0(sizeof(*connect_state)); 369 connect_state->addr_list = res; 370 connect_state->callback = callback; 371 connect_state->opaque = opaque; 372 } 373 374 for (e = res; e != NULL; e = e->ai_next) { 375 if (error_is_set(errp)) { 376 error_free(*errp); 377 *errp = NULL; 378 } 379 if (connect_state != NULL) { 380 connect_state->current_addr = e; 381 } 382 sock = inet_connect_addr(e, &in_progress, connect_state, errp); 383 if (in_progress) { 384 return sock; 385 } else if (sock >= 0) { 386 /* non blocking socket immediate success, call callback */ 387 if (callback != NULL) { 388 callback(sock, opaque); 389 } 390 break; 391 } 392 } 393 g_free(connect_state); 394 freeaddrinfo(res); 395 return sock; 396 } 397 398 int inet_dgram_opts(QemuOpts *opts, Error **errp) 399 { 400 struct addrinfo ai, *peer = NULL, *local = NULL; 401 const char *addr; 402 const char *port; 403 int sock = -1, rc; 404 405 /* lookup peer addr */ 406 memset(&ai,0, sizeof(ai)); 407 ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; 408 ai.ai_family = PF_UNSPEC; 409 ai.ai_socktype = SOCK_DGRAM; 410 411 addr = qemu_opt_get(opts, "host"); 412 port = qemu_opt_get(opts, "port"); 413 if (addr == NULL || strlen(addr) == 0) { 414 addr = "localhost"; 415 } 416 if (port == NULL || strlen(port) == 0) { 417 error_setg(errp, "remote port not specified"); 418 return -1; 419 } 420 421 if (qemu_opt_get_bool(opts, "ipv4", 0)) 422 ai.ai_family = PF_INET; 423 if (qemu_opt_get_bool(opts, "ipv6", 0)) 424 ai.ai_family = PF_INET6; 425 426 if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) { 427 error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 428 gai_strerror(rc)); 429 return -1; 430 } 431 432 /* lookup local addr */ 433 memset(&ai,0, sizeof(ai)); 434 ai.ai_flags = AI_PASSIVE; 435 ai.ai_family = peer->ai_family; 436 ai.ai_socktype = SOCK_DGRAM; 437 438 addr = qemu_opt_get(opts, "localaddr"); 439 port = qemu_opt_get(opts, "localport"); 440 if (addr == NULL || strlen(addr) == 0) { 441 addr = NULL; 442 } 443 if (!port || strlen(port) == 0) 444 port = "0"; 445 446 if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) { 447 error_setg(errp, "address resolution failed for %s:%s: %s", addr, port, 448 gai_strerror(rc)); 449 goto err; 450 } 451 452 /* create socket */ 453 sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); 454 if (sock < 0) { 455 error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); 456 goto err; 457 } 458 qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 459 460 /* bind socket */ 461 if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { 462 error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); 463 goto err; 464 } 465 466 /* connect to peer */ 467 if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { 468 error_set_errno(errp, errno, QERR_SOCKET_CONNECT_FAILED); 469 goto err; 470 } 471 472 freeaddrinfo(local); 473 freeaddrinfo(peer); 474 return sock; 475 476 err: 477 if (-1 != sock) 478 closesocket(sock); 479 if (local) 480 freeaddrinfo(local); 481 if (peer) 482 freeaddrinfo(peer); 483 return -1; 484 } 485 486 /* compatibility wrapper */ 487 InetSocketAddress *inet_parse(const char *str, Error **errp) 488 { 489 InetSocketAddress *addr; 490 const char *optstr, *h; 491 char host[64]; 492 char port[33]; 493 int to; 494 int pos; 495 496 addr = g_new0(InetSocketAddress, 1); 497 498 /* parse address */ 499 if (str[0] == ':') { 500 /* no host given */ 501 host[0] = '\0'; 502 if (1 != sscanf(str, ":%32[^,]%n", port, &pos)) { 503 error_setg(errp, "error parsing port in address '%s'", str); 504 goto fail; 505 } 506 } else if (str[0] == '[') { 507 /* IPv6 addr */ 508 if (2 != sscanf(str, "[%64[^]]]:%32[^,]%n", host, port, &pos)) { 509 error_setg(errp, "error parsing IPv6 address '%s'", str); 510 goto fail; 511 } 512 addr->ipv6 = addr->has_ipv6 = true; 513 } else { 514 /* hostname or IPv4 addr */ 515 if (2 != sscanf(str, "%64[^:]:%32[^,]%n", host, port, &pos)) { 516 error_setg(errp, "error parsing address '%s'", str); 517 goto fail; 518 } 519 if (host[strspn(host, "0123456789.")] == '\0') { 520 addr->ipv4 = addr->has_ipv4 = true; 521 } 522 } 523 524 addr->host = g_strdup(host); 525 addr->port = g_strdup(port); 526 527 /* parse options */ 528 optstr = str + pos; 529 h = strstr(optstr, ",to="); 530 if (h) { 531 h += 4; 532 if (sscanf(h, "%d%n", &to, &pos) != 1 || 533 (h[pos] != '\0' && h[pos] != ',')) { 534 error_setg(errp, "error parsing to= argument"); 535 goto fail; 536 } 537 addr->has_to = true; 538 addr->to = to; 539 } 540 if (strstr(optstr, ",ipv4")) { 541 addr->ipv4 = addr->has_ipv4 = true; 542 } 543 if (strstr(optstr, ",ipv6")) { 544 addr->ipv6 = addr->has_ipv6 = true; 545 } 546 return addr; 547 548 fail: 549 qapi_free_InetSocketAddress(addr); 550 return NULL; 551 } 552 553 static void inet_addr_to_opts(QemuOpts *opts, const InetSocketAddress *addr) 554 { 555 bool ipv4 = addr->ipv4 || !addr->has_ipv4; 556 bool ipv6 = addr->ipv6 || !addr->has_ipv6; 557 558 if (!ipv4 || !ipv6) { 559 qemu_opt_set_bool(opts, "ipv4", ipv4); 560 qemu_opt_set_bool(opts, "ipv6", ipv6); 561 } 562 if (addr->has_to) { 563 char to[20]; 564 snprintf(to, sizeof(to), "%d", addr->to); 565 qemu_opt_set(opts, "to", to); 566 } 567 qemu_opt_set(opts, "host", addr->host); 568 qemu_opt_set(opts, "port", addr->port); 569 } 570 571 int inet_listen(const char *str, char *ostr, int olen, 572 int socktype, int port_offset, Error **errp) 573 { 574 QemuOpts *opts; 575 char *optstr; 576 int sock = -1; 577 InetSocketAddress *addr; 578 579 addr = inet_parse(str, errp); 580 if (addr != NULL) { 581 opts = qemu_opts_create_nofail(&socket_optslist); 582 inet_addr_to_opts(opts, addr); 583 qapi_free_InetSocketAddress(addr); 584 sock = inet_listen_opts(opts, port_offset, errp); 585 if (sock != -1 && ostr) { 586 optstr = strchr(str, ','); 587 if (qemu_opt_get_bool(opts, "ipv6", 0)) { 588 snprintf(ostr, olen, "[%s]:%s%s", 589 qemu_opt_get(opts, "host"), 590 qemu_opt_get(opts, "port"), 591 optstr ? optstr : ""); 592 } else { 593 snprintf(ostr, olen, "%s:%s%s", 594 qemu_opt_get(opts, "host"), 595 qemu_opt_get(opts, "port"), 596 optstr ? optstr : ""); 597 } 598 } 599 qemu_opts_del(opts); 600 } 601 return sock; 602 } 603 604 /** 605 * Create a blocking socket and connect it to an address. 606 * 607 * @str: address string 608 * @errp: set in case of an error 609 * 610 * Returns -1 in case of error, file descriptor on success 611 **/ 612 int inet_connect(const char *str, Error **errp) 613 { 614 QemuOpts *opts; 615 int sock = -1; 616 InetSocketAddress *addr; 617 618 addr = inet_parse(str, errp); 619 if (addr != NULL) { 620 opts = qemu_opts_create_nofail(&socket_optslist); 621 inet_addr_to_opts(opts, addr); 622 qapi_free_InetSocketAddress(addr); 623 sock = inet_connect_opts(opts, errp, NULL, NULL); 624 qemu_opts_del(opts); 625 } 626 return sock; 627 } 628 629 /** 630 * Create a non-blocking socket and connect it to an address. 631 * Calls the callback function with fd in case of success or -1 in case of 632 * error. 633 * 634 * @str: address string 635 * @callback: callback function that is called when connect completes, 636 * cannot be NULL. 637 * @opaque: opaque for callback function 638 * @errp: set in case of an error 639 * 640 * Returns: -1 on immediate error, file descriptor on success. 641 **/ 642 int inet_nonblocking_connect(const char *str, 643 NonBlockingConnectHandler *callback, 644 void *opaque, Error **errp) 645 { 646 QemuOpts *opts; 647 int sock = -1; 648 InetSocketAddress *addr; 649 650 g_assert(callback != NULL); 651 652 addr = inet_parse(str, errp); 653 if (addr != NULL) { 654 opts = qemu_opts_create_nofail(&socket_optslist); 655 inet_addr_to_opts(opts, addr); 656 qapi_free_InetSocketAddress(addr); 657 sock = inet_connect_opts(opts, errp, callback, opaque); 658 qemu_opts_del(opts); 659 } 660 return sock; 661 } 662 663 #ifndef _WIN32 664 665 int unix_listen_opts(QemuOpts *opts, Error **errp) 666 { 667 struct sockaddr_un un; 668 const char *path = qemu_opt_get(opts, "path"); 669 int sock, fd; 670 671 sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 672 if (sock < 0) { 673 error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); 674 return -1; 675 } 676 677 memset(&un, 0, sizeof(un)); 678 un.sun_family = AF_UNIX; 679 if (path && strlen(path)) { 680 snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); 681 } else { 682 char *tmpdir = getenv("TMPDIR"); 683 snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX", 684 tmpdir ? tmpdir : "/tmp"); 685 /* 686 * This dummy fd usage silences the mktemp() unsecure warning. 687 * Using mkstemp() doesn't make things more secure here 688 * though. bind() complains about existing files, so we have 689 * to unlink first and thus re-open the race window. The 690 * worst case possible is bind() failing, i.e. a DoS attack. 691 */ 692 fd = mkstemp(un.sun_path); close(fd); 693 qemu_opt_set(opts, "path", un.sun_path); 694 } 695 696 unlink(un.sun_path); 697 if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { 698 error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED); 699 goto err; 700 } 701 if (listen(sock, 1) < 0) { 702 error_set_errno(errp, errno, QERR_SOCKET_LISTEN_FAILED); 703 goto err; 704 } 705 706 return sock; 707 708 err: 709 closesocket(sock); 710 return -1; 711 } 712 713 int unix_connect_opts(QemuOpts *opts, Error **errp, 714 NonBlockingConnectHandler *callback, void *opaque) 715 { 716 struct sockaddr_un un; 717 const char *path = qemu_opt_get(opts, "path"); 718 ConnectState *connect_state = NULL; 719 int sock, rc; 720 721 if (NULL == path) { 722 error_setg(errp, "unix connect: no path specified"); 723 return -1; 724 } 725 726 sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); 727 if (sock < 0) { 728 error_set_errno(errp, errno, QERR_SOCKET_CREATE_FAILED); 729 return -1; 730 } 731 if (callback != NULL) { 732 connect_state = g_malloc0(sizeof(*connect_state)); 733 connect_state->callback = callback; 734 connect_state->opaque = opaque; 735 qemu_set_nonblock(sock); 736 } 737 738 memset(&un, 0, sizeof(un)); 739 un.sun_family = AF_UNIX; 740 snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); 741 742 /* connect to peer */ 743 do { 744 rc = 0; 745 if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) { 746 rc = -socket_error(); 747 } 748 } while (rc == -EINTR); 749 750 if (connect_state != NULL && QEMU_SOCKET_RC_INPROGRESS(rc)) { 751 connect_state->fd = sock; 752 qemu_set_fd_handler2(sock, NULL, NULL, wait_for_connect, 753 connect_state); 754 return sock; 755 } else if (rc >= 0) { 756 /* non blocking socket immediate success, call callback */ 757 if (callback != NULL) { 758 callback(sock, opaque); 759 } 760 } 761 762 if (rc < 0) { 763 error_set_errno(errp, -rc, QERR_SOCKET_CONNECT_FAILED); 764 close(sock); 765 sock = -1; 766 } 767 768 g_free(connect_state); 769 return sock; 770 } 771 772 #else 773 774 int unix_listen_opts(QemuOpts *opts, Error **errp) 775 { 776 error_setg(errp, "unix sockets are not available on windows"); 777 errno = ENOTSUP; 778 return -1; 779 } 780 781 int unix_connect_opts(QemuOpts *opts, Error **errp, 782 NonBlockingConnectHandler *callback, void *opaque) 783 { 784 error_setg(errp, "unix sockets are not available on windows"); 785 errno = ENOTSUP; 786 return -1; 787 } 788 #endif 789 790 /* compatibility wrapper */ 791 int unix_listen(const char *str, char *ostr, int olen, Error **errp) 792 { 793 QemuOpts *opts; 794 char *path, *optstr; 795 int sock, len; 796 797 opts = qemu_opts_create_nofail(&socket_optslist); 798 799 optstr = strchr(str, ','); 800 if (optstr) { 801 len = optstr - str; 802 if (len) { 803 path = g_malloc(len+1); 804 snprintf(path, len+1, "%.*s", len, str); 805 qemu_opt_set(opts, "path", path); 806 g_free(path); 807 } 808 } else { 809 qemu_opt_set(opts, "path", str); 810 } 811 812 sock = unix_listen_opts(opts, errp); 813 814 if (sock != -1 && ostr) 815 snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : ""); 816 qemu_opts_del(opts); 817 return sock; 818 } 819 820 int unix_connect(const char *path, Error **errp) 821 { 822 QemuOpts *opts; 823 int sock; 824 825 opts = qemu_opts_create_nofail(&socket_optslist); 826 qemu_opt_set(opts, "path", path); 827 sock = unix_connect_opts(opts, errp, NULL, NULL); 828 qemu_opts_del(opts); 829 return sock; 830 } 831 832 833 int unix_nonblocking_connect(const char *path, 834 NonBlockingConnectHandler *callback, 835 void *opaque, Error **errp) 836 { 837 QemuOpts *opts; 838 int sock = -1; 839 840 g_assert(callback != NULL); 841 842 opts = qemu_opts_create_nofail(&socket_optslist); 843 qemu_opt_set(opts, "path", path); 844 sock = unix_connect_opts(opts, errp, callback, opaque); 845 qemu_opts_del(opts); 846 return sock; 847 } 848 849 SocketAddress *socket_parse(const char *str, Error **errp) 850 { 851 SocketAddress *addr = NULL; 852 853 addr = g_new(SocketAddress, 1); 854 if (strstart(str, "unix:", NULL)) { 855 if (str[5] == '\0') { 856 error_setg(errp, "invalid Unix socket address"); 857 goto fail; 858 } else { 859 addr->kind = SOCKET_ADDRESS_KIND_UNIX; 860 addr->q_unix = g_new(UnixSocketAddress, 1); 861 addr->q_unix->path = g_strdup(str + 5); 862 } 863 } else if (strstart(str, "fd:", NULL)) { 864 if (str[3] == '\0') { 865 error_setg(errp, "invalid file descriptor address"); 866 goto fail; 867 } else { 868 addr->kind = SOCKET_ADDRESS_KIND_FD; 869 addr->fd = g_new(String, 1); 870 addr->fd->str = g_strdup(str + 3); 871 } 872 } else { 873 addr->kind = SOCKET_ADDRESS_KIND_INET; 874 addr->inet = g_new(InetSocketAddress, 1); 875 addr->inet = inet_parse(str, errp); 876 if (addr->inet == NULL) { 877 goto fail; 878 } 879 } 880 return addr; 881 882 fail: 883 qapi_free_SocketAddress(addr); 884 return NULL; 885 } 886 887 int socket_connect(SocketAddress *addr, Error **errp, 888 NonBlockingConnectHandler *callback, void *opaque) 889 { 890 QemuOpts *opts; 891 int fd; 892 893 opts = qemu_opts_create_nofail(&socket_optslist); 894 switch (addr->kind) { 895 case SOCKET_ADDRESS_KIND_INET: 896 inet_addr_to_opts(opts, addr->inet); 897 fd = inet_connect_opts(opts, errp, callback, opaque); 898 break; 899 900 case SOCKET_ADDRESS_KIND_UNIX: 901 qemu_opt_set(opts, "path", addr->q_unix->path); 902 fd = unix_connect_opts(opts, errp, callback, opaque); 903 break; 904 905 case SOCKET_ADDRESS_KIND_FD: 906 fd = monitor_get_fd(cur_mon, addr->fd->str, errp); 907 if (callback) { 908 qemu_set_nonblock(fd); 909 callback(fd, opaque); 910 } 911 break; 912 913 default: 914 abort(); 915 } 916 qemu_opts_del(opts); 917 return fd; 918 } 919 920 int socket_listen(SocketAddress *addr, Error **errp) 921 { 922 QemuOpts *opts; 923 int fd; 924 925 opts = qemu_opts_create_nofail(&socket_optslist); 926 switch (addr->kind) { 927 case SOCKET_ADDRESS_KIND_INET: 928 inet_addr_to_opts(opts, addr->inet); 929 fd = inet_listen_opts(opts, 0, errp); 930 break; 931 932 case SOCKET_ADDRESS_KIND_UNIX: 933 qemu_opt_set(opts, "path", addr->q_unix->path); 934 fd = unix_listen_opts(opts, errp); 935 break; 936 937 case SOCKET_ADDRESS_KIND_FD: 938 fd = monitor_get_fd(cur_mon, addr->fd->str, errp); 939 break; 940 941 default: 942 abort(); 943 } 944 qemu_opts_del(opts); 945 return fd; 946 } 947 948 int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp) 949 { 950 QemuOpts *opts; 951 int fd; 952 953 opts = qemu_opts_create_nofail(&socket_optslist); 954 switch (remote->kind) { 955 case SOCKET_ADDRESS_KIND_INET: 956 qemu_opt_set(opts, "host", remote->inet->host); 957 qemu_opt_set(opts, "port", remote->inet->port); 958 if (local) { 959 qemu_opt_set(opts, "localaddr", local->inet->host); 960 qemu_opt_set(opts, "localport", local->inet->port); 961 } 962 fd = inet_dgram_opts(opts, errp); 963 break; 964 965 default: 966 error_setg(errp, "socket type unsupported for datagram"); 967 return -1; 968 } 969 qemu_opts_del(opts); 970 return fd; 971 } 972