aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@gmail.com>2022-04-25 08:36:12 +0000
committerMarc-André Lureau <marcandre.lureau@gmail.com>2022-04-25 08:36:12 +0000
commit3b521f531f7b85d9d101b8d7dfa729c8f2d9208d (patch)
treeade86112b5f0bb1c6209ef720921904bcb933648
parent888ddad6bde1dc6d7dbfc8daa7d015251b72e02c (diff)
parentf65862ff117447bc69b137d36237ef1ea8868121 (diff)
downloadslirp-3b521f531f7b85d9d101b8d7dfa729c8f2d9208d.zip
slirp-3b521f531f7b85d9d101b8d7dfa729c8f2d9208d.tar.gz
slirp-3b521f531f7b85d9d101b8d7dfa729c8f2d9208d.tar.bz2
Merge branch 'opaque-timer' into 'master'
Support for CFI See merge request slirp/libslirp!117
-rw-r--r--meson.build6
-rw-r--r--src/ip6_icmp.c26
-rw-r--r--src/ip6_icmp.h4
-rw-r--r--src/ip6_input.c4
-rw-r--r--src/libslirp.h23
-rw-r--r--src/libslirp.map4
-rw-r--r--src/slirp.c44
-rw-r--r--src/slirp.h5
-rw-r--r--test/pingtest.c16
9 files changed, 100 insertions, 32 deletions
diff --git a/meson.build b/meson.build
index 37d3bf4..1fb2cd3 100644
--- a/meson.build
+++ b/meson.build
@@ -44,9 +44,9 @@ conf.set_quoted('SLIRP_VERSION_STRING', full_version + get_option('version_suffi
# - If the interface is the same as the previous version, but bugs are
# fixed, change:
# REVISION += 1
-lt_current = 3
-lt_revision = 1
-lt_age = 3
+lt_current = 4
+lt_revision = 0
+lt_age = 4
lt_version = '@0@.@1@.@2@'.format(lt_current - lt_age, lt_age, lt_revision)
host_system = host_machine.system()
diff --git a/src/ip6_icmp.c b/src/ip6_icmp.c
index 738b40f..0d7ee69 100644
--- a/src/ip6_icmp.c
+++ b/src/ip6_icmp.c
@@ -10,25 +10,14 @@
#define NDP_Interval \
g_rand_int_range(slirp->grand, NDP_MinRtrAdvInterval, NDP_MaxRtrAdvInterval)
-static void ra_timer_handler(void *opaque)
-{
- Slirp *slirp = opaque;
-
- slirp->cb->timer_mod(slirp->ra_timer,
- slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS +
- NDP_Interval,
- slirp->opaque);
- ndp_send_ra(slirp);
-}
-
-void icmp6_init(Slirp *slirp)
+void icmp6_post_init(Slirp *slirp)
{
if (!slirp->in6_enabled) {
return;
}
slirp->ra_timer =
- slirp->cb->timer_new(ra_timer_handler, slirp, slirp->opaque);
+ slirp_timer_new(slirp, SLIRP_TIMER_RA, NULL);
slirp->cb->timer_mod(slirp->ra_timer,
slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS +
NDP_Interval,
@@ -140,7 +129,7 @@ void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code)
/*
* Send NDP Router Advertisement
*/
-void ndp_send_ra(Slirp *slirp)
+static void ndp_send_ra(Slirp *slirp)
{
DEBUG_CALL("ndp_send_ra");
@@ -219,6 +208,15 @@ void ndp_send_ra(Slirp *slirp)
ip6_output(NULL, t, 0);
}
+void ra_timer_handler(Slirp *slirp, void *unused)
+{
+ slirp->cb->timer_mod(slirp->ra_timer,
+ slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS +
+ NDP_Interval,
+ slirp->opaque);
+ ndp_send_ra(slirp);
+}
+
/*
* Send NDP Neighbor Solitication
*/
diff --git a/src/ip6_icmp.h b/src/ip6_icmp.h
index 9070999..9f378f1 100644
--- a/src/ip6_icmp.h
+++ b/src/ip6_icmp.h
@@ -209,12 +209,12 @@ struct ndpopt {
#define NDP_AdvPrefLifetime 14400
#define NDP_AdvAutonomousFlag 1
-void icmp6_init(Slirp *slirp);
+void icmp6_post_init(Slirp *slirp);
void icmp6_cleanup(Slirp *slirp);
void icmp6_input(struct mbuf *);
void icmp6_forward_error(struct mbuf *m, uint8_t type, uint8_t code, struct in6_addr *src);
void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code);
-void ndp_send_ra(Slirp *slirp);
void ndp_send_ns(Slirp *slirp, struct in6_addr addr);
+void ra_timer_handler(Slirp *slirp, void *unused);
#endif
diff --git a/src/ip6_input.c b/src/ip6_input.c
index b3d9865..4aca082 100644
--- a/src/ip6_input.c
+++ b/src/ip6_input.c
@@ -11,9 +11,9 @@
* IP initialization: fill in IP protocol switch table.
* All protocols not implemented in kernel go to raw IP protocol handler.
*/
-void ip6_init(Slirp *slirp)
+void ip6_post_init(Slirp *slirp)
{
- icmp6_init(slirp);
+ icmp6_post_init(slirp);
}
void ip6_cleanup(Slirp *slirp)
diff --git a/src/libslirp.h b/src/libslirp.h
index 1e75501..77396f0 100644
--- a/src/libslirp.h
+++ b/src/libslirp.h
@@ -39,6 +39,11 @@ typedef void (*SlirpTimerCb)(void *opaque);
typedef int (*SlirpAddPollCb)(int fd, int events, void *opaque);
typedef int (*SlirpGetREventsCb)(int idx, void *opaque);
+typedef enum SlirpTimerId {
+ SLIRP_TIMER_RA,
+ SLIRP_TIMER_NUM,
+} SlirpTimerId;
+
/*
* Callbacks from slirp, to be set by the application.
*
@@ -58,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);
@@ -71,6 +77,16 @@ 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
+ */
+
+ /* Initialization has completed and a Slirp* has been created. */
+ void (*init_completed)(Slirp *slirp, void *opaque);
+ /* 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
@@ -166,6 +182,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 5e08b53..1423b01 100644
--- a/src/slirp.c
+++ b/src/slirp.c
@@ -528,6 +528,43 @@ static void slirp_init_once(void)
}
}
+static void ra_timer_handler_cb(void *opaque)
+{
+ Slirp *slirp = 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);
+ return slirp->cb->timer_new(ra_timer_handler_cb, slirp, slirp->opaque);
+
+ default:
+ abort();
+ }
+}
+
Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaque)
{
Slirp *slirp;
@@ -547,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();
@@ -557,7 +595,6 @@ Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaque)
if_init(slirp);
ip_init(slirp);
- ip6_init(slirp);
m_init(slirp);
@@ -607,6 +644,11 @@ Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaque)
slirp->disable_dhcp = false;
}
+ if (slirp->cfg_version >= 4 && slirp->cb->init_completed) {
+ slirp->cb->init_completed(slirp, slirp->opaque);
+ }
+
+ ip6_post_init(slirp);
return slirp;
}
diff --git a/src/slirp.h b/src/slirp.h
index 239d570..35c2be3 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;
@@ -244,7 +246,7 @@ void ip_stripoptions(register struct mbuf *, struct mbuf *);
int ip_output(struct socket *, struct mbuf *);
/* ip6_input.c */
-void ip6_init(Slirp *);
+void ip6_post_init(Slirp *);
void ip6_cleanup(Slirp *);
void ip6_input(struct mbuf *);
@@ -280,5 +282,6 @@ struct socket *slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr,
int guest_port);
void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len);
+void *slirp_timer_new(Slirp *slirp, SlirpTimerId id, void *cb_opaque);
#endif
diff --git a/test/pingtest.c b/test/pingtest.c
index 15249f0..3bb0488 100644
--- a/test/pingtest.c
+++ b/test/pingtest.c
@@ -196,7 +196,7 @@ static int64_t clock_get_ns(void *opaque) {
}
struct timer {
- SlirpTimerCb cb;
+ SlirpTimerId id;
void *cb_opaque;
int64_t expire;
struct timer *next;
@@ -204,9 +204,9 @@ struct timer {
static struct timer *timer_queue;
-static void *timer_new(SlirpTimerCb cb, void *cb_opaque, void *opaque) {
+static void *timer_new_opaque(SlirpTimerId id, void *cb_opaque, void *opaque) {
struct timer *new_timer = malloc(sizeof(*new_timer));
- new_timer->cb = cb;
+ new_timer->id = id;
new_timer->cb_opaque = cb_opaque;
new_timer->next = NULL;
return new_timer;
@@ -242,14 +242,14 @@ static void timer_mod(void *_timer, int64_t expire_time, void *opaque) {
*t = timer;
}
-static void timer_check(void) {
+static void timer_check(Slirp *slirp) {
while (timer_queue && timer_queue->expire <= mytime)
{
struct timer *t = timer_queue;
printf("handling %p at time %lu\n",
t, (unsigned long) timer_queue->expire);
timer_queue = t->next;
- t->cb(t->cb_opaque);
+ slirp_handle_timer(slirp, t->id, t->cb_opaque);
}
}
@@ -378,7 +378,7 @@ static struct SlirpCb callbacks = {
.send_packet = send_packet,
.guest_error = guest_error,
.clock_get_ns = clock_get_ns,
- .timer_new = timer_new,
+ .timer_new_opaque = timer_new_opaque,
.timer_free = timer_free,
.timer_mod = timer_mod,
.register_poll_fd = register_poll_fd,
@@ -389,7 +389,7 @@ static struct SlirpCb callbacks = {
int main(int argc, char *argv[]) {
SlirpConfig config = {
- .version = 3,
+ .version = 4,
.restricted = false,
.in_enabled = true,
.vnetwork.s_addr = htonl(0x0a000200),
@@ -472,7 +472,7 @@ int main(int argc, char *argv[]) {
while (!done) {
printf("time %lu\n", (unsigned long) mytime);
- timer_check();
+ timer_check(slirp);
/* Here we make the virtual time wait like the real time, but we could
* make it wait differently */
timeout = timer_timeout();