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