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/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
  44typedef struct {
  45    char buf[21];
  46    size_t buflen;
  47} TCPChardevTelnetInit;
  48
  49typedef enum {
  50    TCP_CHARDEV_STATE_DISCONNECTED,
  51    TCP_CHARDEV_STATE_CONNECTING,
  52    TCP_CHARDEV_STATE_CONNECTED,
  53} TCPChardevState;
  54
  55typedef 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
  91static gboolean socket_reconnect_timeout(gpointer opaque);
  92static void tcp_chr_telnet_init(Chardev *chr);
  93
  94static 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
 109static 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
 118static 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
 134static 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
 147static void tcp_chr_accept(QIONetListener *listener,
 148                           QIOChannelSocket *cioc,
 149                           void *opaque);
 150
 151static int tcp_chr_read_poll(void *opaque);
 152static void tcp_chr_disconnect(Chardev *chr);
 153
 154/* Called with chr_write_lock held.  */
 155static 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
 188static 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
 199static 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
 270static 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
 296static 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
 321static 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
 378static 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
 384static 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
 393static 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
 420static 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
 428static 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
 456static 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 */
 472static 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
 492static 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
 523static 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
 532static 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
 552static 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
 589static 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
 610static 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
 623static 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
 632static 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
 653static 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
 684end:
 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
 692static 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
 738cont:
 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
 746static 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
 763static 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
 781static 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
 801static 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
 840static 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
 853static 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
 890static 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
 911static 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
 924static 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
 941static 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
 955static 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
