103 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			103 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * replay-net.c
 | 
						|
 *
 | 
						|
 * Copyright (c) 2010-2016 Institute for System Programming
 | 
						|
 *                         of the Russian Academy of Sciences.
 | 
						|
 *
 | 
						|
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
						|
 * See the COPYING file in the top-level directory.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include "qemu/osdep.h"
 | 
						|
#include "qemu/error-report.h"
 | 
						|
#include "sysemu/replay.h"
 | 
						|
#include "replay-internal.h"
 | 
						|
#include "sysemu/sysemu.h"
 | 
						|
#include "net/net.h"
 | 
						|
#include "net/filter.h"
 | 
						|
#include "qemu/iov.h"
 | 
						|
 | 
						|
struct ReplayNetState {
 | 
						|
    NetFilterState *nfs;
 | 
						|
    int id;
 | 
						|
};
 | 
						|
 | 
						|
typedef struct NetEvent {
 | 
						|
    uint8_t id;
 | 
						|
    uint32_t flags;
 | 
						|
    uint8_t *data;
 | 
						|
    size_t size;
 | 
						|
} NetEvent;
 | 
						|
 | 
						|
static NetFilterState **network_filters;
 | 
						|
static int network_filters_count;
 | 
						|
 | 
						|
ReplayNetState *replay_register_net(NetFilterState *nfs)
 | 
						|
{
 | 
						|
    ReplayNetState *rns = g_new0(ReplayNetState, 1);
 | 
						|
    rns->nfs = nfs;
 | 
						|
    rns->id = network_filters_count++;
 | 
						|
    network_filters = g_realloc(network_filters,
 | 
						|
                                network_filters_count
 | 
						|
                                    * sizeof(*network_filters));
 | 
						|
    network_filters[network_filters_count - 1] = nfs;
 | 
						|
    return rns;
 | 
						|
}
 | 
						|
 | 
						|
void replay_unregister_net(ReplayNetState *rns)
 | 
						|
{
 | 
						|
    network_filters[rns->id] = NULL;
 | 
						|
    g_free(rns);
 | 
						|
}
 | 
						|
 | 
						|
void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
 | 
						|
                             const struct iovec *iov, int iovcnt)
 | 
						|
{
 | 
						|
    NetEvent *event = g_new(NetEvent, 1);
 | 
						|
    event->flags = flags;
 | 
						|
    event->data = g_malloc(iov_size(iov, iovcnt));
 | 
						|
    event->size = iov_size(iov, iovcnt);
 | 
						|
    event->id = rns->id;
 | 
						|
    iov_to_buf(iov, iovcnt, 0, event->data, event->size);
 | 
						|
 | 
						|
    replay_add_event(REPLAY_ASYNC_EVENT_NET, event, NULL, 0);
 | 
						|
}
 | 
						|
 | 
						|
void replay_event_net_run(void *opaque)
 | 
						|
{
 | 
						|
    NetEvent *event = opaque;
 | 
						|
    struct iovec iov = {
 | 
						|
        .iov_base = (void *)event->data,
 | 
						|
        .iov_len = event->size
 | 
						|
    };
 | 
						|
 | 
						|
    assert(event->id < network_filters_count);
 | 
						|
 | 
						|
    qemu_netfilter_pass_to_next(network_filters[event->id]->netdev,
 | 
						|
        event->flags, &iov, 1, network_filters[event->id]);
 | 
						|
 | 
						|
    g_free(event->data);
 | 
						|
    g_free(event);
 | 
						|
}
 | 
						|
 | 
						|
void replay_event_net_save(void *opaque)
 | 
						|
{
 | 
						|
    NetEvent *event = opaque;
 | 
						|
 | 
						|
    replay_put_byte(event->id);
 | 
						|
    replay_put_dword(event->flags);
 | 
						|
    replay_put_array(event->data, event->size);
 | 
						|
}
 | 
						|
 | 
						|
void *replay_event_net_load(void)
 | 
						|
{
 | 
						|
    NetEvent *event = g_new(NetEvent, 1);
 | 
						|
 | 
						|
    event->id = replay_get_byte();
 | 
						|
    event->flags = replay_get_dword();
 | 
						|
    replay_get_array_alloc(&event->data, &event->size);
 | 
						|
 | 
						|
    return event;
 | 
						|
}
 |