From 8e6b6d04b11d3a2a4fd8413555414c5f8e500915 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 28 Jul 2021 17:16:06 +0200 Subject: introduce timer_new_opaque callback Add a new callback that supports CFI better by avoiding having function pointers in the external libslirp API. Instead, the new API passes an opaque integer and requests the application to call a new libslirp function when the timer expires. Signed-off-by: Paolo Bonzini --- src/libslirp.h | 16 +++++++++++++++- src/libslirp.map | 4 ++++ src/slirp.c | 17 +++++++++++++++++ src/slirp.h | 2 ++ 4 files changed, 38 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/libslirp.h b/src/libslirp.h index 546f2f9..8eb47a0 100644 --- a/src/libslirp.h +++ b/src/libslirp.h @@ -63,7 +63,8 @@ typedef struct SlirpCb { void (*guest_error)(const char *msg, void *opaque); /* Return the virtual clock value in nanoseconds */ int64_t (*clock_get_ns)(void *opaque); - /* Create a new timer with the given callback and opaque data */ + /* Create a new timer with the given callback and opaque data. Not + * needed if timer_new_opaque is provided. */ void *(*timer_new)(SlirpTimerCb cb, void *cb_opaque, void *opaque); /* Remove and free a timer */ void (*timer_free)(void *timer, void *opaque); @@ -76,6 +77,14 @@ typedef struct SlirpCb { /* Kick the io-thread, to signal that new events may be processed because some TCP buffer * can now receive more data, i.e. slirp_socket_can_recv will return 1. */ void (*notify)(void *opaque); + + /* + * Fields introduced in SlirpConfig version 4 begin + */ + + /* Create a new timer. When the timer fires, the application passes + * the SlirpTimerId and cb_opaque to slirp_handle_timer. */ + void *(*timer_new_opaque)(SlirpTimerId id, void *cb_opaque, void *opaque); } SlirpCb; #define SLIRP_CONFIG_VERSION_MIN 1 @@ -171,6 +180,11 @@ void slirp_pollfds_poll(Slirp *slirp, int select_error, * guest network, to be interpreted by slirp. */ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len); +/* This is called by the application when a timer expires, if it provides + * the timer_new_opaque callback. It is not needed if the application only + * uses timer_new. */ +void slirp_handle_timer(Slirp *slirp, SlirpTimerId id, void *cb_opaque); + /* These set up / remove port forwarding between a host port in the real world * and the guest network. */ int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, diff --git a/src/libslirp.map b/src/libslirp.map index 792b0a9..3921f8a 100644 --- a/src/libslirp.map +++ b/src/libslirp.map @@ -34,3 +34,7 @@ SLIRP_4.5 { slirp_remove_hostxfwd; slirp_neighbor_info; } SLIRP_4.2; + +SLIRP_4.7 { + slirp_handle_timer; +} SLIRP_4.5; diff --git a/src/slirp.c b/src/slirp.c index a2876f2..c92a9a9 100644 --- a/src/slirp.c +++ b/src/slirp.c @@ -535,10 +535,26 @@ static void ra_timer_handler_cb(void *opaque) return ra_timer_handler(slirp, NULL); } +void slirp_handle_timer(Slirp *slirp, SlirpTimerId id, void *cb_opaque) +{ + g_return_if_fail(id >= 0 && id < SLIRP_TIMER_NUM); + + switch (id) { + case SLIRP_TIMER_RA: + return ra_timer_handler(slirp, cb_opaque); + default: + abort(); + } +} + void *slirp_timer_new(Slirp *slirp, SlirpTimerId id, void *cb_opaque) { g_return_val_if_fail(id >= 0 && id < SLIRP_TIMER_NUM, NULL); + if (slirp->cfg_version >= 4 && slirp->cb->timer_new_opaque) { + return slirp->cb->timer_new_opaque(id, cb_opaque, slirp->opaque); + } + switch (id) { case SLIRP_TIMER_RA: g_return_val_if_fail(cb_opaque == NULL, NULL); @@ -568,6 +584,7 @@ Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaque) slirp_init_once(); + slirp->cfg_version = cfg->version; slirp->opaque = opaque; slirp->cb = callbacks; slirp->grand = g_rand_new(); diff --git a/src/slirp.h b/src/slirp.h index bfe7b83..50e33a5 100644 --- a/src/slirp.h +++ b/src/slirp.h @@ -120,6 +120,8 @@ bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr, uint8_t out_ethaddr[ETH_ALEN]); struct Slirp { + int cfg_version; + unsigned time_fasttimo; unsigned last_slowtimo; bool do_slowtimo; -- cgit v1.1