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