1 /* 2 * QEMU System Emulator 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu/osdep.h" 26 #include "chardev/char.h" 27 #include "io/channel-socket.h" 28 #include "io/channel-tls.h" 29 #include "io/channel-websock.h" 30 #include "io/net-listener.h" 31 #include "qemu/error-report.h" 32 #include "qemu/option.h" 33 #include "qapi/error.h" 34 #include "qapi/clone-visitor.h" 35 #include "qapi/qapi-visit-sockets.h" 36 37 #include "chardev/char-io.h" 38 39 /***********************************************************/ 40 /* TCP Net console */ 41 42 #define TCP_MAX_FDS 16 43 44 typedef struct { 45 char buf[21]; 46 size_t buflen; 47 } TCPChardevTelnetInit; 48 49 typedef enum { 50 TCP_CHARDEV_STATE_DISCONNECTED, 51 TCP_CHARDEV_STATE_CONNECTING, 52 TCP_CHARDEV_STATE_CONNECTED, 53 } TCPChardevState; 54 55 typedef struct { 56 Chardev parent; 57 QIOChannel *ioc; /* Client I/O channel */ 58 QIOChannelSocket *sioc; /* Client master channel */ 59 QIONetListener *listener; 60 GSource *hup_source; 61 QCryptoTLSCreds *tls_creds; 62 char *tls_authz; 63 TCPChardevState state; 64 int max_size; 65 int do_telnetopt; 66 int do_nodelay; 67 int *read_msgfds; 68 size_t read_msgfds_num; 69 int *write_msgfds; 70 size_t write_msgfds_num; 71 72 SocketAddress *addr; 73 bool is_listen; 74 bool is_telnet; 75 bool is_tn3270; 76 GSource *telnet_source; 77 TCPChardevTelnetInit *telnet_init; 78 79 bool is_websock; 80 81 GSource *reconnect_timer; 82 int64_t reconnect_time; 83 bool connect_err_reported; 84 85 QIOTask *connect_task; 86 } SocketChardev; 87 88 #define SOCKET_CHARDEV(obj) \ 89 OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET) 90 91 static gboolean socket_reconnect_timeout(gpointer opaque); 92 static void tcp_chr_telnet_init(Chardev *chr); 93 94 static void tcp_chr_change_state(SocketChardev *s, TCPChardevState state) 95 { 96 switch (state) { 97 case TCP_CHARDEV_STATE_DISCONNECTED: 98 break; 99 case TCP_CHARDEV_STATE_CONNECTING: 100 assert(s->state == TCP_CHARDEV_STATE_DISCONNECTED); 101 break; 102 case TCP_CHARDEV_STATE_CONNECTED: 103 assert(s->state == TCP_CHARDEV_STATE_CONNECTING); 104 break; 105 } 106 s->state = state; 107 } 108 109 static void tcp_chr_reconn_timer_cancel(SocketChardev *s) 110 { 111 if (s->reconnect_timer) { 112 g_source_destroy(s->reconnect_timer); 113 g_source_unref(s->reconnect_timer); 114 s->reconnect_timer = NULL; 115 } 116 } 117 118 static void qemu_chr_socket_restart_timer(Chardev *chr) 119 { 120 SocketChardev *s = SOCKET_CHARDEV(chr); 121 char *name; 122 123 assert(s->state == TCP_CHARDEV_STATE_DISCONNECTED); 124 assert(!s->reconnect_timer); 125 name = g_strdup_printf("chardev-socket-reconnect-%s", chr->label); 126 s->reconnect_timer = qemu_chr_timeout_add_ms(chr, 127 s->reconnect_time * 1000, 128 socket_reconnect_timeout, 129 chr); 130 g_source_set_name(s->reconnect_timer, name); 131 g_free(name); 132 } 133 134 static void check_report_connect_error(Chardev *chr, 135 Error *err) 136 { 137 SocketChardev *s = SOCKET_CHARDEV(chr); 138 139 if (!s->connect_err_reported) { 140 error_report("Unable to connect character device %s: %s", 141 chr->label, error_get_pretty(err)); 142 s->connect_err_reported = true; 143 } 144 qemu_chr_socket_restart_timer(chr); 145 } 146 147 static void tcp_chr_accept(QIONetListener *listener, 148 QIOChannelSocket *cioc, 149 void *opaque); 150 151 static int tcp_chr_read_poll(void *opaque); 152 static void tcp_chr_disconnect(Chardev *chr); 153 154 /* Called with chr_write_lock held. */ 155 static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len) 156 { 157 SocketChardev *s = SOCKET_CHARDEV(chr); 158 159 if (s->state == TCP_CHARDEV_STATE_CONNECTED) { 160 int ret = io_channel_send_full(s->ioc, buf, len, 161 s->write_msgfds, 162 s->write_msgfds_num); 163 164 /* free the written msgfds in any cases 165 * other than ret < 0 && errno == EAGAIN 166 */ 167 if (!(ret < 0 && EAGAIN == errno) 168 && s->write_msgfds_num) { 169 g_free(s->write_msgfds); 170 s->write_msgfds = 0; 171 s->write_msgfds_num = 0; 172 } 173 174 if (ret < 0 && errno != EAGAIN) { 175 if (tcp_chr_read_poll(chr) <= 0) { 176 tcp_chr_disconnect(chr); 177 return len; 178 } /* else let the read handler finish it properly */ 179 } 180 181 return ret; 182 } else { 183 /* XXX: indicate an error ? */ 184 return len; 185 } 186 } 187 188 static int tcp_chr_read_poll(void *opaque) 189 { 190 Chardev *chr = CHARDEV(opaque); 191 SocketChardev *s = SOCKET_CHARDEV(opaque); 192 if (s->state != TCP_CHARDEV_STATE_CONNECTED) { 193 return 0; 194 } 195 s->max_size = qemu_chr_be_can_write(chr); 196 return s->max_size; 197 } 198 199 static void tcp_chr_process_IAC_bytes(Chardev *chr, 200 SocketChardev *s, 201 uint8_t *buf, int *size) 202 { 203 /* Handle any telnet or tn3270 client's basic IAC options. 204 * For telnet options, it satisfies char by char mode with no echo. 205 * For tn3270 options, it satisfies binary mode with EOR. 206 * All IAC options will be removed from the buf and the do_opt 207 * pointer will be used to track the state of the width of the 208 * IAC information. 209 * 210 * RFC854: "All TELNET commands consist of at least a two byte sequence. 211 * The commands dealing with option negotiation are three byte sequences, 212 * the third byte being the code for the option referenced." 213 * "IAC BREAK", "IAC IP", "IAC NOP" and the double IAC are two bytes. 214 * "IAC SB", "IAC SE" and "IAC EOR" are saved to split up data boundary 215 * for tn3270. 216 * NOP, Break and Interrupt Process(IP) might be encountered during a TN3270 217 * session, and NOP and IP need to be done later. 218 */ 219 220 int i; 221 int j = 0; 222 223 for (i = 0; i < *size; i++) { 224 if (s->do_telnetopt > 1) { 225 if ((unsigned char)buf[i] == IAC && s->do_telnetopt == 2) { 226 /* Double IAC means send an IAC */ 227 if (j != i) { 228 buf[j] = buf[i]; 229 } 230 j++; 231 s->do_telnetopt = 1; 232 } else { 233 if ((unsigned char)buf[i] == IAC_BREAK 234 && s->do_telnetopt == 2) { 235 /* Handle IAC break commands by sending a serial break */ 236 qemu_chr_be_event(chr, CHR_EVENT_BREAK); 237 s->do_telnetopt++; 238 } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_EOR 239 || (unsigned char)buf[i] == IAC_SB 240 || (unsigned char)buf[i] == IAC_SE) 241 && s->do_telnetopt == 2) { 242 buf[j++] = IAC; 243 buf[j++] = buf[i]; 244 s->do_telnetopt++; 245 } else if (s->is_tn3270 && ((unsigned char)buf[i] == IAC_IP 246 || (unsigned char)buf[i] == IAC_NOP) 247 && s->do_telnetopt == 2) { 248 /* TODO: IP and NOP need to be implemented later. */ 249 s->do_telnetopt++; 250 } 251 s->do_telnetopt++; 252 } 253 if (s->do_telnetopt >= 4) { 254 s->do_telnetopt = 1; 255 } 256 } else { 257 if ((unsigned char)buf[i] == IAC) { 258 s->do_telnetopt = 2; 259 } else { 260 if (j != i) { 261 buf[j] = buf[i]; 262 } 263 j++; 264 } 265 } 266 } 267 *size = j; 268 } 269 270 static int tcp_get_msgfds(Chardev *chr, int *fds, int num) 271 { 272 SocketChardev *s = SOCKET_CHARDEV(chr); 273 274 int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num; 275 276 assert(num <= TCP_MAX_FDS); 277 278 if (to_copy) { 279 int i; 280 281 memcpy(fds, s->read_msgfds, to_copy * sizeof(int)); 282 283 /* Close unused fds */ 284 for (i = to_copy; i < s->read_msgfds_num; i++) { 285 close(s->read_msgfds[i]); 286 } 287 288 g_free(s->read_msgfds); 289 s->read_msgfds = 0; 290 s->read_msgfds_num = 0; 291 } 292 293 return to_copy; 294 } 295 296 static int tcp_set_msgfds(Chardev *chr, int *fds, int num) 297 { 298 SocketChardev *s = SOCKET_CHARDEV(chr); 299 300 /* clear old pending fd array */ 301 g_free(s->write_msgfds); 302 s->write_msgfds = NULL; 303 s->write_msgfds_num = 0; 304 305 if ((s->state != TCP_CHARDEV_STATE_CONNECTED) || 306 !qio_channel_has_feature(s->ioc, 307 QIO_CHANNEL_FEATURE_FD_PASS)) { 308 return -1; 309 } 310 311 if (num) { 312 s->write_msgfds = g_new(int, num); 313 memcpy(s->write_msgfds, fds, num * sizeof(int)); 314 } 315 316 s->write_msgfds_num = num; 317 318 return 0; 319 } 320 321 static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len) 322 { 323 SocketChardev *s = SOCKET_CHARDEV(chr); 324 struct iovec iov = { .iov_base = buf, .iov_len = len }; 325 int ret; 326 size_t i; 327 int *msgfds = NULL; 328 size_t msgfds_num = 0; 329 330 if (qio_channel_has_feature(s->ioc, QIO_CHANNEL_FEATURE_FD_PASS)) { 331 ret = qio_channel_readv_full(s->ioc, &iov, 1, 332 &msgfds, &msgfds_num, 333 NULL); 334 } else { 335 ret = qio_channel_readv_full(s->ioc, &iov, 1, 336 NULL, NULL, 337 NULL); 338 } 339 340 if (ret == QIO_CHANNEL_ERR_BLOCK) { 341 errno = EAGAIN; 342 ret = -1; 343 } else if (ret == -1) { 344 errno = EIO; 345 } 346 347 if (msgfds_num) { 348 /* close and clean read_msgfds */ 349 for (i = 0; i < s->read_msgfds_num; i++) { 350 close(s->read_msgfds[i]); 351 } 352 353 if (s->read_msgfds_num) { 354 g_free(s->read_msgfds); 355 } 356 357 s->read_msgfds = msgfds; 358 s->read_msgfds_num = msgfds_num; 359 } 360 361 for (i = 0; i < s->read_msgfds_num; i++) { 362 int fd = s->read_msgfds[i]; 363 if (fd < 0) { 364 continue; 365 } 366 367 /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */ 368 qemu_set_block(fd); 369 370 #ifndef MSG_CMSG_CLOEXEC 371 qemu_set_cloexec(fd); 372 #endif 373 } 374 375 return ret; 376 } 377 378 static GSource *tcp_chr_add_watch(Chardev *chr, GIOCondition cond) 379 { 380 SocketChardev *s = SOCKET_CHARDEV(chr); 381 return qio_channel_create_watch(s->ioc, cond); 382 } 383 384 static void remove_hup_source(SocketChardev *s) 385 { 386 if (s->hup_source != NULL) { 387 g_source_destroy(s->hup_source); 388 g_source_unref(s->hup_source); 389 s->hup_source = NULL; 390 } 391 } 392 393 static void tcp_chr_free_connection(Chardev *chr) 394 { 395 SocketChardev *s = SOCKET_CHARDEV(chr); 396 int i; 397 398 if (s->read_msgfds_num) { 399 for (i = 0; i < s->read_msgfds_num; i++) { 400 close(s->read_msgfds[i]); 401 } 402 g_free(s->read_msgfds); 403 s->read_msgfds = NULL; 404 s->read_msgfds_num = 0; 405 } 406 407 remove_hup_source(s); 408 409 tcp_set_msgfds(chr, NULL, 0); 410 remove_fd_in_watch(chr); 411 object_unref(OBJECT(s->sioc)); 412 s->sioc = NULL; 413 object_unref(OBJECT(s->ioc)); 414 s->ioc = NULL; 415 g_free(chr->filename); 416 chr->filename = NULL; 417 tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED); 418 } 419 420 static const char *qemu_chr_socket_protocol(SocketChardev *s) 421 { 422 if (s->is_telnet) { 423 return "telnet"; 424 } 425 return s->is_websock ? "websocket" : "tcp"; 426 } 427 428 static char *qemu_chr_socket_address(SocketChardev *s, const char *prefix) 429 { 430 switch (s->addr->type) { 431 case SOCKET_ADDRESS_TYPE_INET: 432 return g_strdup_printf("%s%s:%s:%s%s", prefix, 433 qemu_chr_socket_protocol(s), 434 s->addr->u.inet.host, 435 s->addr->u.inet.port, 436 s->is_listen ? ",server" : ""); 437 break; 438 case SOCKET_ADDRESS_TYPE_UNIX: 439 return g_strdup_printf("%sunix:%s%s", prefix, 440 s->addr->u.q_unix.path, 441 s->is_listen ? ",server" : ""); 442 break; 443 case SOCKET_ADDRESS_TYPE_FD: 444 return g_strdup_printf("%sfd:%s%s", prefix, s->addr->u.fd.str, 445 s->is_listen ? ",server" : ""); 446 break; 447 case SOCKET_ADDRESS_TYPE_VSOCK: 448 return g_strdup_printf("%svsock:%s:%s", prefix, 449 s->addr->u.vsock.cid, 450 s->addr->u.vsock.port); 451 default: 452 abort(); 453 } 454 } 455 456 static void update_disconnected_filename(SocketChardev *s) 457 { 458 Chardev *chr = CHARDEV(s); 459 460 g_free(chr->filename); 461 if (s->addr) { 462 chr->filename = qemu_chr_socket_address(s, "disconnected:"); 463 } else { 464 chr->filename = g_strdup("disconnected:socket"); 465 } 466 } 467 468 /* NB may be called even if tcp_chr_connect has not been 469 * reached, due to TLS or telnet initialization failure, 470 * so can *not* assume s->state == TCP_CHARDEV_STATE_CONNECTED 471 */ 472 static void tcp_chr_disconnect(Chardev *chr) 473 { 474 SocketChardev *s = SOCKET_CHARDEV(chr); 475 bool emit_close = s->state == TCP_CHARDEV_STATE_CONNECTED; 476 477 tcp_chr_free_connection(chr); 478 479 if (s->listener) { 480 qio_net_listener_set_client_func_full(s->listener, tcp_chr_accept, 481 chr, NULL, chr->gcontext); 482 } 483 update_disconnected_filename(s); 484 if (emit_close) { 485 qemu_chr_be_event(chr, CHR_EVENT_CLOSED); 486 } 487 if (s->reconnect_time) { 488 qemu_chr_socket_restart_timer(chr); 489 } 490 } 491 492 static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque) 493 { 494 Chardev *chr = CHARDEV(opaque); 495 SocketChardev *s = SOCKET_CHARDEV(opaque); 496 uint8_t buf[CHR_READ_BUF_LEN]; 497 int len, size; 498 499 if ((s->state != TCP_CHARDEV_STATE_CONNECTED) || 500 s->max_size <= 0) { 501 return TRUE; 502 } 503 len = sizeof(buf); 504 if (len > s->max_size) { 505 len = s->max_size; 506 } 507 size = tcp_chr_recv(chr, (void *)buf, len); 508 if (size == 0 || (size == -1 && errno != EAGAIN)) { 509 /* connection closed */ 510 tcp_chr_disconnect(chr); 511 } else if (size > 0) { 512 if (s->do_telnetopt) { 513 tcp_chr_process_IAC_bytes(chr, s, buf, &size); 514 } 515 if (size > 0) { 516 qemu_chr_be_write(chr, buf, size); 517 } 518 } 519 520 return TRUE; 521 } 522 523 static gboolean tcp_chr_hup(QIOChannel *channel, 524 GIOCondition cond, 525 void *opaque) 526 { 527 Chardev *chr = CHARDEV(opaque); 528 tcp_chr_disconnect(chr); 529 return G_SOURCE_REMOVE; 530 } 531 532 static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len) 533 { 534 SocketChardev *s = SOCKET_CHARDEV(chr); 535 int size; 536 537 if (s->state != TCP_CHARDEV_STATE_CONNECTED) { 538 return 0; 539 } 540 541 qio_channel_set_blocking(s->ioc, true, NULL); 542 size = tcp_chr_recv(chr, (void *) buf, len); 543 qio_channel_set_blocking(s->ioc, false, NULL); 544 if (size == 0) { 545 /* connection closed */ 546 tcp_chr_disconnect(chr); 547 } 548 549 return size; 550 } 551 552 static char *qemu_chr_compute_filename(SocketChardev *s) 553 { 554 struct sockaddr_storage *ss = &s->sioc->localAddr; 555 struct sockaddr_storage *ps = &s->sioc->remoteAddr; 556 socklen_t ss_len = s->sioc->localAddrLen; 557 socklen_t ps_len = s->sioc->remoteAddrLen; 558 char shost[NI_MAXHOST], sserv[NI_MAXSERV]; 559 char phost[NI_MAXHOST], pserv[NI_MAXSERV]; 560 const char *left = "", *right = ""; 561 562 switch (ss->ss_family) { 563 #ifndef _WIN32 564 case AF_UNIX: 565 return g_strdup_printf("unix:%s%s", 566 ((struct sockaddr_un *)(ss))->sun_path, 567 s->is_listen ? ",server" : ""); 568 #endif 569 case AF_INET6: 570 left = "["; 571 right = "]"; 572 /* fall through */ 573 case AF_INET: 574 getnameinfo((struct sockaddr *) ss, ss_len, shost, sizeof(shost), 575 sserv, sizeof(sserv), NI_NUMERICHOST | NI_NUMERICSERV); 576 getnameinfo((struct sockaddr *) ps, ps_len, phost, sizeof(phost), 577 pserv, sizeof(pserv), NI_NUMERICHOST | NI_NUMERICSERV); 578 return g_strdup_printf("%s:%s%s%s:%s%s <-> %s%s%s:%s", 579 qemu_chr_socket_protocol(s), 580 left, shost, right, sserv, 581 s->is_listen ? ",server" : "", 582 left, phost, right, pserv); 583 584 default: 585 return g_strdup_printf("unknown"); 586 } 587 } 588 589 static void update_ioc_handlers(SocketChardev *s) 590 { 591 Chardev *chr = CHARDEV(s); 592 593 if (s->state != TCP_CHARDEV_STATE_CONNECTED) { 594 return; 595 } 596 597 remove_fd_in_watch(chr); 598 chr->gsource = io_add_watch_poll(chr, s->ioc, 599 tcp_chr_read_poll, 600 tcp_chr_read, chr, 601 chr->gcontext); 602 603 remove_hup_source(s); 604 s->hup_source = qio_channel_create_watch(s->ioc, G_IO_HUP); 605 g_source_set_callback(s->hup_source, (GSourceFunc)tcp_chr_hup, 606 chr, NULL); 607 g_source_attach(s->hup_source, chr->gcontext); 608 } 609 610 static void tcp_chr_connect(void *opaque) 611 { 612 Chardev *chr = CHARDEV(opaque); 613 SocketChardev *s = SOCKET_CHARDEV(opaque); 614 615 g_free(chr->filename); 616 chr->filename = qemu_chr_compute_filename(s); 617 618 tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTED); 619 update_ioc_handlers(s); 620 qemu_chr_be_event(chr, CHR_EVENT_OPENED); 621 } 622 623 static void tcp_chr_telnet_destroy(SocketChardev *s) 624 { 625 if (s->telnet_source) { 626 g_source_destroy(s->telnet_source); 627 g_source_unref(s->telnet_source); 628 s->telnet_source = NULL; 629 } 630 } 631 632 static void tcp_chr_update_read_handler(Chardev *chr) 633 { 634 SocketChardev *s = SOCKET_CHARDEV(chr); 635 636 if (s->listener && s->state == TCP_CHARDEV_STATE_DISCONNECTED) { 637 /* 638 * It's possible that chardev context is changed in 639 * qemu_chr_be_update_read_handlers(). Reset it for QIO net 640 * listener if there is. 641 */ 642 qio_net_listener_set_client_func_full(s->listener, tcp_chr_accept, 643 chr, NULL, chr->gcontext); 644 } 645 646 if (s->telnet_source) { 647 tcp_chr_telnet_init(CHARDEV(s)); 648 } 649 650 update_ioc_handlers(s); 651 } 652 653 static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc, 654 GIOCondition cond G_GNUC_UNUSED, 655 gpointer user_data) 656 { 657 SocketChardev *s = user_data; 658 Chardev *chr = CHARDEV(s); 659 TCPChardevTelnetInit *init = s->telnet_init; 660 ssize_t ret; 661 662 assert(init); 663 664 ret = qio_channel_write(ioc, init->buf, init->buflen, NULL); 665 if (ret < 0) { 666 if (ret == QIO_CHANNEL_ERR_BLOCK) { 667 ret = 0; 668 } else { 669 tcp_chr_disconnect(chr); 670 goto end; 671 } 672 } 673 init->buflen -= ret; 674 675 if (init->buflen == 0) { 676 tcp_chr_connect(chr); 677 goto end; 678 } 679 680 memmove(init->buf, init->buf + ret, init->buflen); 681 682 return G_SOURCE_CONTINUE; 683 684 end: 685 g_free(s->telnet_init); 686 s->telnet_init = NULL; 687 g_source_unref(s->telnet_source); 688 s->telnet_source = NULL; 689 return G_SOURCE_REMOVE; 690 } 691 692 static void tcp_chr_telnet_init(Chardev *chr) 693 { 694 SocketChardev *s = SOCKET_CHARDEV(chr); 695 TCPChardevTelnetInit *init; 696 size_t n = 0; 697 698 /* Destroy existing task */ 699 tcp_chr_telnet_destroy(s); 700 701 if (s->telnet_init) { 702 /* We are possibly during a handshake already */ 703 goto cont; 704 } 705 706 s->telnet_init = g_new0(TCPChardevTelnetInit, 1); 707 init = s->telnet_init; 708 709 #define IACSET(x, a, b, c) \ 710 do { \ 711 x[n++] = a; \ 712 x[n++] = b; \ 713 x[n++] = c; \ 714 } while (0) 715 716 if (!s->is_tn3270) { 717 init->buflen = 12; 718 /* Prep the telnet negotion to put telnet in binary, 719 * no echo, single char mode */ 720 IACSET(init->buf, 0xff, 0xfb, 0x01); /* IAC WILL ECHO */ 721 IACSET(init->buf, 0xff, 0xfb, 0x03); /* IAC WILL Suppress go ahead */ 722 IACSET(init->buf, 0xff, 0xfb, 0x00); /* IAC WILL Binary */ 723 IACSET(init->buf, 0xff, 0xfd, 0x00); /* IAC DO Binary */ 724 } else { 725 init->buflen = 21; 726 /* Prep the TN3270 negotion based on RFC1576 */ 727 IACSET(init->buf, 0xff, 0xfd, 0x19); /* IAC DO EOR */ 728 IACSET(init->buf, 0xff, 0xfb, 0x19); /* IAC WILL EOR */ 729 IACSET(init->buf, 0xff, 0xfd, 0x00); /* IAC DO BINARY */ 730 IACSET(init->buf, 0xff, 0xfb, 0x00); /* IAC WILL BINARY */ 731 IACSET(init->buf, 0xff, 0xfd, 0x18); /* IAC DO TERMINAL TYPE */ 732 IACSET(init->buf, 0xff, 0xfa, 0x18); /* IAC SB TERMINAL TYPE */ 733 IACSET(init->buf, 0x01, 0xff, 0xf0); /* SEND IAC SE */ 734 } 735 736 #undef IACSET 737 738 cont: 739 s->telnet_source = qio_channel_add_watch_source(s->ioc, G_IO_OUT, 740 tcp_chr_telnet_init_io, 741 s, NULL, 742 chr->gcontext); 743 } 744 745 746 static void tcp_chr_websock_handshake(QIOTask *task, gpointer user_data) 747 { 748 Chardev *chr = user_data; 749 SocketChardev *s = user_data; 750 751 if (qio_task_propagate_error(task, NULL)) { 752 tcp_chr_disconnect(chr); 753 } else { 754 if (s->do_telnetopt) { 755 tcp_chr_telnet_init(chr); 756 } else { 757 tcp_chr_connect(chr); 758 } 759 } 760 } 761 762 763 static void tcp_chr_websock_init(Chardev *chr) 764 { 765 SocketChardev *s = SOCKET_CHARDEV(chr); 766 QIOChannelWebsock *wioc = NULL; 767 gchar *name; 768 769 wioc = qio_channel_websock_new_server(s->ioc); 770 771 name = g_strdup_printf("chardev-websocket-server-%s", chr->label); 772 qio_channel_set_name(QIO_CHANNEL(wioc), name); 773 g_free(name); 774 object_unref(OBJECT(s->ioc)); 775 s->ioc = QIO_CHANNEL(wioc); 776 777 qio_channel_websock_handshake(wioc, tcp_chr_websock_handshake, chr, NULL); 778 } 779 780 781 static void tcp_chr_tls_handshake(QIOTask *task, 782 gpointer user_data) 783 { 784 Chardev *chr = user_data; 785 SocketChardev *s = user_data; 786 787 if (qio_task_propagate_error(task, NULL)) { 788 tcp_chr_disconnect(chr); 789 } else { 790 if (s->is_websock) { 791 tcp_chr_websock_init(chr); 792 } else if (s->do_telnetopt) { 793 tcp_chr_telnet_init(chr); 794 } else { 795 tcp_chr_connect(chr); 796 } 797 } 798 } 799 800 801 static void tcp_chr_tls_init(Chardev *chr) 802 { 803 SocketChardev *s = SOCKET_CHARDEV(chr); 804 QIOChannelTLS *tioc; 805 Error *err = NULL; 806 gchar *name; 807 808 if (s->is_listen) { 809 tioc = qio_channel_tls_new_server( 810 s->ioc, s->tls_creds, 811 s->tls_authz, 812 &err); 813 } else { 814 tioc = qio_channel_tls_new_client( 815 s->ioc, s->tls_creds, 816 s->addr->u.inet.host, 817 &err); 818 } 819 if (tioc == NULL) { 820 error_free(err); 821 tcp_chr_disconnect(chr); 822 return; 823 } 824 name = g_strdup_printf("chardev-tls-%s-%s", 825 s->is_listen ? "server" : "client", 826 chr->label); 827 qio_channel_set_name(QIO_CHANNEL(tioc), name); 828 g_free(name); 829 object_unref(OBJECT(s->ioc)); 830 s->ioc = QIO_CHANNEL(tioc); 831 832 qio_channel_tls_handshake(tioc, 833 tcp_chr_tls_handshake, 834 chr, 835 NULL, 836 chr->gcontext); 837 } 838 839 840 static void tcp_chr_set_client_ioc_name(Chardev *chr, 841 QIOChannelSocket *sioc) 842 { 843 SocketChardev *s = SOCKET_CHARDEV(chr); 844 char *name; 845 name = g_strdup_printf("chardev-tcp-%s-%s", 846 s->is_listen ? "server" : "client", 847 chr->label); 848 qio_channel_set_name(QIO_CHANNEL(sioc), name); 849 g_free(name); 850 851 } 852 853 static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc) 854 { 855 SocketChardev *s = SOCKET_CHARDEV(chr); 856 857 if (s->state != TCP_CHARDEV_STATE_CONNECTING) { 858 return -1; 859 } 860 861 s->ioc = QIO_CHANNEL(sioc); 862 object_ref(OBJECT(sioc)); 863 s->sioc = sioc; 864 object_ref(OBJECT(sioc)); 865 866 qio_channel_set_blocking(s->ioc, false, NULL); 867 868 if (s->do_nodelay) { 869 qio_channel_set_delay(s->ioc, false); 870 } 871 if (s->listener) { 872 qio_net_listener_set_client_func_full(s->listener, NULL, NULL, 873 NULL, chr->gcontext); 874 } 875 876 if (s->tls_creds) { 877 tcp_chr_tls_init(chr); 878 } else if (s->is_websock) { 879 tcp_chr_websock_init(chr); 880 } else if (s->do_telnetopt) { 881 tcp_chr_telnet_init(chr); 882 } else { 883 tcp_chr_connect(chr); 884 } 885 886 return 0; 887 } 888 889 890 static int tcp_chr_add_client(Chardev *chr, int fd) 891 { 892 int ret; 893 QIOChannelSocket *sioc; 894 SocketChardev *s = SOCKET_CHARDEV(chr); 895 896 if (s->state != TCP_CHARDEV_STATE_DISCONNECTED) { 897 return -1; 898 } 899 900 sioc = qio_channel_socket_new_fd(fd, NULL); 901 if (!sioc) { 902 return -1; 903 } 904 tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING); 905 tcp_chr_set_client_ioc_name(chr, sioc); 906 ret = tcp_chr_new_client(chr, sioc); 907 object_unref(OBJECT(sioc)); 908 return ret; 909 } 910 911 static void tcp_chr_accept(QIONetListener *listener, 912 QIOChannelSocket *cioc, 913 void *opaque) 914 { 915 Chardev *chr = CHARDEV(opaque); 916 SocketChardev *s = SOCKET_CHARDEV(chr); 917 918 tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING); 919 tcp_chr_set_client_ioc_name(chr, cioc); 920 tcp_chr_new_client(chr, cioc); 921 } 922 923 924 static int tcp_chr_connect_client_sync(Chardev *chr, Error **errp) 925 { 926 SocketChardev *s = SOCKET_CHARDEV(chr); 927 QIOChannelSocket *sioc = qio_channel_socket_new(); 928 tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING); 929 tcp_chr_set_client_ioc_name(chr, sioc); 930 if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) { 931 tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED); 932 object_unref(OBJECT(sioc)); 933 return -1; 934 } 935 tcp_chr_new_client(chr, sioc); 936 object_unref(OBJECT(sioc)); 937 return 0; 938 } 939 940 941 static void tcp_chr_accept_server_sync(Chardev *chr) 942 { 943 SocketChardev *s = SOCKET_CHARDEV(chr); 944 QIOChannelSocket *sioc; 945 info_report("QEMU waiting for connection on: %s", 946 chr->filename); 947 tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING); 948 sioc = qio_net_listener_wait_client(s->listener); 949 tcp_chr_set_client_ioc_name(chr, sioc); 950 tcp_chr_new_client(chr, sioc); 951 object_unref(OBJECT(sioc)); 952 } 953 954 955 static int tcp_chr_wait_connected(Chardev *chr, Error **errp) 956 { 957 SocketChardev *s = SOCKET_CHARDEV(chr); 958 const char *opts[] = { "telnet", "tn3270", "websock", "tls-creds" }; 959 bool optset[] = { s->is_telnet, s->is_tn3270, s->is_websock, s->tls_creds }; 960 size_t i; 961 962 QEMU_BUILD_BUG_ON(G_N_ELEMENTS(opts) != G_N_ELEMENTS(optset)); 963 for (i = 0; i < G_N_ELEMENTS(opts); i++) { 964 if (optset[i]) { 965 error_setg(errp, 966 "'%s' option is incompatible with waiting for " 967 "connection completion", opts[i]); 968 return -1; 969 } 970 } 971 972 tcp_chr_reconn_timer_cancel(s); 973 974 /* 975 * We expect states to be as follows: 976 * 977 * - server 978 * - wait -> CONNECTED 979 * - nowait -> DISCONNECTED 980 * - client 981 * - reconnect == 0 -> CONNECTED 982 * - reconnect != 0 -> CONNECTING 983 * 984 */ 985 if (s->state == TCP_CHARDEV_STATE_CONNECTING) { 986 if (!s->connect_task) { 987 error_setg(errp, 988 "Unexpected 'connecting' state without connect task " 989 "while waiting for connection completion"); 990 return -1; 991 } 992 /* 993 * tcp_chr_wait_connected should only ever be run from the 994 * main loop thread associated with chr->gcontext, otherwise 995 * qio_task_wait_thread has a dangerous race condition with 996 * free'ing of the s->connect_task object. 997 * 998 * Acquiring the main context doesn't 100% prove we're in 999 * the main loop thread, but it does at least guarantee 1000 * that the main loop won't be executed by another thread 1001 * avoiding the race condition with the task idle callback. 1002 */ 1003 g_main_context_acquire(chr->gcontext); 1004 qio_task_wait_thread(s->connect_task); 1005 g_main_context_release(chr->gcontext); 1006 1007 /* 1008 * The completion callback (qemu_chr_socket_connected) for 1009 * s->connect_task should have set this to NULL by the time 1010 * qio_task_wait_thread has returned. 1011 */ 1012 assert(!s->connect_task); 1013 1014 /* 1015 * NB we are *not* guaranteed to have "s->state == ..CONNECTED" 1016 * at this point as this first connect may be failed, so 1017 * allow the next loop to run regardless. 1018 */ 1019 } 1020 1021 while (s->state != TCP_CHARDEV_STATE_CONNECTED) { 1022 if (s->is_listen) { 1023 tcp_chr_accept_server_sync(chr); 1024 } else { 1025 Error *err = NULL; 1026 if (tcp_chr_connect_client_sync(chr, &err) < 0) { 1027 if (s->reconnect_time) { 1028 error_free(err); 1029 g_usleep(s->reconnect_time * 1000ULL * 1000ULL); 1030 } else { 1031 error_propagate(errp, err); 1032 return -1; 1033 } 1034 } 1035 } 1036 } 1037 1038 return 0; 1039 } 1040 1041 static void char_socket_finalize(Object *obj) 1042 { 1043 Chardev *chr = CHARDEV(obj); 1044 SocketChardev *s = SOCKET_CHARDEV(obj); 1045 1046 tcp_chr_free_connection(chr); 1047 tcp_chr_reconn_timer_cancel(s); 1048 qapi_free_SocketAddress(s->addr); 1049 tcp_chr_telnet_destroy(s); 1050 g_free(s->telnet_init); 1051 if (s->listener) { 1052 qio_net_listener_set_client_func_full(s->listener, NULL, NULL, 1053 NULL, chr->gcontext); 1054 object_unref(OBJECT(s->listener)); 1055 } 1056 if (s->tls_creds) { 1057 object_unref(OBJECT(s->tls_creds)); 1058 } 1059 g_free(s->tls_authz); 1060 1061 qemu_chr_be_event(chr, CHR_EVENT_CLOSED); 1062 } 1063 1064 static void qemu_chr_socket_connected(QIOTask *task, void *opaque) 1065 { 1066 QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task)); 1067 Chardev *chr = CHARDEV(opaque); 1068 SocketChardev *s = SOCKET_CHARDEV(chr); 1069 Error *err = NULL; 1070 1071 s->connect_task = NULL; 1072 1073 if (qio_task_propagate_error(task, &err)) { 1074 tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED); 1075 check_report_connect_error(chr, err); 1076 error_free(err); 1077 goto cleanup; 1078 } 1079 1080 s->connect_err_reported = false; 1081 tcp_chr_new_client(chr, sioc); 1082 1083 cleanup: 1084 object_unref(OBJECT(sioc)); 1085 } 1086 1087 1088 static void tcp_chr_connect_client_task(QIOTask *task, 1089 gpointer opaque) 1090 { 1091 QIOChannelSocket *ioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task)); 1092 SocketAddress *addr = opaque; 1093 Error *err = NULL; 1094 1095 qio_channel_socket_connect_sync(ioc, addr, &err); 1096 1097 qio_task_set_error(task, err); 1098 } 1099 1100 1101 static void tcp_chr_connect_client_async(Chardev *chr) 1102 { 1103 SocketChardev *s = SOCKET_CHARDEV(chr); 1104 QIOChannelSocket *sioc; 1105 1106 tcp_chr_change_state(s, TCP_CHARDEV_STATE_CONNECTING); 1107 sioc = qio_channel_socket_new(); 1108 tcp_chr_set_client_ioc_name(chr, sioc); 1109 /* 1110 * Normally code would use the qio_channel_socket_connect_async 1111 * method which uses a QIOTask + qio_task_set_error internally 1112 * to avoid blocking. The tcp_chr_wait_connected method, however, 1113 * needs a way to synchronize with completion of the background 1114 * connect task which can't be done with the QIOChannelSocket 1115 * async APIs. Thus we must use QIOTask directly to implement 1116 * the non-blocking concept locally. 1117 */ 1118 s->connect_task = qio_task_new(OBJECT(sioc), 1119 qemu_chr_socket_connected, 1120 chr, NULL); 1121 qio_task_run_in_thread(s->connect_task, 1122 tcp_chr_connect_client_task, 1123 s->addr, 1124 NULL, 1125 chr->gcontext); 1126 } 1127 1128 static gboolean socket_reconnect_timeout(gpointer opaque) 1129 { 1130 Chardev *chr = CHARDEV(opaque); 1131 SocketChardev *s = SOCKET_CHARDEV(opaque); 1132 1133 g_source_unref(s->reconnect_timer); 1134 s->reconnect_timer = NULL; 1135 1136 if (chr->be_open) { 1137 return false; 1138 } 1139 1140 tcp_chr_connect_client_async(chr); 1141 1142 return false; 1143 } 1144 1145 1146 static int qmp_chardev_open_socket_server(Chardev *chr, 1147 bool is_telnet, 1148 bool is_waitconnect, 1149 Error **errp) 1150 { 1151 SocketChardev *s = SOCKET_CHARDEV(chr); 1152 char *name; 1153 if (is_telnet) { 1154 s->do_telnetopt = 1; 1155 } 1156 s->listener = qio_net_listener_new(); 1157 1158 name = g_strdup_printf("chardev-tcp-listener-%s", chr->label); 1159 qio_net_listener_set_name(s->listener, name); 1160 g_free(name); 1161 1162 if (qio_net_listener_open_sync(s->listener, s->addr, errp) < 0) { 1163 object_unref(OBJECT(s->listener)); 1164 s->listener = NULL; 1165 return -1; 1166 } 1167 1168 qapi_free_SocketAddress(s->addr); 1169 s->addr = socket_local_address(s->listener->sioc[0]->fd, errp); 1170 update_disconnected_filename(s); 1171 1172 if (is_waitconnect) { 1173 tcp_chr_accept_server_sync(chr); 1174 } else { 1175 qio_net_listener_set_client_func_full(s->listener, 1176 tcp_chr_accept, 1177 chr, NULL, 1178 chr->gcontext); 1179 } 1180 1181 return 0; 1182 } 1183 1184 1185 static int qmp_chardev_open_socket_client(Chardev *chr, 1186 int64_t reconnect, 1187 Error **errp) 1188 { 1189 SocketChardev *s = SOCKET_CHARDEV(chr); 1190 1191 if (reconnect > 0) { 1192 s->reconnect_time = reconnect; 1193 tcp_chr_connect_client_async(chr); 1194 return 0; 1195 } else { 1196 return tcp_chr_connect_client_sync(chr, errp); 1197 } 1198 } 1199 1200 1201 static bool qmp_chardev_validate_socket(ChardevSocket *sock, 1202 SocketAddress *addr, 1203 Error **errp) 1204 { 1205 /* Validate any options which have a dependency on address type */ 1206 switch (addr->type) { 1207 case SOCKET_ADDRESS_TYPE_FD: 1208 if (sock->has_reconnect) { 1209 error_setg(errp, 1210 "'reconnect' option is incompatible with " 1211 "'fd' address type"); 1212 return false; 1213 } 1214 if (sock->has_tls_creds && 1215 !(sock->has_server && sock->server)) { 1216 error_setg(errp, 1217 "'tls_creds' option is incompatible with " 1218 "'fd' address type as client"); 1219 return false; 1220 } 1221 break; 1222 1223 case SOCKET_ADDRESS_TYPE_UNIX: 1224 if (sock->has_tls_creds) { 1225 error_setg(errp, 1226 "'tls_creds' option is incompatible with " 1227 "'unix' address type"); 1228 return false; 1229 } 1230 break; 1231 1232 case SOCKET_ADDRESS_TYPE_INET: 1233 break; 1234 1235 case SOCKET_ADDRESS_TYPE_VSOCK: 1236 if (sock->has_tls_creds) { 1237 error_setg(errp, 1238 "'tls_creds' option is incompatible with " 1239 "'vsock' address type"); 1240 return false; 1241 } 1242 1243 default: 1244 break; 1245 } 1246 1247 if (sock->has_tls_authz && !sock->has_tls_creds) { 1248 error_setg(errp, "'tls_authz' option requires 'tls_creds' option"); 1249 return false; 1250 } 1251 1252 /* Validate any options which have a dependancy on client vs server */ 1253 if (!sock->has_server || sock->server) { 1254 if (sock->has_reconnect) { 1255 error_setg(errp, 1256 "'reconnect' option is incompatible with " 1257 "socket in server listen mode"); 1258 return false; 1259 } 1260 } else { 1261 if (sock->has_websocket && sock->websocket) { 1262 error_setg(errp, "%s", "Websocket client is not implemented"); 1263 return false; 1264 } 1265 if (sock->has_wait) { 1266 error_setg(errp, "%s", 1267 "'wait' option is incompatible with " 1268 "socket in client connect mode"); 1269 return false; 1270 } 1271 } 1272 1273 return true; 1274 } 1275 1276 1277 static void qmp_chardev_open_socket(Chardev *chr, 1278 ChardevBackend *backend, 1279 bool *be_opened, 1280 Error **errp) 1281 { 1282 SocketChardev *s = SOCKET_CHARDEV(chr); 1283 ChardevSocket *sock = backend->u.socket.data; 1284 bool do_nodelay = sock->has_nodelay ? sock->nodelay : false; 1285 bool is_listen = sock->has_server ? sock->server : true; 1286 bool is_telnet = sock->has_telnet ? sock->telnet : false; 1287 bool is_tn3270 = sock->has_tn3270 ? sock->tn3270 : false; 1288 bool is_waitconnect = sock->has_wait ? sock->wait : false; 1289 bool is_websock = sock->has_websocket ? sock->websocket : false; 1290 int64_t reconnect = sock->has_reconnect ? sock->reconnect : 0; 1291 SocketAddress *addr; 1292 1293 s->is_listen = is_listen; 1294 s->is_telnet = is_telnet; 1295 s->is_tn3270 = is_tn3270; 1296 s->is_websock = is_websock; 1297 s->do_nodelay = do_nodelay; 1298 if (sock->tls_creds) { 1299 Object *creds; 1300 creds = object_resolve_path_component( 1301 object_get_objects_root(), sock->tls_creds); 1302 if (!creds) { 1303 error_setg(errp, "No TLS credentials with id '%s'", 1304 sock->tls_creds); 1305 return; 1306 } 1307 s->tls_creds = (QCryptoTLSCreds *) 1308 object_dynamic_cast(creds, 1309 TYPE_QCRYPTO_TLS_CREDS); 1310 if (!s->tls_creds) { 1311 error_setg(errp, "Object with id '%s' is not TLS credentials", 1312 sock->tls_creds); 1313 return; 1314 } 1315 object_ref(OBJECT(s->tls_creds)); 1316 if (is_listen) { 1317 if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { 1318 error_setg(errp, "%s", 1319 "Expected TLS credentials for server endpoint"); 1320 return; 1321 } 1322 } else { 1323 if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) { 1324 error_setg(errp, "%s", 1325 "Expected TLS credentials for client endpoint"); 1326 return; 1327 } 1328 } 1329 } 1330 s->tls_authz = g_strdup(sock->tls_authz); 1331 1332 s->addr = addr = socket_address_flatten(sock->addr); 1333 1334 if (!qmp_chardev_validate_socket(sock, addr, errp)) { 1335 return; 1336 } 1337 1338 qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE); 1339 /* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */ 1340 if (addr->type == SOCKET_ADDRESS_TYPE_UNIX) { 1341 qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS); 1342 } 1343 1344 /* be isn't opened until we get a connection */ 1345 *be_opened = false; 1346 1347 update_disconnected_filename(s); 1348 1349 if (s->is_listen) { 1350 if (qmp_chardev_open_socket_server(chr, is_telnet || is_tn3270, 1351 is_waitconnect, errp) < 0) { 1352 return; 1353 } 1354 } else { 1355 if (qmp_chardev_open_socket_client(chr, reconnect, errp) < 0) { 1356 return; 1357 } 1358 } 1359 } 1360 1361 static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend, 1362 Error **errp) 1363 { 1364 const char *path = qemu_opt_get(opts, "path"); 1365 const char *host = qemu_opt_get(opts, "host"); 1366 const char *port = qemu_opt_get(opts, "port"); 1367 const char *fd = qemu_opt_get(opts, "fd"); 1368 SocketAddressLegacy *addr; 1369 ChardevSocket *sock; 1370 1371 if ((!!path + !!fd + !!host) != 1) { 1372 error_setg(errp, 1373 "Exactly one of 'path', 'fd' or 'host' required"); 1374 return; 1375 } 1376 1377 if (host && !port) { 1378 error_setg(errp, "chardev: socket: no port given"); 1379 return; 1380 } 1381 1382 backend->type = CHARDEV_BACKEND_KIND_SOCKET; 1383 sock = backend->u.socket.data = g_new0(ChardevSocket, 1); 1384 qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock)); 1385 1386 sock->has_nodelay = qemu_opt_get(opts, "delay"); 1387 sock->nodelay = !qemu_opt_get_bool(opts, "delay", true); 1388 /* 1389 * We have different default to QMP for 'server', hence 1390 * we can't just check for existence of 'server' 1391 */ 1392 sock->has_server = true; 1393 sock->server = qemu_opt_get_bool(opts, "server", false); 1394 sock->has_telnet = qemu_opt_get(opts, "telnet"); 1395 sock->telnet = qemu_opt_get_bool(opts, "telnet", false); 1396 sock->has_tn3270 = qemu_opt_get(opts, "tn3270"); 1397 sock->tn3270 = qemu_opt_get_bool(opts, "tn3270", false); 1398 sock->has_websocket = qemu_opt_get(opts, "websocket"); 1399 sock->websocket = qemu_opt_get_bool(opts, "websocket", false); 1400 /* 1401 * We have different default to QMP for 'wait' when 'server' 1402 * is set, hence we can't just check for existence of 'wait' 1403 */ 1404 sock->has_wait = qemu_opt_find(opts, "wait") || sock->server; 1405 sock->wait = qemu_opt_get_bool(opts, "wait", true); 1406 sock->has_reconnect = qemu_opt_find(opts, "reconnect"); 1407 sock->reconnect = qemu_opt_get_number(opts, "reconnect", 0); 1408 sock->has_tls_creds = qemu_opt_get(opts, "tls-creds"); 1409 sock->tls_creds = g_strdup(qemu_opt_get(opts, "tls-creds")); 1410 sock->has_tls_authz = qemu_opt_get(opts, "tls-authz"); 1411 sock->tls_authz = g_strdup(qemu_opt_get(opts, "tls-authz")); 1412 1413 addr = g_new0(SocketAddressLegacy, 1); 1414 if (path) { 1415 UnixSocketAddress *q_unix; 1416 addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX; 1417 q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1); 1418 q_unix->path = g_strdup(path); 1419 } else if (host) { 1420 addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET; 1421 addr->u.inet.data = g_new(InetSocketAddress, 1); 1422 *addr->u.inet.data = (InetSocketAddress) { 1423 .host = g_strdup(host), 1424 .port = g_strdup(port), 1425 .has_to = qemu_opt_get(opts, "to"), 1426 .to = qemu_opt_get_number(opts, "to", 0), 1427 .has_ipv4 = qemu_opt_get(opts, "ipv4"), 1428 .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0), 1429 .has_ipv6 = qemu_opt_get(opts, "ipv6"), 1430 .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0), 1431 }; 1432 } else if (fd) { 1433 addr->type = SOCKET_ADDRESS_LEGACY_KIND_FD; 1434 addr->u.fd.data = g_new(String, 1); 1435 addr->u.fd.data->str = g_strdup(fd); 1436 } else { 1437 g_assert_not_reached(); 1438 } 1439 sock->addr = addr; 1440 } 1441 1442 static void 1443 char_socket_get_addr(Object *obj, Visitor *v, const char *name, 1444 void *opaque, Error **errp) 1445 { 1446 SocketChardev *s = SOCKET_CHARDEV(obj); 1447 1448 visit_type_SocketAddress(v, name, &s->addr, errp); 1449 } 1450 1451 static bool 1452 char_socket_get_connected(Object *obj, Error **errp) 1453 { 1454 SocketChardev *s = SOCKET_CHARDEV(obj); 1455 1456 return s->state == TCP_CHARDEV_STATE_CONNECTED; 1457 } 1458 1459 static void char_socket_class_init(ObjectClass *oc, void *data) 1460 { 1461 ChardevClass *cc = CHARDEV_CLASS(oc); 1462 1463 cc->parse = qemu_chr_parse_socket; 1464 cc->open = qmp_chardev_open_socket; 1465 cc->chr_wait_connected = tcp_chr_wait_connected; 1466 cc->chr_write = tcp_chr_write; 1467 cc->chr_sync_read = tcp_chr_sync_read; 1468 cc->chr_disconnect = tcp_chr_disconnect; 1469 cc->get_msgfds = tcp_get_msgfds; 1470 cc->set_msgfds = tcp_set_msgfds; 1471 cc->chr_add_client = tcp_chr_add_client; 1472 cc->chr_add_watch = tcp_chr_add_watch; 1473 cc->chr_update_read_handler = tcp_chr_update_read_handler; 1474 1475 object_class_property_add(oc, "addr", "SocketAddress", 1476 char_socket_get_addr, NULL, 1477 NULL, NULL, &error_abort); 1478 1479 object_class_property_add_bool(oc, "connected", char_socket_get_connected, 1480 NULL, &error_abort); 1481 } 1482 1483 static const TypeInfo char_socket_type_info = { 1484 .name = TYPE_CHARDEV_SOCKET, 1485 .parent = TYPE_CHARDEV, 1486 .instance_size = sizeof(SocketChardev), 1487 .instance_finalize = char_socket_finalize, 1488 .class_init = char_socket_class_init, 1489 }; 1490 1491 static void register_types(void) 1492 { 1493 type_register_static(&char_socket_type_info); 1494 } 1495 1496 type_init(register_types); 1497