1041static 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
1064static 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
1083cleanup:
1084    object_unref(OBJECT(sioc));
1085}
1086
1087
1088static 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
1101static 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
1128static 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
1146static 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
1185static 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
1201static 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            warn_report("'wait' option is deprecated with "
1267                        "socket in client connect mode");
1268            if (sock->wait) {
1269                error_setg(errp, "%s",
1270                           "'wait' option is incompatible with "
1271                           "socket in client connect mode");
1272                return false;
1273            }
1274        }
1275    }
1276
1277    return true;
1278}
1279
1280
1281static void qmp_chardev_open_socket(Chardev *chr,
1282                                    ChardevBackend *backend,
1283                                    bool *be_opened,
1284                                    Error **errp)
1285{
1286    SocketChardev *s = SOCKET_CHARDEV(chr);
1287    ChardevSocket *sock = backend->u.socket.data;
1288    bool do_nodelay     = sock->has_nodelay ? sock->nodelay : false;
1289    bool is_listen      = sock->has_server  ? sock->server  : true;
1290    bool is_telnet      = sock->has_telnet  ? sock->telnet  : false;
1291    bool is_tn3270      = sock->has_tn3270  ? sock->tn3270  : false;
1292    bool is_waitconnect = sock->has_wait    ? sock->wait    : false;
1293    bool is_websock     = sock->has_websocket ? sock->websocket : false;
1294    int64_t reconnect   = sock->has_reconnect ? sock->reconnect : 0;
1295    SocketAddress *addr;
1296
1297    s->is_listen = is_listen;
1298    s->is_telnet = is_telnet;
1299    s->is_tn3270 = is_tn3270;
1300    s->is_websock = is_websock;
1301    s->do_nodelay = do_nodelay;
1302    if (sock->tls_creds) {
1303        Object *creds;
1304        creds = object_resolve_path_component(
1305            object_get_objects_root(), sock->tls_creds);
1306        if (!creds) {
1307            error_setg(errp, "No TLS credentials with id '%s'",
1308                       sock->tls_creds);
1309            return;
1310        }
1311        s->tls_creds = (QCryptoTLSCreds *)
1312            object_dynamic_cast(creds,
1313                                TYPE_QCRYPTO_TLS_CREDS);
1314        if (!s->tls_creds) {
1315            error_setg(errp, "Object with id '%s' is not TLS credentials",
1316                       sock->tls_creds);
1317            return;
1318        }
1319        object_ref(OBJECT(s->tls_creds));
1320        if (is_listen) {
1321            if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
1322                error_setg(errp, "%s",
1323                           "Expected TLS credentials for server endpoint");
1324                return;
1325            }
1326        } else {
1327            if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
1328                error_setg(errp, "%s",
1329                           "Expected TLS credentials for client endpoint");
1330                return;
1331            }
1332        }
1333    }
1334    s->tls_authz = g_strdup(sock->tls_authz);
1335
1336    s->addr = addr = socket_address_flatten(sock->addr);
1337
1338    if (!qmp_chardev_validate_socket(sock, addr, errp)) {
1339        return;
1340    }
1341
1342    qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE);
1343    /* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */
1344    if (addr->type == SOCKET_ADDRESS_TYPE_UNIX) {
1345        qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS);
1346    }
1347
1348    /* be isn't opened until we get a connection */
1349    *be_opened = false;
1350
1351    update_disconnected_filename(s);
1352
1353    if (s->is_listen) {
1354        if (qmp_chardev_open_socket_server(chr, is_telnet || is_tn3270,
1355                                           is_waitconnect, errp) < 0) {
1356            return;
1357        }
1358    } else {
1359        if (qmp_chardev_open_socket_client(chr, reconnect, errp) < 0) {
1360            return;
1361        }
1362    }
1363}
1364
1365static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
1366                                  Error **errp)
1367{
1368    const char *path = qemu_opt_get(opts, "path");
1369    const char *host = qemu_opt_get(opts, "host");
1370    const char *port = qemu_opt_get(opts, "port");
1371    const char *fd = qemu_opt_get(opts, "fd");
1372    SocketAddressLegacy *addr;
1373    ChardevSocket *sock;
1374
1375    if ((!!path + !!fd + !!host) != 1) {
1376        error_setg(errp,
1377                   "Exactly one of 'path', 'fd' or 'host' required");
1378        return;
1379    }
1380
1381    if (host && !port) {
1382        error_setg(errp, "chardev: socket: no port given");
1383        return;
1384    }
1385
1386    backend->type = CHARDEV_BACKEND_KIND_SOCKET;
1387    sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
1388    qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
1389
1390    sock->has_nodelay = qemu_opt_get(opts, "delay");
1391    sock->nodelay = !qemu_opt_get_bool(opts, "delay", true);
1392    /*
1393     * We have different default to QMP for 'server', hence
1394     * we can't just check for existence of 'server'
1395     */
1396    sock->has_server = true;
1397    sock->server = qemu_opt_get_bool(opts, "server", false);
1398    sock->has_telnet = qemu_opt_get(opts, "telnet");
1399    sock->telnet = qemu_opt_get_bool(opts, "telnet", false);
1400    sock->has_tn3270 = qemu_opt_get(opts, "tn3270");
1401    sock->tn3270 = qemu_opt_get_bool(opts, "tn3270", false);
1402    sock->has_websocket = qemu_opt_get(opts, "websocket");
1403    sock->websocket = qemu_opt_get_bool(opts, "websocket", false);
1404    /*
1405     * We have different default to QMP for 'wait' when 'server'
1406     * is set, hence we can't just check for existence of 'wait'
1407     */
1408    sock->has_wait = qemu_opt_find(opts, "wait") || sock->server;
1409    sock->wait = qemu_opt_get_bool(opts, "wait", true);
1410    sock->has_reconnect = qemu_opt_find(opts, "reconnect");
1411    sock->reconnect = qemu_opt_get_number(opts, "reconnect", 0);
1412    sock->has_tls_creds = qemu_opt_get(opts, "tls-creds");
1413    sock->tls_creds = g_strdup(qemu_opt_get(opts, "tls-creds"));
1414    sock->has_tls_authz = qemu_opt_get(opts, "tls-authz");
1415    sock->tls_authz = g_strdup(qemu_opt_get(opts, "tls-authz"));
1416
1417    addr = g_new0(SocketAddressLegacy, 1);
1418    if (path) {
1419        UnixSocketAddress *q_unix;
1420        addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;
1421        q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
1422        q_unix->path = g_strdup(path);
1423    } else if (host) {
1424        addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
1425        addr->u.inet.data = g_new(InetSocketAddress, 1);
1426        *addr->u.inet.data = (InetSocketAddress) {
1427            .host = g_strdup(host),
1428            .port = g_strdup(port),
1429            .has_to = qemu_opt_get(opts, "to"),
1430            .to = qemu_opt_get_number(opts, "to", 0),
1431            .has_ipv4 = qemu_opt_get(opts, "ipv4"),
1432            .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
1433            .has_ipv6 = qemu_opt_get(opts, "ipv6"),
1434            .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
1435        };
1436    } else if (fd) {
1437        addr->type = SOCKET_ADDRESS_LEGACY_KIND_FD;
1438        addr->u.fd.data = g_new(String, 1);
1439        addr->u.fd.data->str = g_strdup(fd);
1440    } else {
1441        g_assert_not_reached();
1442    }
1443    sock->addr = addr;
1444}
1445
1446static void
1447char_socket_get_addr(Object *obj, Visitor *v, const char *name,
1448                     void *opaque, Error **errp)
1449{
1450    SocketChardev *s = SOCKET_CHARDEV(obj);
1451
1452    visit_type_SocketAddress(v, name, &s->addr, errp);
1453}
1454
1455static bool
1456char_socket_get_connected(Object *obj, Error **errp)
1457{
1458    SocketChardev *s = SOCKET_CHARDEV(obj);
1459
1460    return s->state == TCP_CHARDEV_STATE_CONNECTED;
1461}
1462
1463static void char_socket_class_init(ObjectClass *oc, void *data)
1464{
1465    ChardevClass *cc = CHARDEV_CLASS(oc);
1466
1467    cc->parse = qemu_chr_parse_socket;
1468    cc->open = qmp_chardev_open_socket;
1469    cc->chr_wait_connected = tcp_chr_wait_connected;
1470    cc->chr_write = tcp_chr_write;
1471    cc->chr_sync_read = tcp_chr_sync_read;
1472    cc->chr_disconnect = tcp_chr_disconnect;
1473    cc->get_msgfds = tcp_get_msgfds;
1474    cc->set_msgfds = tcp_set_msgfds;
1475    cc->chr_add_client = tcp_chr_add_client;
1476    cc->chr_add_watch = tcp_chr_add_watch;
1477    cc->chr_update_read_handler = tcp_chr_update_read_handler;
1478
1479    object_class_property_add(oc, "addr", "SocketAddress",
1480                              char_socket_get_addr, NULL,
1481                              NULL, NULL, &error_abort);
1482
1483    object_class_property_add_bool(oc, "connected", char_socket_get_connected,
1484                                   NULL, &error_abort);
1485}
1486
1487static const TypeInfo char_socket_type_info = {
1488    .name = TYPE_CHARDEV_SOCKET,
1489    .parent = TYPE_CHARDEV,
1490    .instance_size = sizeof(SocketChardev),
1491    .instance_finalize = char_socket_finalize,
1492    .class_init = char_socket_class_init,
1493};
1494
1495static void register_types(void)
1496{
1497    type_register_static(&char_socket_type_info);
1498}
1499
1500type_init(register_types);
1501