+ .notify = net_slirp_notify,
+};
+
+static int slirp_poll_to_gio(int events)
+{
+ int ret = 0;
+
+ if (events & SLIRP_POLL_IN) {
+ ret |= G_IO_IN;
+ }
+ if (events & SLIRP_POLL_OUT) {
+ ret |= G_IO_OUT;
+ }
+ if (events & SLIRP_POLL_PRI) {
+ ret |= G_IO_PRI;
+ }
+ if (events & SLIRP_POLL_ERR) {
+ ret |= G_IO_ERR;
+ }
+ if (events & SLIRP_POLL_HUP) {
+ ret |= G_IO_HUP;
+ }
+
+ return ret;
+}
+
+static int net_slirp_add_poll(int fd, int events, void *opaque)
+{
+ GArray *pollfds = opaque;
+ GPollFD pfd = {
+ .fd = fd,
+ .events = slirp_poll_to_gio(events),
+ };
+ int idx = pollfds->len;
+ g_array_append_val(pollfds, pfd);
+ return idx;
+}
+
+static int slirp_gio_to_poll(int events)
+{
+ int ret = 0;
+
+ if (events & G_IO_IN) {
+ ret |= SLIRP_POLL_IN;
+ }
+ if (events & G_IO_OUT) {
+ ret |= SLIRP_POLL_OUT;
+ }
+ if (events & G_IO_PRI) {
+ ret |= SLIRP_POLL_PRI;
+ }
+ if (events & G_IO_ERR) {
+ ret |= SLIRP_POLL_ERR;
+ }
+ if (events & G_IO_HUP) {
+ ret |= SLIRP_POLL_HUP;
+ }
+
+ return ret;
+}
+
+static int net_slirp_get_revents(int idx, void *opaque)
+{
+ GArray *pollfds = opaque;
+
+ return slirp_gio_to_poll(g_array_index(pollfds, GPollFD, idx).revents);
+}
+
+static void net_slirp_poll_notify(Notifier *notifier, void *data)
+{
+ MainLoopPoll *poll = data;
+ SlirpState *s = container_of(notifier, SlirpState, poll_notifier);
+
+ switch (poll->state) {
+ case MAIN_LOOP_POLL_FILL:
+ slirp_pollfds_fill(s->slirp, &poll->timeout,
+ net_slirp_add_poll, poll->pollfds);
+ break;
+ case MAIN_LOOP_POLL_OK:
+ case MAIN_LOOP_POLL_ERR:
+ slirp_pollfds_poll(s->slirp, poll->state == MAIN_LOOP_POLL_ERR,
+ net_slirp_get_revents, poll->pollfds);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static ssize_t
+net_slirp_stream_read(void *buf, size_t size, void *opaque)
+{
+ QEMUFile *f = opaque;
+
+ return qemu_get_buffer(f, buf, size);
+}
+
+static ssize_t
+net_slirp_stream_write(const void *buf, size_t size, void *opaque)
+{
+ QEMUFile *f = opaque;
+
+ qemu_put_buffer(f, buf, size);
+ if (qemu_file_get_error(f)) {
+ return -1;
+ }
+
+ return size;
+}
+
+static int net_slirp_state_load(QEMUFile *f, void *opaque, int version_id)
+{
+ Slirp *slirp = opaque;
+
+ return slirp_state_load(slirp, version_id, net_slirp_stream_read, f);
+}
+
+static void net_slirp_state_save(QEMUFile *f, void *opaque)
+{
+ Slirp *slirp = opaque;
+
+ slirp_state_save(slirp, net_slirp_stream_write, f);
+}
+
+static SaveVMHandlers savevm_slirp_state = {
+ .save_state = net_slirp_state_save,
+ .load_state = net_slirp_state_load,