cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

socket.c (5681B)


      1/*
      2 * QEMU live migration via socket
      3 *
      4 * Copyright Red Hat, Inc. 2009-2016
      5 *
      6 * Authors:
      7 *  Chris Lalancette <clalance@redhat.com>
      8 *  Daniel P. Berrange <berrange@redhat.com>
      9 *
     10 * This work is licensed under the terms of the GNU GPL, version 2.  See
     11 * the COPYING file in the top-level directory.
     12 *
     13 * Contributions after 2012-01-13 are licensed under the terms of the
     14 * GNU GPL, version 2 or (at your option) any later version.
     15 */
     16
     17#include "qemu/osdep.h"
     18#include "qemu/cutils.h"
     19
     20#include "qemu/error-report.h"
     21#include "qapi/error.h"
     22#include "channel.h"
     23#include "socket.h"
     24#include "migration.h"
     25#include "qemu-file.h"
     26#include "io/channel-socket.h"
     27#include "io/net-listener.h"
     28#include "trace.h"
     29
     30
     31struct SocketOutgoingArgs {
     32    SocketAddress *saddr;
     33} outgoing_args;
     34
     35void socket_send_channel_create(QIOTaskFunc f, void *data)
     36{
     37    QIOChannelSocket *sioc = qio_channel_socket_new();
     38    qio_channel_socket_connect_async(sioc, outgoing_args.saddr,
     39                                     f, data, NULL, NULL);
     40}
     41
     42int socket_send_channel_destroy(QIOChannel *send)
     43{
     44    /* Remove channel */
     45    object_unref(OBJECT(send));
     46    if (outgoing_args.saddr) {
     47        qapi_free_SocketAddress(outgoing_args.saddr);
     48        outgoing_args.saddr = NULL;
     49    }
     50    return 0;
     51}
     52
     53struct SocketConnectData {
     54    MigrationState *s;
     55    char *hostname;
     56};
     57
     58static void socket_connect_data_free(void *opaque)
     59{
     60    struct SocketConnectData *data = opaque;
     61    if (!data) {
     62        return;
     63    }
     64    g_free(data->hostname);
     65    g_free(data);
     66}
     67
     68static void socket_outgoing_migration(QIOTask *task,
     69                                      gpointer opaque)
     70{
     71    struct SocketConnectData *data = opaque;
     72    QIOChannel *sioc = QIO_CHANNEL(qio_task_get_source(task));
     73    Error *err = NULL;
     74
     75    if (qio_task_propagate_error(task, &err)) {
     76        trace_migration_socket_outgoing_error(error_get_pretty(err));
     77    } else {
     78        trace_migration_socket_outgoing_connected(data->hostname);
     79    }
     80    migration_channel_connect(data->s, sioc, data->hostname, err);
     81    object_unref(OBJECT(sioc));
     82}
     83
     84static void
     85socket_start_outgoing_migration_internal(MigrationState *s,
     86                                         SocketAddress *saddr,
     87                                         Error **errp)
     88{
     89    QIOChannelSocket *sioc = qio_channel_socket_new();
     90    struct SocketConnectData *data = g_new0(struct SocketConnectData, 1);
     91
     92    data->s = s;
     93
     94    /* in case previous migration leaked it */
     95    qapi_free_SocketAddress(outgoing_args.saddr);
     96    outgoing_args.saddr = saddr;
     97
     98    if (saddr->type == SOCKET_ADDRESS_TYPE_INET) {
     99        data->hostname = g_strdup(saddr->u.inet.host);
    100    }
    101
    102    qio_channel_set_name(QIO_CHANNEL(sioc), "migration-socket-outgoing");
    103    qio_channel_socket_connect_async(sioc,
    104                                     saddr,
    105                                     socket_outgoing_migration,
    106                                     data,
    107                                     socket_connect_data_free,
    108                                     NULL);
    109}
    110
    111void socket_start_outgoing_migration(MigrationState *s,
    112                                     const char *str,
    113                                     Error **errp)
    114{
    115    Error *err = NULL;
    116    SocketAddress *saddr = socket_parse(str, &err);
    117    if (!err) {
    118        socket_start_outgoing_migration_internal(s, saddr, &err);
    119    }
    120    error_propagate(errp, err);
    121}
    122
    123static void socket_accept_incoming_migration(QIONetListener *listener,
    124                                             QIOChannelSocket *cioc,
    125                                             gpointer opaque)
    126{
    127    trace_migration_socket_incoming_accepted();
    128
    129    if (migration_has_all_channels()) {
    130        error_report("%s: Extra incoming migration connection; ignoring",
    131                     __func__);
    132        return;
    133    }
    134
    135    qio_channel_set_name(QIO_CHANNEL(cioc), "migration-socket-incoming");
    136    migration_channel_process_incoming(QIO_CHANNEL(cioc));
    137}
    138
    139static void
    140socket_incoming_migration_end(void *opaque)
    141{
    142    QIONetListener *listener = opaque;
    143
    144    qio_net_listener_disconnect(listener);
    145    object_unref(OBJECT(listener));
    146}
    147
    148static void
    149socket_start_incoming_migration_internal(SocketAddress *saddr,
    150                                         Error **errp)
    151{
    152    QIONetListener *listener = qio_net_listener_new();
    153    MigrationIncomingState *mis = migration_incoming_get_current();
    154    size_t i;
    155    int num = 1;
    156
    157    qio_net_listener_set_name(listener, "migration-socket-listener");
    158
    159    if (migrate_use_multifd()) {
    160        num = migrate_multifd_channels();
    161    }
    162
    163    if (qio_net_listener_open_sync(listener, saddr, num, errp) < 0) {
    164        object_unref(OBJECT(listener));
    165        return;
    166    }
    167
    168    mis->transport_data = listener;
    169    mis->transport_cleanup = socket_incoming_migration_end;
    170
    171    qio_net_listener_set_client_func_full(listener,
    172                                          socket_accept_incoming_migration,
    173                                          NULL, NULL,
    174                                          g_main_context_get_thread_default());
    175
    176    for (i = 0; i < listener->nsioc; i++)  {
    177        SocketAddress *address =
    178            qio_channel_socket_get_local_address(listener->sioc[i], errp);
    179        if (!address) {
    180            return;
    181        }
    182        migrate_add_address(address);
    183        qapi_free_SocketAddress(address);
    184    }
    185}
    186
    187void socket_start_incoming_migration(const char *str, Error **errp)
    188{
    189    Error *err = NULL;
    190    SocketAddress *saddr = socket_parse(str, &err);
    191    if (!err) {
    192        socket_start_incoming_migration_internal(saddr, &err);
    193    }
    194    qapi_free_SocketAddress(saddr);
    195    error_propagate(errp, err);
    196}