2
0
Эх сурвалжийг харах

Merge remote-tracking branch 'remotes/thibault/tags/samuel-thibault' into staging

slirp updates

Gerd Hoffmann (1):
  slirp: add tftp tracing

Marc-André Lureau (61):
  slirp: associate slirp_output callback with the Slirp context
  slirp: remove do_pty from fork_exec()
  slirp: replace ex_pty with ex_chardev
  slirp: use a dedicated field for chardev pointer
  slirp: remove unused EMU_RSH
  slirp: rename /extra/chardev
  slirp: move internal function declarations
  slirp: remove Monitor dependency, return a string for info
  slirp: fix slirp_add_exec() leaks
  slirp: replace the poor-man string split with g_strsplit()
  slirp: remove dead declarations
  slirp: move socket pair creation in helper function
  slirp: remove unused M_TRAILINGSPACE
  slirp: use a callback structure to interface with qemu
  slirp: remove PROBE_CONN dead-code
  slirp: remove FULL_BOLT
  slirp: remove the disabled readv()/writev() code path
  slirp: remove HAVE_SYS_SIGNAL_H
  slirp: remove unused HAVE_SYS_BITYPES_H
  slirp: remove NO_UNIX_SOCKETS
  slirp: remove unused HAVE_SYS_STROPTS_H
  slirp: remove unused HAVE_ARPA_INET_H
  slirp: remove unused HAVE_SYS_WAIT_H
  slirp: remove unused HAVE_SYS_SELECT_H
  slirp: remove HAVE_SYS_IOCTL_H
  slirp: remove HAVE_SYS_FILIO_H
  slirp: remove unused DECLARE_IOVEC
  slirp: remove unused HAVE_INET_ATON
  slirp: replace HOST_WORDS_BIGENDIAN with glib equivalent
  slirp: replace SIZEOF_CHAR_P with glib equivalent
  slirp: replace compile time DO_KEEPALIVE
  slirp: remove unused global slirp_instance
  slirp: replace error_report() with g_critical()
  slirp: improve a bit the debug macros
  slirp: add a callback to log guest errors
  slirp: remove #if notdef dead code
  slirp: remove unused sbflush()
  slirp: NULL is defined by stddef.h
  slirp: remove dead TCP_ACK_HACK code
  slirp: replace ARRAY_SIZE with G_N_ELEMENTS
  net: do not depend on slirp internals
  glib-compat: add g_spawn_async_with_fds() fallback
  slirp: simplify fork_exec()
  slirp: replace error_report() with g_critical()
  slirp: drop <Vista compatibility
  slirp: rename exec_list
  slirp: use virtual time for packet expiration
  slirp: replace a fprintf with g_critical()
  slirp: replace some fprintf() with DEBUG_MISC
  slirp: replace a DEBUG block with WITH_ICMP_ERROR_MSG
  slirp: no need to make DPRINTF conditional on DEBUG
  slirp: always build with debug statements
  slirp: introduce SLIRP_DEBUG environment variable
  slirp: use %p for pointers format
  slirp: remove remaining DEBUG blocks
  slirp: replace DEBUG_ARGS with DEBUG_ARG
  slirp: factor out guestfwd addition checks
  slirp: add clock_get_ns() callback
  build-sys: use a separate slirp-obj-y && slirp.mo
  slirp: set G_LOG_DOMAIN
  slirp: call into g_debug() for DEBUG macros

Prasad J Pandit (1):
  slirp: check data length while emulating ident function

Samuel Thibault (2):
  slirp: Enable fork_exec support on Windows
  slirp: Mark debugging calls as unlikely

 Makefile              |   5 +-
 Makefile.objs         |   4 +-
 Makefile.target       |   5 +-
 include/glib-compat.h |  56 +++++++++
 net/colo-compare.c    |  11 +-
 net/colo.c            |   1 +
 net/colo.h            |   7 +-
 net/filter-rewriter.c |   9 +-
 net/slirp.c           |  61 +++++----
 net/util.h            |  55 ++++++++
 slirp/Makefile.objs   |  37 +++++-
 slirp/arp_table.c     |  12 +-
 slirp/bootp.c         |  10 +-
 slirp/cksum.c         |   8 +-
 slirp/debug.h         |  47 ++++---
 slirp/dhcpv6.c        |  17 ++-
 slirp/if.c            |   4 +-
 slirp/ip.h            |  10 +-
 slirp/ip6.h           |   3 +-
 slirp/ip6_icmp.c      |  27 ++--
 slirp/ip6_icmp.h      |   6 +-
 slirp/ip6_input.c     |   2 +-
 slirp/ip6_output.c    |   4 +-
 slirp/ip_icmp.c       |  31 ++---
 slirp/ip_input.c      | 200 -----------------------------
 slirp/libslirp.h      |  27 ++--
 slirp/main.h          |  33 -----
 slirp/mbuf.c          |   2 +-
 slirp/mbuf.h          |   1 -
 slirp/misc.c          | 286 +++++++++++++++++-------------------------
 slirp/misc.h          |  13 +-
 slirp/ncsi.c          |   4 +-
 slirp/ndp_table.c     |  32 +++--
 slirp/sbuf.h          |   1 -
 slirp/slirp.c         | 177 +++++++++++++-------------
 slirp/slirp.h         |  45 ++-----
 slirp/slirp_config.h  |  86 -------------
 slirp/socket.c        |  53 +++-----
 slirp/socket.h        |   2 +-
 slirp/tcp.h           |   4 +-
 slirp/tcp_input.c     |  84 ++-----------
 slirp/tcp_output.c    |   2 +-
 slirp/tcp_subr.c      |  22 ++--
 slirp/tcp_timer.c     |   2 +-
 slirp/tftp.c          |   7 +-
 slirp/trace-events    |   5 +
 slirp/udp.c           |   5 +-
 slirp/udp6.c          |  11 +-
 stubs/slirp.c         |   2 +-
 49 files changed, 603 insertions(+), 935 deletions(-)
 delete mode 100644 slirp/slirp_config.h
 create mode 100644 slirp/trace-events

--
2.20.1

# gpg: Signature made Mon 14 Jan 2019 22:52:32 GMT
# gpg:                using RSA key DB550E89F0FA54F3
# gpg: Good signature from "Samuel Thibault <samuel.thibault@aquilenet.fr>"
# gpg:                 aka "Samuel Thibault <sthibault@debian.org>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@gnu.org>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@inria.fr>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@labri.fr>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@ens-lyon.org>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@u-bordeaux.fr>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 900C B024 B679 31D4 0F82  304B D017 8C76 7D06 9EE6
#      Subkey fingerprint: E61D BB15 D417 2BDE C97E  92D9 DB55 0E89 F0FA 54F3

* remotes/thibault/tags/samuel-thibault: (65 commits)
  slirp: check data length while emulating ident function
  slirp: Mark debugging calls as unlikely
  slirp: call into g_debug() for DEBUG macros
  slirp: set G_LOG_DOMAIN
  build-sys: use a separate slirp-obj-y && slirp.mo
  slirp: add clock_get_ns() callback
  slirp: factor out guestfwd addition checks
  slirp: replace DEBUG_ARGS with DEBUG_ARG
  slirp: remove remaining DEBUG blocks
  slirp: use %p for pointers format
  slirp: introduce SLIRP_DEBUG environment variable
  slirp: always build with debug statements
  slirp: no need to make DPRINTF conditional on DEBUG
  slirp: replace a DEBUG block with WITH_ICMP_ERROR_MSG
  slirp: replace some fprintf() with DEBUG_MISC
  slirp: replace a fprintf with g_critical()
  slirp: use virtual time for packet expiration
  slirp: rename exec_list
  slirp: drop <Vista compatibility
  slirp: Enable fork_exec support on Windows
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Peter Maydell 6 жил өмнө
parent
commit
6f2f34177a

+ 3 - 2
Makefile

@@ -379,7 +379,8 @@ dummy := $(call unnest-vars,, \
                 ui-obj-m \
                 ui-obj-m \
                 audio-obj-y \
                 audio-obj-y \
                 audio-obj-m \
                 audio-obj-m \
-                trace-obj-y)
+                trace-obj-y \
+                slirp-obj-y)
 
 
 include $(SRC_PATH)/tests/Makefile.include
 include $(SRC_PATH)/tests/Makefile.include
 
 
@@ -452,7 +453,7 @@ CAP_CFLAGS += -DCAPSTONE_HAS_X86
 subdir-capstone: .git-submodule-status
 subdir-capstone: .git-submodule-status
 	$(call quiet-command,$(MAKE) -C $(SRC_PATH)/capstone CAPSTONE_SHARED=no BUILDDIR="$(BUILD_DIR)/capstone" CC="$(CC)" AR="$(AR)" LD="$(LD)" RANLIB="$(RANLIB)" CFLAGS="$(CAP_CFLAGS)" $(SUBDIR_MAKEFLAGS) $(BUILD_DIR)/capstone/$(LIBCAPSTONE))
 	$(call quiet-command,$(MAKE) -C $(SRC_PATH)/capstone CAPSTONE_SHARED=no BUILDDIR="$(BUILD_DIR)/capstone" CC="$(CC)" AR="$(AR)" LD="$(LD)" RANLIB="$(RANLIB)" CFLAGS="$(CAP_CFLAGS)" $(SUBDIR_MAKEFLAGS) $(BUILD_DIR)/capstone/$(LIBCAPSTONE))
 
 
-$(SUBDIR_RULES): libqemuutil.a $(common-obj-y) $(chardev-obj-y) \
+$(SUBDIR_RULES): libqemuutil.a $(common-obj-y) $(chardev-obj-y) $(slirp-obj-y) \
 	$(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY))
 	$(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY))
 
 
 ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
 ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))

+ 2 - 2
Makefile.objs

@@ -17,6 +17,7 @@ util-obj-y += $(QAPI_MODULES:%=qapi/qapi-events-%.o)
 util-obj-y += qapi/qapi-introspect.o
 util-obj-y += qapi/qapi-introspect.o
 
 
 chardev-obj-y = chardev/
 chardev-obj-y = chardev/
+slirp-obj-$(CONFIG_SLIRP) = slirp/
 
 
 #######################################################################
 #######################################################################
 # block-obj-y is code used by both qemu system emulation and qemu-img
 # block-obj-y is code used by both qemu system emulation and qemu-img
@@ -79,8 +80,6 @@ common-obj-y += vl.o
 vl.o-cflags := $(GPROF_CFLAGS) $(SDL_CFLAGS)
 vl.o-cflags := $(GPROF_CFLAGS) $(SDL_CFLAGS)
 common-obj-$(CONFIG_TPM) += tpm.o
 common-obj-$(CONFIG_TPM) += tpm.o
 
 
-common-obj-$(CONFIG_SLIRP) += slirp/
-
 common-obj-y += backends/
 common-obj-y += backends/
 common-obj-y += chardev/
 common-obj-y += chardev/
 
 
@@ -193,6 +192,7 @@ trace-events-subdirs += net
 trace-events-subdirs += qapi
 trace-events-subdirs += qapi
 trace-events-subdirs += qom
 trace-events-subdirs += qom
 trace-events-subdirs += scsi
 trace-events-subdirs += scsi
+trace-events-subdirs += slirp
 trace-events-subdirs += target/arm
 trace-events-subdirs += target/arm
 trace-events-subdirs += target/i386
 trace-events-subdirs += target/i386
 trace-events-subdirs += target/mips
 trace-events-subdirs += target/mips

+ 4 - 1
Makefile.target

@@ -165,6 +165,7 @@ target-obj-y :=
 block-obj-y :=
 block-obj-y :=
 common-obj-y :=
 common-obj-y :=
 chardev-obj-y :=
 chardev-obj-y :=
+slirp-obj-y :=
 include $(SRC_PATH)/Makefile.objs
 include $(SRC_PATH)/Makefile.objs
 dummy := $(call unnest-vars,,target-obj-y)
 dummy := $(call unnest-vars,,target-obj-y)
 target-obj-y-save := $(target-obj-y)
 target-obj-y-save := $(target-obj-y)
@@ -177,7 +178,8 @@ dummy := $(call unnest-vars,.., \
                qom-obj-y \
                qom-obj-y \
                io-obj-y \
                io-obj-y \
                common-obj-y \
                common-obj-y \
-               common-obj-m)
+               common-obj-m \
+               slirp-obj-y)
 target-obj-y := $(target-obj-y-save)
 target-obj-y := $(target-obj-y-save)
 all-obj-y += $(common-obj-y)
 all-obj-y += $(common-obj-y)
 all-obj-y += $(target-obj-y)
 all-obj-y += $(target-obj-y)
@@ -186,6 +188,7 @@ all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y) $(chardev-obj-y)
 all-obj-$(CONFIG_USER_ONLY) += $(crypto-aes-obj-y)
 all-obj-$(CONFIG_USER_ONLY) += $(crypto-aes-obj-y)
 all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
 all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
 all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)
 all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)
+all-obj-$(CONFIG_SOFTMMU) += $(slirp-obj-y)
 
 
 $(QEMU_PROG_BUILD): config-devices.mak
 $(QEMU_PROG_BUILD): config-devices.mak
 
 

+ 56 - 0
include/glib-compat.h

@@ -83,6 +83,62 @@ static inline gboolean g_strv_contains_qemu(const gchar *const *strv,
 }
 }
 #define g_strv_contains(a, b) g_strv_contains_qemu(a, b)
 #define g_strv_contains(a, b) g_strv_contains_qemu(a, b)
 
 
+#if !GLIB_CHECK_VERSION(2, 58, 0)
+typedef struct QemuGSpawnFds {
+    GSpawnChildSetupFunc child_setup;
+    gpointer user_data;
+    gint stdin_fd;
+    gint stdout_fd;
+    gint stderr_fd;
+} QemuGSpawnFds;
+
+static inline void
+qemu_gspawn_fds_setup(gpointer user_data)
+{
+    QemuGSpawnFds *q = (QemuGSpawnFds *)user_data;
+
+    dup2(q->stdin_fd, 0);
+    dup2(q->stdout_fd, 1);
+    dup2(q->stderr_fd, 2);
+    q->child_setup(q->user_data);
+}
+#endif
+
+static inline gboolean
+g_spawn_async_with_fds_qemu(const gchar *working_directory,
+                            gchar **argv,
+                            gchar **envp,
+                            GSpawnFlags flags,
+                            GSpawnChildSetupFunc child_setup,
+                            gpointer user_data,
+                            GPid *child_pid,
+                            gint stdin_fd,
+                            gint stdout_fd,
+                            gint stderr_fd,
+                            GError **error)
+{
+#if GLIB_CHECK_VERSION(2, 58, 0)
+    return g_spawn_async_with_fds(working_directory, argv, envp, flags,
+                                  child_setup, user_data,
+                                  child_pid, stdin_fd, stdout_fd, stderr_fd,
+                                  error);
+#else
+    QemuGSpawnFds setup = {
+        .child_setup = child_setup,
+        .user_data = user_data,
+        .stdin_fd = stdin_fd,
+        .stdout_fd = stdout_fd,
+        .stderr_fd = stderr_fd,
+    };
+
+    return g_spawn_async(working_directory, argv, envp, flags,
+                         qemu_gspawn_fds_setup, &setup,
+                         child_pid, error);
+#endif
+}
+
+#define g_spawn_async_with_fds(wd, argv, env, f, c, d, p, ifd, ofd, efd, err) \
+    g_spawn_async_with_fds_qemu(wd, argv, env, f, c, d, p, ifd, ofd, efd, err)
 
 
 #if defined(_WIN32) && !GLIB_CHECK_VERSION(2, 50, 0)
 #if defined(_WIN32) && !GLIB_CHECK_VERSION(2, 50, 0)
 /*
 /*

+ 6 - 5
net/colo-compare.c

@@ -30,6 +30,7 @@
 #include "net/colo-compare.h"
 #include "net/colo-compare.h"
 #include "migration/colo.h"
 #include "migration/colo.h"
 #include "migration/migration.h"
 #include "migration/migration.h"
+#include "util.h"
 
 
 #define TYPE_COLO_COMPARE "colo-compare"
 #define TYPE_COLO_COMPARE "colo-compare"
 #define COLO_COMPARE(obj) \
 #define COLO_COMPARE(obj) \
@@ -129,19 +130,19 @@ static int compare_chr_send(CompareState *s,
 
 
 static gint seq_sorter(Packet *a, Packet *b, gpointer data)
 static gint seq_sorter(Packet *a, Packet *b, gpointer data)
 {
 {
-    struct tcphdr *atcp, *btcp;
+    struct tcp_hdr *atcp, *btcp;
 
 
-    atcp = (struct tcphdr *)(a->transport_header);
-    btcp = (struct tcphdr *)(b->transport_header);
+    atcp = (struct tcp_hdr *)(a->transport_header);
+    btcp = (struct tcp_hdr *)(b->transport_header);
     return ntohl(atcp->th_seq) - ntohl(btcp->th_seq);
     return ntohl(atcp->th_seq) - ntohl(btcp->th_seq);
 }
 }
 
 
 static void fill_pkt_tcp_info(void *data, uint32_t *max_ack)
 static void fill_pkt_tcp_info(void *data, uint32_t *max_ack)
 {
 {
     Packet *pkt = data;
     Packet *pkt = data;
-    struct tcphdr *tcphd;
+    struct tcp_hdr *tcphd;
 
 
-    tcphd = (struct tcphdr *)pkt->transport_header;
+    tcphd = (struct tcp_hdr *)pkt->transport_header;
 
 
     pkt->tcp_seq = ntohl(tcphd->th_seq);
     pkt->tcp_seq = ntohl(tcphd->th_seq);
     pkt->tcp_ack = ntohl(tcphd->th_ack);
     pkt->tcp_ack = ntohl(tcphd->th_ack);

+ 1 - 0
net/colo.c

@@ -15,6 +15,7 @@
 #include "qemu/osdep.h"
 #include "qemu/osdep.h"
 #include "trace.h"
 #include "trace.h"
 #include "colo.h"
 #include "colo.h"
+#include "util.h"
 
 
 uint32_t connection_key_hash(const void *opaque)
 uint32_t connection_key_hash(const void *opaque)
 {
 {

+ 3 - 4
net/colo.h

@@ -15,10 +15,9 @@
 #ifndef QEMU_COLO_PROXY_H
 #ifndef QEMU_COLO_PROXY_H
 #define QEMU_COLO_PROXY_H
 #define QEMU_COLO_PROXY_H
 
 
-#include "slirp/slirp.h"
 #include "qemu/jhash.h"
 #include "qemu/jhash.h"
 #include "qemu/timer.h"
 #include "qemu/timer.h"
-#include "slirp/tcp.h"
+#include "net/eth.h"
 
 
 #define HASHTABLE_MAX_SIZE 16384
 #define HASHTABLE_MAX_SIZE 16384
 
 
@@ -81,10 +80,10 @@ typedef struct Connection {
     /* the maximum of acknowledgement number in secondary_list queue */
     /* the maximum of acknowledgement number in secondary_list queue */
     uint32_t sack;
     uint32_t sack;
     /* offset = secondary_seq - primary_seq */
     /* offset = secondary_seq - primary_seq */
-    tcp_seq  offset;
+    uint32_t  offset;
 
 
     int tcp_state; /* TCP FSM state */
     int tcp_state; /* TCP FSM state */
-    tcp_seq fin_ack_seq; /* the seq of 'fin=1,ack=1' */
+    uint32_t fin_ack_seq; /* the seq of 'fin=1,ack=1' */
 } Connection;
 } Connection;
 
 
 uint32_t connection_key_hash(const void *opaque);
 uint32_t connection_key_hash(const void *opaque);

+ 5 - 4
net/filter-rewriter.c

@@ -22,6 +22,7 @@
 #include "net/checksum.h"
 #include "net/checksum.h"
 #include "net/colo.h"
 #include "net/colo.h"
 #include "migration/colo.h"
 #include "migration/colo.h"
+#include "util.h"
 
 
 #define FILTER_COLO_REWRITER(obj) \
 #define FILTER_COLO_REWRITER(obj) \
     OBJECT_CHECK(RewriterState, (obj), TYPE_FILTER_REWRITER)
     OBJECT_CHECK(RewriterState, (obj), TYPE_FILTER_REWRITER)
@@ -73,9 +74,9 @@ static int handle_primary_tcp_pkt(RewriterState *rf,
                                   Connection *conn,
                                   Connection *conn,
                                   Packet *pkt, ConnectionKey *key)
                                   Packet *pkt, ConnectionKey *key)
 {
 {
-    struct tcphdr *tcp_pkt;
+    struct tcp_hdr *tcp_pkt;
 
 
-    tcp_pkt = (struct tcphdr *)pkt->transport_header;
+    tcp_pkt = (struct tcp_hdr *)pkt->transport_header;
     if (trace_event_get_state_backends(TRACE_COLO_FILTER_REWRITER_DEBUG)) {
     if (trace_event_get_state_backends(TRACE_COLO_FILTER_REWRITER_DEBUG)) {
         trace_colo_filter_rewriter_pkt_info(__func__,
         trace_colo_filter_rewriter_pkt_info(__func__,
                     inet_ntoa(pkt->ip->ip_src), inet_ntoa(pkt->ip->ip_dst),
                     inet_ntoa(pkt->ip->ip_src), inet_ntoa(pkt->ip->ip_dst),
@@ -176,9 +177,9 @@ static int handle_secondary_tcp_pkt(RewriterState *rf,
                                     Connection *conn,
                                     Connection *conn,
                                     Packet *pkt, ConnectionKey *key)
                                     Packet *pkt, ConnectionKey *key)
 {
 {
-    struct tcphdr *tcp_pkt;
+    struct tcp_hdr *tcp_pkt;
 
 
-    tcp_pkt = (struct tcphdr *)pkt->transport_header;
+    tcp_pkt = (struct tcp_hdr *)pkt->transport_header;
 
 
     if (trace_event_get_state_backends(TRACE_COLO_FILTER_REWRITER_DEBUG)) {
     if (trace_event_get_state_backends(TRACE_COLO_FILTER_REWRITER_DEBUG)) {
         trace_colo_filter_rewriter_pkt_info(__func__,
         trace_colo_filter_rewriter_pkt_info(__func__,

+ 29 - 32
net/slirp.c

@@ -23,6 +23,7 @@
  */
  */
 
 
 #include "qemu/osdep.h"
 #include "qemu/osdep.h"
+#include "qemu/log.h"
 #include "net/slirp.h"
 #include "net/slirp.h"
 
 
 
 
@@ -37,12 +38,12 @@
 #include "qemu/error-report.h"
 #include "qemu/error-report.h"
 #include "qemu/sockets.h"
 #include "qemu/sockets.h"
 #include "slirp/libslirp.h"
 #include "slirp/libslirp.h"
-#include "slirp/ip6.h"
 #include "chardev/char-fe.h"
 #include "chardev/char-fe.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/sysemu.h"
 #include "qemu/cutils.h"
 #include "qemu/cutils.h"
 #include "qapi/error.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qdict.h"
 #include "qapi/qmp/qdict.h"
+#include "util.h"
 
 
 static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
 static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
 {
 {
@@ -99,7 +100,7 @@ static void slirp_smb_cleanup(SlirpState *s);
 static inline void slirp_smb_cleanup(SlirpState *s) { }
 static inline void slirp_smb_cleanup(SlirpState *s) { }
 #endif
 #endif
 
 
-void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len)
+static void net_slirp_output(void *opaque, const uint8_t *pkt, int pkt_len)
 {
 {
     SlirpState *s = opaque;
     SlirpState *s = opaque;
 
 
@@ -140,6 +141,22 @@ static NetClientInfo net_slirp_info = {
     .cleanup = net_slirp_cleanup,
     .cleanup = net_slirp_cleanup,
 };
 };
 
 
+static void net_slirp_guest_error(const char *msg)
+{
+    qemu_log_mask(LOG_GUEST_ERROR, "%s", msg);
+}
+
+static int64_t net_slirp_clock_get_ns(void)
+{
+    return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+}
+
+static const SlirpCb slirp_cb = {
+    .output = net_slirp_output,
+    .guest_error = net_slirp_guest_error,
+    .clock_get_ns = net_slirp_clock_get_ns,
+};
+
 static int net_slirp_init(NetClientState *peer, const char *model,
 static int net_slirp_init(NetClientState *peer, const char *model,
                           const char *name, int restricted,
                           const char *name, int restricted,
                           bool ipv4, const char *vnetwork, const char *vhost,
                           bool ipv4, const char *vnetwork, const char *vhost,
@@ -279,17 +296,6 @@ static int net_slirp_init(NetClientState *peer, const char *model,
     }
     }
 #endif
 #endif
 
 
-#if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
-    /* No inet_pton helper before Vista... */
-    if (vprefix6) {
-        /* Unsupported */
-        error_setg(errp, "IPv6 prefix not supported");
-        return -1;
-    }
-    memset(&ip6_prefix, 0, sizeof(ip6_prefix));
-    ip6_prefix.s6_addr[0] = 0xfe;
-    ip6_prefix.s6_addr[1] = 0xc0;
-#else
     if (!vprefix6) {
     if (!vprefix6) {
         vprefix6 = "fec0::";
         vprefix6 = "fec0::";
     }
     }
@@ -297,7 +303,6 @@ static int net_slirp_init(NetClientState *peer, const char *model,
         error_setg(errp, "Failed to parse IPv6 prefix");
         error_setg(errp, "Failed to parse IPv6 prefix");
         return -1;
         return -1;
     }
     }
-#endif
 
 
     if (!vprefix6_len) {
     if (!vprefix6_len) {
         vprefix6_len = 64;
         vprefix6_len = 64;
@@ -309,10 +314,6 @@ static int net_slirp_init(NetClientState *peer, const char *model,
     }
     }
 
 
     if (vhost6) {
     if (vhost6) {
-#if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
-        error_setg(errp, "IPv6 host not supported");
-        return -1;
-#else
         if (!inet_pton(AF_INET6, vhost6, &ip6_host)) {
         if (!inet_pton(AF_INET6, vhost6, &ip6_host)) {
             error_setg(errp, "Failed to parse IPv6 host");
             error_setg(errp, "Failed to parse IPv6 host");
             return -1;
             return -1;
@@ -321,17 +322,12 @@ static int net_slirp_init(NetClientState *peer, const char *model,
             error_setg(errp, "IPv6 Host doesn't belong to network");
             error_setg(errp, "IPv6 Host doesn't belong to network");
             return -1;
             return -1;
         }
         }
-#endif
     } else {
     } else {
         ip6_host = ip6_prefix;
         ip6_host = ip6_prefix;
         ip6_host.s6_addr[15] |= 2;
         ip6_host.s6_addr[15] |= 2;
     }
     }
 
 
     if (vnameserver6) {
     if (vnameserver6) {
-#if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
-        error_setg(errp, "IPv6 DNS not supported");
-        return -1;
-#else
         if (!inet_pton(AF_INET6, vnameserver6, &ip6_dns)) {
         if (!inet_pton(AF_INET6, vnameserver6, &ip6_dns)) {
             error_setg(errp, "Failed to parse IPv6 DNS");
             error_setg(errp, "Failed to parse IPv6 DNS");
             return -1;
             return -1;
@@ -340,7 +336,6 @@ static int net_slirp_init(NetClientState *peer, const char *model,
             error_setg(errp, "IPv6 DNS doesn't belong to network");
             error_setg(errp, "IPv6 DNS doesn't belong to network");
             return -1;
             return -1;
         }
         }
-#endif
     } else {
     } else {
         ip6_dns = ip6_prefix;
         ip6_dns = ip6_prefix;
         ip6_dns.s6_addr[15] |= 3;
         ip6_dns.s6_addr[15] |= 3;
@@ -378,7 +373,8 @@ static int net_slirp_init(NetClientState *peer, const char *model,
                           ipv6, ip6_prefix, vprefix6_len, ip6_host,
                           ipv6, ip6_prefix, vprefix6_len, ip6_host,
                           vhostname, tftp_server_name,
                           vhostname, tftp_server_name,
                           tftp_export, bootfile, dhcp,
                           tftp_export, bootfile, dhcp,
-                          dns, ip6_dns, dnssearch, vdomainname, s);
+                          dns, ip6_dns, dnssearch, vdomainname,
+                          &slirp_cb, s);
     QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
     QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
 
 
     for (config = slirp_configs; config; config = config->next) {
     for (config = slirp_configs; config; config = config->next) {
@@ -708,8 +704,8 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
              CONFIG_SMBD_COMMAND, s->smb_dir, smb_conf);
              CONFIG_SMBD_COMMAND, s->smb_dir, smb_conf);
     g_free(smb_conf);
     g_free(smb_conf);
 
 
-    if (slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 139) < 0 ||
-        slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 445) < 0) {
+    if (slirp_add_exec(s->slirp, NULL, smb_cmdline, &vserver_addr, 139) < 0 ||
+        slirp_add_exec(s->slirp, NULL, smb_cmdline, &vserver_addr, 445) < 0) {
         slirp_smb_cleanup(s);
         slirp_smb_cleanup(s);
         g_free(smb_cmdline);
         g_free(smb_cmdline);
         error_setg(errp, "Conflicting/invalid smbserver address");
         error_setg(errp, "Conflicting/invalid smbserver address");
@@ -773,7 +769,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
     snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port);
     snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port);
 
 
     if ((strlen(p) > 4) && !strncmp(p, "cmd:", 4)) {
     if ((strlen(p) > 4) && !strncmp(p, "cmd:", 4)) {
-        if (slirp_add_exec(s->slirp, 0, &p[4], &server, port) < 0) {
+        if (slirp_add_exec(s->slirp, NULL, &p[4], &server, port) < 0) {
             error_setg(errp, "Conflicting/invalid host:port in guest "
             error_setg(errp, "Conflicting/invalid host:port in guest "
                        "forwarding rule '%s'", config_str);
                        "forwarding rule '%s'", config_str);
             return -1;
             return -1;
@@ -800,7 +796,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
             return -1;
             return -1;
         }
         }
 
 
-        if (slirp_add_exec(s->slirp, 3, &fwd->hd, &server, port) < 0) {
+        if (slirp_add_exec(s->slirp, &fwd->hd, NULL, &server, port) < 0) {
             error_setg(errp, "Conflicting/invalid host:port in guest "
             error_setg(errp, "Conflicting/invalid host:port in guest "
                        "forwarding rule '%s'", config_str);
                        "forwarding rule '%s'", config_str);
             g_free(fwd);
             g_free(fwd);
@@ -827,10 +823,11 @@ void hmp_info_usernet(Monitor *mon, const QDict *qdict)
     QTAILQ_FOREACH(s, &slirp_stacks, entry) {
     QTAILQ_FOREACH(s, &slirp_stacks, entry) {
         int id;
         int id;
         bool got_hub_id = net_hub_id_for_client(&s->nc, &id) == 0;
         bool got_hub_id = net_hub_id_for_client(&s->nc, &id) == 0;
-        monitor_printf(mon, "Hub %d (%s):\n",
+        char *info = slirp_connection_info(s->slirp);
+        monitor_printf(mon, "Hub %d (%s):\n%s",
                        got_hub_id ? id : -1,
                        got_hub_id ? id : -1,
-                       s->nc.name);
-        slirp_connection_info(s->slirp, mon);
+                       s->nc.name, info);
+        g_free(info);
     }
     }
 }
 }
 
 

+ 55 - 0
net/util.h

@@ -26,6 +26,61 @@
 #define QEMU_NET_UTIL_H
 #define QEMU_NET_UTIL_H
 
 
 
 
+/*
+ * Structure of an internet header, naked of options.
+ */
+struct ip {
+#ifdef HOST_WORDS_BIGENDIAN
+    uint8_t ip_v:4,         /* version */
+            ip_hl:4;        /* header length */
+#else
+    uint8_t ip_hl:4,        /* header length */
+            ip_v:4;         /* version */
+#endif
+    uint8_t ip_tos;         /* type of service */
+    uint16_t ip_len;        /* total length */
+    uint16_t ip_id;         /* identification */
+    uint16_t ip_off;        /* fragment offset field */
+#define IP_DF 0x4000        /* don't fragment flag */
+#define IP_MF 0x2000        /* more fragments flag */
+#define IP_OFFMASK 0x1fff   /* mask for fragmenting bits */
+    uint8_t ip_ttl;         /* time to live */
+    uint8_t ip_p;           /* protocol */
+    uint16_t ip_sum;        /* checksum */
+    struct in_addr ip_src, ip_dst;  /* source and dest address */
+} QEMU_PACKED;
+
+static inline bool in6_equal_net(const struct in6_addr *a,
+                                 const struct in6_addr *b,
+                                 int prefix_len)
+{
+    if (memcmp(a, b, prefix_len / 8) != 0) {
+        return 0;
+    }
+
+    if (prefix_len % 8 == 0) {
+        return 1;
+    }
+
+    return a->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8))
+        == b->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8));
+}
+
+#define TCPS_CLOSED             0       /* closed */
+#define TCPS_LISTEN             1       /* listening for connection */
+#define TCPS_SYN_SENT           2       /* active, have sent syn */
+#define TCPS_SYN_RECEIVED       3       /* have send and received syn */
+/* states < TCPS_ESTABLISHED are those where connections not established */
+#define TCPS_ESTABLISHED        4       /* established */
+#define TCPS_CLOSE_WAIT         5       /* rcvd fin, waiting for close */
+/* states > TCPS_CLOSE_WAIT are those where user has closed */
+#define TCPS_FIN_WAIT_1         6       /* have closed, sent fin */
+#define TCPS_CLOSING            7       /* closed xchd FIN; await FIN ACK */
+#define TCPS_LAST_ACK           8       /* had fin and close; await FIN ACK */
+/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */
+#define TCPS_FIN_WAIT_2         9       /* have closed, fin is acked */
+#define TCPS_TIME_WAIT          10      /* in 2*msl quiet wait after close */
+
 int net_parse_macaddr(uint8_t *macaddr, const char *p);
 int net_parse_macaddr(uint8_t *macaddr, const char *p);
 
 
 #endif /* QEMU_NET_UTIL_H */
 #endif /* QEMU_NET_UTIL_H */

+ 32 - 5
slirp/Makefile.objs

@@ -1,5 +1,32 @@
-common-obj-y = cksum.o if.o ip_icmp.o ip6_icmp.o ip6_input.o ip6_output.o \
-               ip_input.o ip_output.o dnssearch.o dhcpv6.o
-common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
-common-obj-y += tcp_subr.o tcp_timer.o udp.o udp6.o bootp.o tftp.o arp_table.o \
-                ndp_table.o ncsi.o
+slirp-obj-y = slirp.mo
+
+slirp.mo-objs = \
+	arp_table.o \
+	bootp.o \
+	cksum.o \
+	dhcpv6.o \
+	dnssearch.o \
+	if.o \
+	ip6_icmp.o \
+	ip6_input.o \
+	ip6_output.o \
+	ip_icmp.o \
+	ip_input.o \
+	ip_output.o \
+	mbuf.o \
+	misc.o \
+	ncsi.o \
+	ndp_table.o \
+	sbuf.o \
+	slirp.o \
+	socket.o \
+	tcp_input.o \
+	tcp_output.o \
+	tcp_subr.o \
+	tcp_timer.o \
+	tftp.o \
+	udp.o \
+	udp6.o \
+	$(NULL)
+
+slirp.mo-cflags = -DG_LOG_DOMAIN=\"Slirp\"

+ 6 - 6
slirp/arp_table.c

@@ -34,9 +34,9 @@ void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN])
 
 
     DEBUG_CALL("arp_table_add");
     DEBUG_CALL("arp_table_add");
     DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){.s_addr = ip_addr}));
     DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){.s_addr = ip_addr}));
-    DEBUG_ARGS((dfd, " hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
-                ethaddr[0], ethaddr[1], ethaddr[2],
-                ethaddr[3], ethaddr[4], ethaddr[5]));
+    DEBUG_ARG("hw addr = %02x:%02x:%02x:%02x:%02x:%02x",
+              ethaddr[0], ethaddr[1], ethaddr[2],
+              ethaddr[3], ethaddr[4], ethaddr[5]);
 
 
     if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
     if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
         /* Do not register broadcast addresses */
         /* Do not register broadcast addresses */
@@ -79,9 +79,9 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
     for (i = 0; i < ARP_TABLE_SIZE; i++) {
     for (i = 0; i < ARP_TABLE_SIZE; i++) {
         if (arptbl->table[i].ar_sip == ip_addr) {
         if (arptbl->table[i].ar_sip == ip_addr) {
             memcpy(out_ethaddr, arptbl->table[i].ar_sha,  ETH_ALEN);
             memcpy(out_ethaddr, arptbl->table[i].ar_sha,  ETH_ALEN);
-            DEBUG_ARGS((dfd, " found hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
-                        out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
-                        out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]));
+            DEBUG_ARG("found hw addr = %02x:%02x:%02x:%02x:%02x:%02x",
+                      out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
+                      out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]);
             return 1;
             return 1;
         }
         }
     }
     }

+ 3 - 7
slirp/bootp.c

@@ -36,12 +36,7 @@
 
 
 static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
 static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
 
 
-#ifdef DEBUG
-#define DPRINTF(fmt, ...) \
-do if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ##  __VA_ARGS__); fflush(dfd); } while (0)
-#else
-#define DPRINTF(fmt, ...) do{}while(0)
-#endif
+#define DPRINTF(fmt, ...) DEBUG_CALL(fmt, ##__VA_ARGS__)
 
 
 static BOOTPClient *get_new_addr(Slirp *slirp, struct in_addr *paddr,
 static BOOTPClient *get_new_addr(Slirp *slirp, struct in_addr *paddr,
                                  const uint8_t *macaddr)
                                  const uint8_t *macaddr)
@@ -167,8 +162,9 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
     DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type);
     DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type);
     if (preq_addr.s_addr != htonl(0L))
     if (preq_addr.s_addr != htonl(0L))
         DPRINTF(" req_addr=%08" PRIx32 "\n", ntohl(preq_addr.s_addr));
         DPRINTF(" req_addr=%08" PRIx32 "\n", ntohl(preq_addr.s_addr));
-    else
+    else {
         DPRINTF("\n");
         DPRINTF("\n");
+    }
 
 
     if (dhcp_msg_type == 0)
     if (dhcp_msg_type == 0)
         dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */
         dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */

+ 2 - 6
slirp/cksum.c

@@ -70,9 +70,7 @@ int cksum(struct mbuf *m, int len)
 
 
 	if (len < mlen)
 	if (len < mlen)
 	   mlen = len;
 	   mlen = len;
-#ifdef DEBUG
 	len -= mlen;
 	len -= mlen;
-#endif
 	/*
 	/*
 	 * Force to even boundary.
 	 * Force to even boundary.
 	 */
 	 */
@@ -122,12 +120,10 @@ int cksum(struct mbuf *m, int len)
 	   s_util.c[0] = *(uint8_t *)w;
 	   s_util.c[0] = *(uint8_t *)w;
 
 
 cont:
 cont:
-#ifdef DEBUG
 	if (len) {
 	if (len) {
-		DEBUG_ERROR((dfd, "cksum: out of data\n"));
-		DEBUG_ERROR((dfd, " len = %d\n", len));
+		DEBUG_ERROR("cksum: out of data");
+		DEBUG_ERROR(" len = %d", len);
 	}
 	}
-#endif
 	if (mlen == -1) {
 	if (mlen == -1) {
 		/* The last mbuf has odd # of bytes. Follow the
 		/* The last mbuf has odd # of bytes. Follow the
 		 standard (the odd byte may be shifted left by 8 bits
 		 standard (the odd byte may be shifted left by 8 bits

+ 27 - 20
slirp/debug.h

@@ -5,30 +5,37 @@
  * terms and conditions of the copyright.
  * terms and conditions of the copyright.
  */
  */
 
 
-//#define DEBUG 1
-
-#ifdef DEBUG
+#ifndef DEBUG_H_
+#define DEBUG_H_
 
 
 #define DBG_CALL 0x1
 #define DBG_CALL 0x1
 #define DBG_MISC 0x2
 #define DBG_MISC 0x2
 #define DBG_ERROR 0x4
 #define DBG_ERROR 0x4
 
 
-#define dfd stderr
-
 extern int slirp_debug;
 extern int slirp_debug;
 
 
-#define DEBUG_CALL(x) if (slirp_debug & DBG_CALL) { fprintf(dfd, "%s...\n", x); fflush(dfd); }
-#define DEBUG_ARG(x, y) if (slirp_debug & DBG_CALL) { fputc(' ', dfd); fprintf(dfd, x, y); fputc('\n', dfd); fflush(dfd); }
-#define DEBUG_ARGS(x) if (slirp_debug & DBG_CALL) { fprintf x ; fflush(dfd); }
-#define DEBUG_MISC(x) if (slirp_debug & DBG_MISC) { fprintf x ; fflush(dfd); }
-#define DEBUG_ERROR(x) if (slirp_debug & DBG_ERROR) {fprintf x ; fflush(dfd); }
-
-#else
-
-#define DEBUG_CALL(x)
-#define DEBUG_ARG(x, y)
-#define DEBUG_ARGS(x)
-#define DEBUG_MISC(x)
-#define DEBUG_ERROR(x)
-
-#endif
+#define DEBUG_CALL(fmt, ...) do {               \
+    if (G_UNLIKELY(slirp_debug & DBG_CALL)) {   \
+        g_debug(fmt "...", ##__VA_ARGS__);      \
+    }                                           \
+} while (0)
+
+#define DEBUG_ARG(fmt, ...) do {                \
+    if (G_UNLIKELY(slirp_debug & DBG_CALL)) {   \
+        g_debug(" " fmt, ##__VA_ARGS__);        \
+    }                                           \
+} while (0)
+
+#define DEBUG_MISC(fmt, ...) do {               \
+    if (G_UNLIKELY(slirp_debug & DBG_MISC)) {   \
+        g_debug(fmt, ##__VA_ARGS__);            \
+    }                                           \
+} while (0)
+
+#define DEBUG_ERROR(fmt, ...) do {              \
+    if (G_UNLIKELY(slirp_debug & DBG_ERROR)) {  \
+        g_debug(fmt, ##__VA_ARGS__);            \
+    }                                           \
+} while (0)
+
+#endif /* DEBUG_H_ */

+ 8 - 9
slirp/dhcpv6.c

@@ -50,7 +50,7 @@ struct requested_infos {
  * the odata region, thus the caller must keep odata valid as long as it
  * the odata region, thus the caller must keep odata valid as long as it
  * needs to access the requested_infos struct.
  * needs to access the requested_infos struct.
  */
  */
-static int dhcpv6_parse_info_request(uint8_t *odata, int olen,
+static int dhcpv6_parse_info_request(Slirp *slirp, uint8_t *odata, int olen,
                                      struct requested_infos *ri)
                                      struct requested_infos *ri)
 {
 {
     int i, req_opt;
     int i, req_opt;
@@ -61,7 +61,7 @@ static int dhcpv6_parse_info_request(uint8_t *odata, int olen,
         int len = odata[2] << 8 | odata[3];
         int len = odata[2] << 8 | odata[3];
 
 
         if (len + 4 > olen) {
         if (len + 4 > olen) {
-            qemu_log_mask(LOG_GUEST_ERROR, "Guest sent bad DHCPv6 packet!\n");
+            slirp->cb->guest_error("Guest sent bad DHCPv6 packet!");
             return -E2BIG;
             return -E2BIG;
         }
         }
 
 
@@ -92,14 +92,14 @@ static int dhcpv6_parse_info_request(uint8_t *odata, int olen,
                     ri->want_boot_url = true;
                     ri->want_boot_url = true;
                     break;
                     break;
                 default:
                 default:
-                    DEBUG_MISC((dfd, "dhcpv6: Unsupported option request %d\n",
-                                req_opt));
+                    DEBUG_MISC("dhcpv6: Unsupported option request %d",
+                               req_opt);
                 }
                 }
             }
             }
             break;
             break;
         default:
         default:
-            DEBUG_MISC((dfd, "dhcpv6 info req: Unsupported option %d, len=%d\n",
-                        option, len));
+            DEBUG_MISC("dhcpv6 info req: Unsupported option %d, len=%d",
+                       option, len);
         }
         }
 
 
         odata += len + 4;
         odata += len + 4;
@@ -121,7 +121,7 @@ static void dhcpv6_info_request(Slirp *slirp, struct sockaddr_in6 *srcsas,
     struct mbuf *m;
     struct mbuf *m;
     uint8_t *resp;
     uint8_t *resp;
 
 
-    if (dhcpv6_parse_info_request(odata, olen, &ri) < 0) {
+    if (dhcpv6_parse_info_request(slirp, odata, olen, &ri) < 0) {
         return;
         return;
     }
     }
 
 
@@ -203,7 +203,6 @@ void dhcpv6_input(struct sockaddr_in6 *srcsas, struct mbuf *m)
         dhcpv6_info_request(m->slirp, srcsas, xid, &data[4], data_len - 4);
         dhcpv6_info_request(m->slirp, srcsas, xid, &data[4], data_len - 4);
         break;
         break;
     default:
     default:
-        DEBUG_MISC((dfd, "dhcpv6_input: Unsupported message type 0x%x\n",
-                    data[0]));
+        DEBUG_MISC("dhcpv6_input: Unsupported message type 0x%x", data[0]);
     }
     }
 }
 }

+ 1 - 3
slirp/if.c

@@ -131,12 +131,10 @@ diddit:
 		}
 		}
 	}
 	}
 
 
-#ifndef FULL_BOLT
 	/*
 	/*
 	 * This prevents us from malloc()ing too many mbufs
 	 * This prevents us from malloc()ing too many mbufs
 	 */
 	 */
 	if_start(ifm->slirp);
 	if_start(ifm->slirp);
-#endif
 }
 }
 
 
 /*
 /*
@@ -150,7 +148,7 @@ diddit:
  */
  */
 void if_start(Slirp *slirp)
 void if_start(Slirp *slirp)
 {
 {
-    uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
+    uint64_t now = slirp->cb->clock_get_ns();
     bool from_batchq = false;
     bool from_batchq = false;
     struct mbuf *ifm, *ifm_next, *ifqt;
     struct mbuf *ifm, *ifm_next, *ifqt;
 
 

+ 6 - 4
slirp/ip.h

@@ -33,7 +33,9 @@
 #ifndef IP_H
 #ifndef IP_H
 #define IP_H
 #define IP_H
 
 
-#ifdef HOST_WORDS_BIGENDIAN
+#include <glib.h>
+
+#if G_BYTE_ORDER == G_BIG_ENDIAN
 # undef NTOHL
 # undef NTOHL
 # undef NTOHS
 # undef NTOHS
 # undef HTONL
 # undef HTONL
@@ -69,7 +71,7 @@ typedef uint32_t n_long;                 /* long as received from the net */
  * Structure of an internet header, naked of options.
  * Structure of an internet header, naked of options.
  */
  */
 struct ip {
 struct ip {
-#ifdef HOST_WORDS_BIGENDIAN
+#if G_BYTE_ORDER == G_BIG_ENDIAN
 	uint8_t ip_v:4,			/* version */
 	uint8_t ip_v:4,			/* version */
 		ip_hl:4;		/* header length */
 		ip_hl:4;		/* header length */
 #else
 #else
@@ -135,7 +137,7 @@ struct	ip_timestamp {
 	uint8_t	ipt_code;		/* IPOPT_TS */
 	uint8_t	ipt_code;		/* IPOPT_TS */
 	uint8_t	ipt_len;		/* size of structure (variable) */
 	uint8_t	ipt_len;		/* size of structure (variable) */
 	uint8_t	ipt_ptr;		/* index of current entry */
 	uint8_t	ipt_ptr;		/* index of current entry */
-#ifdef HOST_WORDS_BIGENDIAN
+#if G_BYTE_ORDER == G_BIG_ENDIAN
 	uint8_t	ipt_oflw:4,		/* overflow counter */
 	uint8_t	ipt_oflw:4,		/* overflow counter */
 		ipt_flg:4;		/* flags, see below */
 		ipt_flg:4;		/* flags, see below */
 #else
 #else
@@ -175,7 +177,7 @@ struct	ip_timestamp {
 
 
 #define	IP_MSS		576		/* default maximum segment size */
 #define	IP_MSS		576		/* default maximum segment size */
 
 
-#if SIZEOF_CHAR_P == 4
+#if GLIB_SIZEOF_VOID_P == 4
 struct mbuf_ptr {
 struct mbuf_ptr {
 	struct mbuf *mptr;
 	struct mbuf *mptr;
 	uint32_t dummy;
 	uint32_t dummy;

+ 2 - 1
slirp/ip6.h

@@ -6,6 +6,7 @@
 #ifndef SLIRP_IP6_H
 #ifndef SLIRP_IP6_H
 #define SLIRP_IP6_H
 #define SLIRP_IP6_H
 
 
+#include <glib.h>
 #include "net/eth.h"
 #include "net/eth.h"
 
 
 #define ALLNODES_MULTICAST  { .s6_addr = \
 #define ALLNODES_MULTICAST  { .s6_addr = \
@@ -113,7 +114,7 @@ static inline void in6_compute_ethaddr(struct in6_addr ip,
  * Structure of an internet header, naked of options.
  * Structure of an internet header, naked of options.
  */
  */
 struct ip6 {
 struct ip6 {
-#ifdef HOST_WORDS_BIGENDIAN
+#if G_BYTE_ORDER == G_BIG_ENDIAN
     uint32_t
     uint32_t
         ip_v:4,         /* version */
         ip_v:4,         /* version */
         ip_tc_hi:4,     /* traffic class */
         ip_tc_hi:4,     /* traffic class */

+ 12 - 15
slirp/ip6_icmp.c

@@ -17,7 +17,7 @@ static void ra_timer_handler(void *opaque)
 {
 {
     Slirp *slirp = opaque;
     Slirp *slirp = opaque;
     timer_mod(slirp->ra_timer,
     timer_mod(slirp->ra_timer,
-              qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + NDP_Interval);
+              slirp->cb->clock_get_ns() / SCALE_MS + NDP_Interval);
     ndp_send_ra(slirp);
     ndp_send_ra(slirp);
 }
 }
 
 
@@ -31,7 +31,7 @@ void icmp6_init(Slirp *slirp)
                                      SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
                                      SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
                                      ra_timer_handler, slirp);
                                      ra_timer_handler, slirp);
     timer_mod(slirp->ra_timer,
     timer_mod(slirp->ra_timer,
-              qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + NDP_Interval);
+              slirp->cb->clock_get_ns() / SCALE_MS + NDP_Interval);
 }
 }
 
 
 void icmp6_cleanup(Slirp *slirp)
 void icmp6_cleanup(Slirp *slirp)
@@ -74,9 +74,10 @@ void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code)
     Slirp *slirp = m->slirp;
     Slirp *slirp = m->slirp;
     struct mbuf *t;
     struct mbuf *t;
     struct ip6 *ip = mtod(m, struct ip6 *);
     struct ip6 *ip = mtod(m, struct ip6 *);
+    char addrstr[INET6_ADDRSTRLEN];
 
 
     DEBUG_CALL("icmp6_send_error");
     DEBUG_CALL("icmp6_send_error");
-    DEBUG_ARGS((dfd, " type = %d, code = %d\n", type, code));
+    DEBUG_ARG("type = %d, code = %d", type, code);
 
 
     if (IN6_IS_ADDR_MULTICAST(&ip->ip_src) ||
     if (IN6_IS_ADDR_MULTICAST(&ip->ip_src) ||
             in6_zero(&ip->ip_src)) {
             in6_zero(&ip->ip_src)) {
@@ -90,11 +91,8 @@ void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code)
     struct ip6 *rip = mtod(t, struct ip6 *);
     struct ip6 *rip = mtod(t, struct ip6 *);
     rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR;
     rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR;
     rip->ip_dst = ip->ip_src;
     rip->ip_dst = ip->ip_src;
-#if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600)
-    char addrstr[INET6_ADDRSTRLEN];
     inet_ntop(AF_INET6, &rip->ip_dst, addrstr, INET6_ADDRSTRLEN);
     inet_ntop(AF_INET6, &rip->ip_dst, addrstr, INET6_ADDRSTRLEN);
     DEBUG_ARG("target = %s", addrstr);
     DEBUG_ARG("target = %s", addrstr);
-#endif
 
 
     rip->ip_nh = IPPROTO_ICMPV6;
     rip->ip_nh = IPPROTO_ICMPV6;
     const int error_data_len = MIN(m->m_len,
     const int error_data_len = MIN(m->m_len,
@@ -222,12 +220,12 @@ void ndp_send_ra(Slirp *slirp)
  */
  */
 void ndp_send_ns(Slirp *slirp, struct in6_addr addr)
 void ndp_send_ns(Slirp *slirp, struct in6_addr addr)
 {
 {
-    DEBUG_CALL("ndp_send_ns");
-#if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600)
     char addrstr[INET6_ADDRSTRLEN];
     char addrstr[INET6_ADDRSTRLEN];
+
     inet_ntop(AF_INET6, &addr, addrstr, INET6_ADDRSTRLEN);
     inet_ntop(AF_INET6, &addr, addrstr, INET6_ADDRSTRLEN);
+
+    DEBUG_CALL("ndp_send_ns");
     DEBUG_ARG("target = %s", addrstr);
     DEBUG_ARG("target = %s", addrstr);
-#endif
 
 
     /* Build IPv6 packet */
     /* Build IPv6 packet */
     struct mbuf *t = m_get(slirp);
     struct mbuf *t = m_get(slirp);
@@ -342,8 +340,7 @@ static void ndp_input(struct mbuf *m, Slirp *slirp, struct ip6 *ip,
 
 
     case ICMP6_NDP_RA:
     case ICMP6_NDP_RA:
         DEBUG_CALL(" type = Router Advertisement");
         DEBUG_CALL(" type = Router Advertisement");
-        qemu_log_mask(LOG_GUEST_ERROR,
-                "Warning: guest sent NDP RA, but shouldn't");
+        slirp->cb->guest_error("Warning: guest sent NDP RA, but shouldn't");
         break;
         break;
 
 
     case ICMP6_NDP_NS:
     case ICMP6_NDP_NS:
@@ -376,8 +373,8 @@ static void ndp_input(struct mbuf *m, Slirp *slirp, struct ip6 *ip,
 
 
     case ICMP6_NDP_REDIRECT:
     case ICMP6_NDP_REDIRECT:
         DEBUG_CALL(" type = Redirect");
         DEBUG_CALL(" type = Redirect");
-        qemu_log_mask(LOG_GUEST_ERROR,
-                "Warning: guest sent NDP REDIRECT, but shouldn't");
+        slirp->cb->guest_error(
+            "Warning: guest sent NDP REDIRECT, but shouldn't");
         break;
         break;
     }
     }
 }
 }
@@ -393,7 +390,7 @@ void icmp6_input(struct mbuf *m)
     int hlen = sizeof(struct ip6);
     int hlen = sizeof(struct ip6);
 
 
     DEBUG_CALL("icmp6_input");
     DEBUG_CALL("icmp6_input");
-    DEBUG_ARG("m = %lx", (long) m);
+    DEBUG_ARG("m = %p", m);
     DEBUG_ARG("m_len = %d", m->m_len);
     DEBUG_ARG("m_len = %d", m->m_len);
 
 
     if (ntohs(ip->ip_pl) < ICMP6_MINLEN) {
     if (ntohs(ip->ip_pl) < ICMP6_MINLEN) {
@@ -417,7 +414,7 @@ void icmp6_input(struct mbuf *m)
             icmp6_send_echoreply(m, slirp, ip, icmp);
             icmp6_send_echoreply(m, slirp, ip, icmp);
         } else {
         } else {
             /* TODO */
             /* TODO */
-            error_report("external icmpv6 not supported yet");
+            g_critical("external icmpv6 not supported yet");
         }
         }
         break;
         break;
 
 

+ 3 - 3
slirp/ip6_icmp.h

@@ -34,7 +34,7 @@ struct ndp_rs {     /* Router Solicitation Message */
 
 
 struct ndp_ra {     /* Router Advertisement Message */
 struct ndp_ra {     /* Router Advertisement Message */
     uint8_t chl;    /* Cur Hop Limit */
     uint8_t chl;    /* Cur Hop Limit */
-#ifdef HOST_WORDS_BIGENDIAN
+#if G_BYTE_ORDER == G_BIG_ENDIAN
     uint8_t
     uint8_t
         M:1,
         M:1,
         O:1,
         O:1,
@@ -56,7 +56,7 @@ struct ndp_ns {     /* Neighbor Solicitation Message */
 } QEMU_PACKED;
 } QEMU_PACKED;
 
 
 struct ndp_na {     /* Neighbor Advertisement Message */
 struct ndp_na {     /* Neighbor Advertisement Message */
-#ifdef HOST_WORDS_BIGENDIAN
+#if G_BYTE_ORDER == G_BIG_ENDIAN
     uint32_t
     uint32_t
         R:1,                /* Router Flag */
         R:1,                /* Router Flag */
         S:1,                /* Solicited Flag */
         S:1,                /* Solicited Flag */
@@ -125,7 +125,7 @@ struct ndpopt {
 #define ndpopt_linklayer ndpopt_body.linklayer_addr
 #define ndpopt_linklayer ndpopt_body.linklayer_addr
         struct prefixinfo {                     /* Prefix Information */
         struct prefixinfo {                     /* Prefix Information */
             uint8_t     prefix_length;
             uint8_t     prefix_length;
-#ifdef HOST_WORDS_BIGENDIAN
+#if G_BYTE_ORDER == G_BIG_ENDIAN
             uint8_t     L:1, A:1, reserved1:6;
             uint8_t     L:1, A:1, reserved1:6;
 #else
 #else
             uint8_t     reserved1:6, A:1, L:1;
             uint8_t     reserved1:6, A:1, L:1;

+ 1 - 1
slirp/ip6_input.c

@@ -31,7 +31,7 @@ void ip6_input(struct mbuf *m)
     }
     }
 
 
     DEBUG_CALL("ip6_input");
     DEBUG_CALL("ip6_input");
-    DEBUG_ARG("m = %lx", (long)m);
+    DEBUG_ARG("m = %p", m);
     DEBUG_ARG("m_len = %d", m->m_len);
     DEBUG_ARG("m_len = %d", m->m_len);
 
 
     if (m->m_len < sizeof(struct ip6)) {
     if (m->m_len < sizeof(struct ip6)) {

+ 2 - 2
slirp/ip6_output.c

@@ -19,8 +19,8 @@ int ip6_output(struct socket *so, struct mbuf *m, int fast)
     struct ip6 *ip = mtod(m, struct ip6 *);
     struct ip6 *ip = mtod(m, struct ip6 *);
 
 
     DEBUG_CALL("ip6_output");
     DEBUG_CALL("ip6_output");
-    DEBUG_ARG("so = %lx", (long)so);
-    DEBUG_ARG("m = %lx", (long)m);
+    DEBUG_ARG("so = %p", so);
+    DEBUG_ARG("m = %p", m);
 
 
     /* Fill IPv6 header */
     /* Fill IPv6 header */
     ip->ip_v = IP6VERSION;
     ip->ip_v = IP6VERSION;

+ 16 - 15
slirp/ip_icmp.c

@@ -34,6 +34,10 @@
 #include "slirp.h"
 #include "slirp.h"
 #include "ip_icmp.h"
 #include "ip_icmp.h"
 
 
+#ifndef WITH_ICMP_ERROR_MSG
+#define WITH_ICMP_ERROR_MSG 0
+#endif
+
 /* The message sent when emulating PING */
 /* The message sent when emulating PING */
 /* Be nice and tell them it's just a pseudo-ping packet */
 /* Be nice and tell them it's just a pseudo-ping packet */
 static const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
 static const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
@@ -99,8 +103,8 @@ static int icmp_send(struct socket *so, struct mbuf *m, int hlen)
 
 
     if (sendto(so->s, m->m_data + hlen, m->m_len - hlen, 0,
     if (sendto(so->s, m->m_data + hlen, m->m_len - hlen, 0,
                (struct sockaddr *)&addr, sizeof(addr)) == -1) {
                (struct sockaddr *)&addr, sizeof(addr)) == -1) {
-        DEBUG_MISC((dfd, "icmp_input icmp sendto tx errno = %d-%s\n",
-                    errno, strerror(errno)));
+        DEBUG_MISC("icmp_input icmp sendto tx errno = %d-%s",
+                   errno, strerror(errno));
         icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno));
         icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno));
         icmp_detach(so);
         icmp_detach(so);
     }
     }
@@ -165,8 +169,8 @@ icmp_input(struct mbuf *m, int hlen)
         return;
         return;
       }
       }
       if (udp_attach(so, AF_INET) == -1) {
       if (udp_attach(so, AF_INET) == -1) {
-	DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
-		    errno,strerror(errno)));
+	DEBUG_MISC("icmp_input udp_attach errno = %d-%s",
+               errno,strerror(errno));
 	sofree(so);
 	sofree(so);
 	m_free(m);
 	m_free(m);
 	goto end_error;
 	goto end_error;
@@ -188,8 +192,8 @@ icmp_input(struct mbuf *m, int hlen)
 
 
       if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,
       if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,
 		(struct sockaddr *)&addr, sockaddr_size(&addr)) == -1) {
 		(struct sockaddr *)&addr, sockaddr_size(&addr)) == -1) {
-	DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
-		    errno,strerror(errno)));
+	DEBUG_MISC("icmp_input udp sendto tx errno = %d-%s",
+               errno,strerror(errno));
 	icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno));
 	icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno));
 	udp_detach(so);
 	udp_detach(so);
       }
       }
@@ -253,13 +257,12 @@ icmp_send_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
   /* check msrc */
   /* check msrc */
   if(!msrc) goto end_error;
   if(!msrc) goto end_error;
   ip = mtod(msrc, struct ip *);
   ip = mtod(msrc, struct ip *);
-#ifdef DEBUG
-  { char bufa[20], bufb[20];
+  if (slirp_debug & DBG_MISC) {
+    char bufa[20], bufb[20];
     strcpy(bufa, inet_ntoa(ip->ip_src));
     strcpy(bufa, inet_ntoa(ip->ip_src));
     strcpy(bufb, inet_ntoa(ip->ip_dst));
     strcpy(bufb, inet_ntoa(ip->ip_dst));
-    DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb));
+    DEBUG_MISC(" %.16s to %.16s", bufa, bufb);
   }
   }
-#endif
   if(ip->ip_off & IP_OFFMASK) goto end_error;    /* Only reply to fragment 0 */
   if(ip->ip_off & IP_OFFMASK) goto end_error;    /* Only reply to fragment 0 */
 
 
   /* Do not reply to source-only IPs */
   /* Do not reply to source-only IPs */
@@ -319,8 +322,7 @@ icmp_send_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
   HTONS(icp->icmp_ip.ip_id);
   HTONS(icp->icmp_ip.ip_id);
   HTONS(icp->icmp_ip.ip_off);
   HTONS(icp->icmp_ip.ip_off);
 
 
-#ifdef DEBUG
-  if(message) {           /* DEBUG : append message to ICMP packet */
+  if (message && WITH_ICMP_ERROR_MSG) { /* append message to ICMP packet */
     int message_len;
     int message_len;
     char *cpnt;
     char *cpnt;
     message_len=strlen(message);
     message_len=strlen(message);
@@ -329,7 +331,6 @@ icmp_send_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
     memcpy(cpnt, message, message_len);
     memcpy(cpnt, message, message_len);
     m->m_len+=message_len;
     m->m_len+=message_len;
   }
   }
-#endif
 
 
   icp->icmp_cksum = 0;
   icp->icmp_cksum = 0;
   icp->icmp_cksum = cksum(m, m->m_len);
   icp->icmp_cksum = cksum(m, m->m_len);
@@ -457,8 +458,8 @@ void icmp_receive(struct socket *so)
         } else {
         } else {
             error_code = ICMP_UNREACH_HOST;
             error_code = ICMP_UNREACH_HOST;
         }
         }
-        DEBUG_MISC((dfd, " udp icmp rx errno = %d-%s\n", errno,
-                    strerror(errno)));
+        DEBUG_MISC(" udp icmp rx errno = %d-%s", errno,
+                   strerror(errno));
         icmp_send_error(so->so_m, ICMP_UNREACH, error_code, 0, strerror(errno));
         icmp_send_error(so->so_m, ICMP_UNREACH, error_code, 0, strerror(errno));
     } else {
     } else {
         icmp_reflect(so->so_m);
         icmp_reflect(so->so_m);

+ 0 - 200
slirp/ip_input.c

@@ -447,206 +447,6 @@ ip_slowtimo(Slirp *slirp)
     }
     }
 }
 }
 
 
-/*
- * Do option processing on a datagram,
- * possibly discarding it if bad options are encountered,
- * or forwarding it if source-routed.
- * Returns 1 if packet has been forwarded/freed,
- * 0 if the packet should be processed further.
- */
-
-#ifdef notdef
-
-int
-ip_dooptions(m)
-	struct mbuf *m;
-{
-	register struct ip *ip = mtod(m, struct ip *);
-	register u_char *cp;
-	register struct ip_timestamp *ipt;
-	register struct in_ifaddr *ia;
-	int opt, optlen, cnt, off, code, type, forward = 0;
-	struct in_addr *sin, dst;
-typedef uint32_t n_time;
-	n_time ntime;
-
-	dst = ip->ip_dst;
-	cp = (u_char *)(ip + 1);
-	cnt = (ip->ip_hl << 2) - sizeof (struct ip);
-	for (; cnt > 0; cnt -= optlen, cp += optlen) {
-		opt = cp[IPOPT_OPTVAL];
-		if (opt == IPOPT_EOL)
-			break;
-		if (opt == IPOPT_NOP)
-			optlen = 1;
-		else {
-			optlen = cp[IPOPT_OLEN];
-			if (optlen <= 0 || optlen > cnt) {
-				code = &cp[IPOPT_OLEN] - (u_char *)ip;
-				goto bad;
-			}
-		}
-		switch (opt) {
-
-		default:
-			break;
-
-		/*
-		 * Source routing with record.
-		 * Find interface with current destination address.
-		 * If none on this machine then drop if strictly routed,
-		 * or do nothing if loosely routed.
-		 * Record interface address and bring up next address
-		 * component.  If strictly routed make sure next
-		 * address is on directly accessible net.
-		 */
-		case IPOPT_LSRR:
-		case IPOPT_SSRR:
-			if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
-				code = &cp[IPOPT_OFFSET] - (u_char *)ip;
-				goto bad;
-			}
-			ipaddr.sin_addr = ip->ip_dst;
-			ia = (struct in_ifaddr *)
-				ifa_ifwithaddr((struct sockaddr *)&ipaddr);
-			if (ia == 0) {
-				if (opt == IPOPT_SSRR) {
-					type = ICMP_UNREACH;
-					code = ICMP_UNREACH_SRCFAIL;
-					goto bad;
-				}
-				/*
-				 * Loose routing, and not at next destination
-				 * yet; nothing to do except forward.
-				 */
-				break;
-			}
-                        off--; /* 0 origin */
-			if (off > optlen - sizeof(struct in_addr)) {
-				/*
-				 * End of source route.  Should be for us.
-				 */
-				save_rte(cp, ip->ip_src);
-				break;
-			}
-			/*
-			 * locate outgoing interface
-			 */
-			bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,
-			    sizeof(ipaddr.sin_addr));
-			if (opt == IPOPT_SSRR) {
-#define	INA	struct in_ifaddr *
-#define	SA	struct sockaddr *
-			    if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
-				ia = (INA)ifa_ifwithnet((SA)&ipaddr);
-			} else
-				ia = ip_rtaddr(ipaddr.sin_addr);
-			if (ia == 0) {
-				type = ICMP_UNREACH;
-				code = ICMP_UNREACH_SRCFAIL;
-				goto bad;
-			}
-			ip->ip_dst = ipaddr.sin_addr;
-			bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
-			    (caddr_t)(cp + off), sizeof(struct in_addr));
-			cp[IPOPT_OFFSET] += sizeof(struct in_addr);
-			/*
-			 * Let ip_intr's mcast routing check handle mcast pkts
-			 */
-			forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));
-			break;
-
-		case IPOPT_RR:
-			if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
-				code = &cp[IPOPT_OFFSET] - (u_char *)ip;
-				goto bad;
-			}
-			/*
-			 * If no space remains, ignore.
-			 */
-                        off--; /* 0 origin */
-			if (off > optlen - sizeof(struct in_addr))
-				break;
-			bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
-			    sizeof(ipaddr.sin_addr));
-			/*
-			 * locate outgoing interface; if we're the destination,
-			 * use the incoming interface (should be same).
-			 */
-			if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
-			    (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
-				type = ICMP_UNREACH;
-				code = ICMP_UNREACH_HOST;
-				goto bad;
-			}
-			bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
-			    (caddr_t)(cp + off), sizeof(struct in_addr));
-			cp[IPOPT_OFFSET] += sizeof(struct in_addr);
-			break;
-
-		case IPOPT_TS:
-			code = cp - (u_char *)ip;
-			ipt = (struct ip_timestamp *)cp;
-			if (ipt->ipt_len < 5)
-				goto bad;
-			if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) {
-				if (++ipt->ipt_oflw == 0)
-					goto bad;
-				break;
-			}
-			sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
-			switch (ipt->ipt_flg) {
-
-			case IPOPT_TS_TSONLY:
-				break;
-
-			case IPOPT_TS_TSANDADDR:
-				if (ipt->ipt_ptr + sizeof(n_time) +
-				    sizeof(struct in_addr) > ipt->ipt_len)
-					goto bad;
-				ipaddr.sin_addr = dst;
-				ia = (INA)ifaof_ i f p foraddr((SA)&ipaddr,
-							    m->m_pkthdr.rcvif);
-				if (ia == 0)
-					continue;
-				bcopy((caddr_t)&IA_SIN(ia)->sin_addr,
-				    (caddr_t)sin, sizeof(struct in_addr));
-				ipt->ipt_ptr += sizeof(struct in_addr);
-				break;
-
-			case IPOPT_TS_PRESPEC:
-				if (ipt->ipt_ptr + sizeof(n_time) +
-				    sizeof(struct in_addr) > ipt->ipt_len)
-					goto bad;
-				bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,
-				    sizeof(struct in_addr));
-				if (ifa_ifwithaddr((SA)&ipaddr) == 0)
-					continue;
-				ipt->ipt_ptr += sizeof(struct in_addr);
-				break;
-
-			default:
-				goto bad;
-			}
-			ntime = iptime();
-			bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,
-			    sizeof(n_time));
-			ipt->ipt_ptr += sizeof(n_time);
-		}
-	}
-	if (forward) {
-		ip_forward(m, 1);
-		return (1);
-	}
-	return (0);
-bad:
-	icmp_send_error(m, type, code, 0, 0);
-
-	return (1);
-}
-
-#endif /* notdef */
-
 /*
 /*
  * Strip out IP options, at higher
  * Strip out IP options, at higher
  * level protocol in the kernel.
  * level protocol in the kernel.

+ 19 - 8
slirp/libslirp.h

@@ -5,8 +5,20 @@
 
 
 typedef struct Slirp Slirp;
 typedef struct Slirp Slirp;
 
 
-int get_dns_addr(struct in_addr *pdns_addr);
-int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id);
+/*
+ * Callbacks from slirp
+ *
+ * The opaque parameter comes from the opaque parameter given to slirp_init().
+ */
+typedef struct SlirpCb {
+    /* Send an ethernet frame to the guest network.  */
+    void (*output)(void *opaque, const uint8_t *pkt, int pkt_len);
+    /* Print a message for an error due to guest misbehavior.  */
+    void (*guest_error)(const char *msg);
+    /* Return the virtual clock value in nanoseconds */
+    int64_t (*clock_get_ns)(void);
+} SlirpCb;
+
 
 
 Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
 Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
                   struct in_addr vnetmask, struct in_addr vhost,
                   struct in_addr vnetmask, struct in_addr vhost,
@@ -17,7 +29,9 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
                   const char *tftp_path, const char *bootfile,
                   const char *tftp_path, const char *bootfile,
                   struct in_addr vdhcp_start, struct in_addr vnameserver,
                   struct in_addr vdhcp_start, struct in_addr vnameserver,
                   struct in6_addr vnameserver6, const char **vdnssearch,
                   struct in6_addr vnameserver6, const char **vdnssearch,
-                  const char *vdomainname, void *opaque);
+                  const char *vdomainname,
+                  const SlirpCb *callbacks,
+                  void *opaque);
 void slirp_cleanup(Slirp *slirp);
 void slirp_cleanup(Slirp *slirp);
 
 
 void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout);
 void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout);
@@ -26,18 +40,15 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error);
 
 
 void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);
 void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);
 
 
-/* you must provide the following functions: */
-void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len);
-
 int slirp_add_hostfwd(Slirp *slirp, int is_udp,
 int slirp_add_hostfwd(Slirp *slirp, int is_udp,
                       struct in_addr host_addr, int host_port,
                       struct in_addr host_addr, int host_port,
                       struct in_addr guest_addr, int guest_port);
                       struct in_addr guest_addr, int guest_port);
 int slirp_remove_hostfwd(Slirp *slirp, int is_udp,
 int slirp_remove_hostfwd(Slirp *slirp, int is_udp,
                          struct in_addr host_addr, int host_port);
                          struct in_addr host_addr, int host_port);
-int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
+int slirp_add_exec(Slirp *slirp, void *chardev, const char *cmdline,
                    struct in_addr *guest_addr, int guest_port);
                    struct in_addr *guest_addr, int guest_port);
 
 
-void slirp_connection_info(Slirp *slirp, Monitor *mon);
+char *slirp_connection_info(Slirp *slirp);
 
 
 void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr,
 void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr,
                        int guest_port, const uint8_t *buf, int size);
                        int guest_port, const uint8_t *buf, int size);

+ 0 - 33
slirp/main.h

@@ -8,42 +8,9 @@
 #ifndef SLIRP_MAIN_H
 #ifndef SLIRP_MAIN_H
 #define SLIRP_MAIN_H
 #define SLIRP_MAIN_H
 
 
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-#define TOWRITEMAX 512
-
-extern int slirp_socket;
-extern int slirp_socket_unit;
-extern int slirp_socket_port;
-extern uint32_t slirp_socket_addr;
-extern char *slirp_socket_passwd;
-extern int ctty_closed;
-
-/*
- * Get the difference in 2 times from updtim()
- * Allow for wraparound times, "just in case"
- * x is the greater of the 2 (current time) and y is
- * what it's being compared against.
- */
-#define TIME_DIFF(x,y) (x)-(y) < 0 ? ~0-(y)+(x) : (x)-(y)
-
-extern char *slirp_tty;
-extern char *exec_shell;
 extern u_int curtime;
 extern u_int curtime;
 extern struct in_addr loopback_addr;
 extern struct in_addr loopback_addr;
 extern unsigned long loopback_mask;
 extern unsigned long loopback_mask;
-extern char *username;
-extern char *socket_path;
-extern int towrite_max;
-extern int ppp_exit;
-extern int tcp_keepintvl;
-
-#define PROTO_SLIP 0x1
-#ifdef USE_PPP
-#define PROTO_PPP 0x2
-#endif
 
 
 int if_encap(Slirp *slirp, struct mbuf *ifm);
 int if_encap(Slirp *slirp, struct mbuf *ifm);
 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags);
 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags);

+ 1 - 1
slirp/mbuf.c

@@ -232,7 +232,7 @@ dtom(Slirp *slirp, void *dat)
 	  }
 	  }
 	}
 	}
 
 
-	DEBUG_ERROR((dfd, "dtom failed"));
+	DEBUG_ERROR("dtom failed");
 
 
 	return (struct mbuf *)0;
 	return (struct mbuf *)0;
 }
 }

+ 0 - 1
slirp/mbuf.h

@@ -72,7 +72,6 @@
  * How much free room there is
  * How much free room there is
  */
  */
 #define M_FREEROOM(m) (M_ROOM(m) - (m)->m_len)
 #define M_FREEROOM(m) (M_ROOM(m) - (m)->m_len)
-#define M_TRAILINGSPACE M_FREEROOM
 
 
 struct mbuf {
 struct mbuf {
 	/* XXX should union some of these! */
 	/* XXX should union some of these! */

+ 115 - 171
slirp/misc.c

@@ -8,14 +8,9 @@
 #include "qemu/osdep.h"
 #include "qemu/osdep.h"
 #include "slirp.h"
 #include "slirp.h"
 #include "libslirp.h"
 #include "libslirp.h"
-#include "monitor/monitor.h"
 #include "qemu/error-report.h"
 #include "qemu/error-report.h"
 #include "qemu/main-loop.h"
 #include "qemu/main-loop.h"
 
 
-#ifdef DEBUG
-int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR;
-#endif
-
 inline void
 inline void
 insque(void *a, void *b)
 insque(void *a, void *b)
 {
 {
@@ -37,189 +32,135 @@ remque(void *a)
   element->qh_rlink = NULL;
   element->qh_rlink = NULL;
 }
 }
 
 
-int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec,
+int add_exec(struct gfwd_list **ex_ptr, void *chardev, const char *cmdline,
              struct in_addr addr, int port)
              struct in_addr addr, int port)
 {
 {
-	struct ex_list *tmp_ptr;
-
-	/* First, check if the port is "bound" */
-	for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
-		if (port == tmp_ptr->ex_fport &&
-		    addr.s_addr == tmp_ptr->ex_addr.s_addr)
-			return -1;
-	}
+	struct gfwd_list *tmp_ptr;
 
 
 	tmp_ptr = *ex_ptr;
 	tmp_ptr = *ex_ptr;
-	*ex_ptr = g_new(struct ex_list, 1);
+	*ex_ptr = g_new0(struct gfwd_list, 1);
 	(*ex_ptr)->ex_fport = port;
 	(*ex_ptr)->ex_fport = port;
 	(*ex_ptr)->ex_addr = addr;
 	(*ex_ptr)->ex_addr = addr;
-	(*ex_ptr)->ex_pty = do_pty;
-	(*ex_ptr)->ex_exec = (do_pty == 3) ? exec : g_strdup(exec);
+	if (chardev) {
+		(*ex_ptr)->ex_chardev = chardev;
+	} else {
+		(*ex_ptr)->ex_exec = g_strdup(cmdline);
+	}
 	(*ex_ptr)->ex_next = tmp_ptr;
 	(*ex_ptr)->ex_next = tmp_ptr;
 	return 0;
 	return 0;
 }
 }
 
 
 
 
-#ifdef _WIN32
-
-int
-fork_exec(struct socket *so, const char *ex, int do_pty)
+static int
+slirp_socketpair_with_oob(int sv[2])
 {
 {
-    /* not implemented */
-    return 0;
-}
-
-#else
-
-/*
- * XXX This is ugly
- * We create and bind a socket, then fork off to another
- * process, which connects to this socket, after which we
- * exec the wanted program.  If something (strange) happens,
- * the accept() call could block us forever.
- *
- * do_pty = 0   Fork/exec inetd style
- * do_pty = 1   Fork/exec using slirp.telnetd
- * do_ptr = 2   Fork/exec using pty
- */
-int
-fork_exec(struct socket *so, const char *ex, int do_pty)
-{
-        int s, cs;
-        struct sockaddr_in addr, csaddr;
-	socklen_t addrlen = sizeof(addr);
-        socklen_t csaddrlen = sizeof(csaddr);
-	int opt;
-	const char *argv[256];
-	/* don't want to clobber the original */
-	char *bptr;
-	const char *curarg;
-	int c, i, ret;
-	pid_t pid;
-
-	DEBUG_CALL("fork_exec");
-	DEBUG_ARG("so = %p", so);
-	DEBUG_ARG("ex = %p", ex);
-	DEBUG_ARG("do_pty = %x", do_pty);
-
-	if (do_pty == 2) {
-                return 0;
-	} else {
-		addr.sin_family = AF_INET;
-		addr.sin_port = 0;
-		addr.sin_addr.s_addr = INADDR_ANY;
-
-		if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
-		    bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
-		    listen(s, 1) < 0) {
-			error_report("Error: inet socket: %s", strerror(errno));
-			if (s >= 0) {
-			    closesocket(s);
-			}
-
-			return 0;
-		}
-	}
+    struct sockaddr_in addr = {
+        .sin_family = AF_INET,
+        .sin_port = 0,
+        .sin_addr.s_addr = INADDR_ANY,
+    };
+    socklen_t addrlen = sizeof(addr);
+    int ret, s;
+
+    sv[1] = -1;
+    s = qemu_socket(AF_INET, SOCK_STREAM, 0);
+    if (s < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
+        listen(s, 1) < 0 ||
+        getsockname(s, (struct sockaddr *)&addr, &addrlen) < 0) {
+        goto err;
+    }
 
 
-        if (getsockname(s, (struct sockaddr *)&csaddr, &csaddrlen) < 0) {
-            closesocket(s);
-            return 0;
-        }
-        cs = qemu_socket(AF_INET, SOCK_STREAM, 0);
-        if (cs < 0) {
-            closesocket(s);
-            return 0;
-        }
-        csaddr.sin_addr = loopback_addr;
-        /*
-         * This connect won't block because we've already listen()ed on
-         * the server end (even though we won't accept() the connection
-         * until later on).
-         */
-        do {
-            ret = connect(cs, (struct sockaddr *)&csaddr, csaddrlen);
-        } while (ret < 0 && errno == EINTR);
-        if (ret < 0) {
-            closesocket(s);
-            closesocket(cs);
-            return 0;
-        }
+    sv[1] = qemu_socket(AF_INET, SOCK_STREAM, 0);
+    if (sv[1] < 0) {
+        goto err;
+    }
+    /*
+     * This connect won't block because we've already listen()ed on
+     * the server end (even though we won't accept() the connection
+     * until later on).
+     */
+    do {
+        ret = connect(sv[1], (struct sockaddr *)&addr, addrlen);
+    } while (ret < 0 && errno == EINTR);
+    if (ret < 0) {
+        goto err;
+    }
 
 
-	pid = fork();
-	switch(pid) {
-	 case -1:
-		error_report("Error: fork failed: %s", strerror(errno));
-                closesocket(cs);
-		close(s);
-		return 0;
+    do {
+        sv[0] = accept(s, (struct sockaddr *)&addr, &addrlen);
+    } while (sv[0] < 0 && errno == EINTR);
+    if (sv[0] < 0) {
+        goto err;
+    }
 
 
-	 case 0:
-                setsid();
+    closesocket(s);
+    return 0;
 
 
-		/* Set the DISPLAY */
-                close(s);
-                dup2(cs, 0);
-                dup2(cs, 1);
-                dup2(cs, 2);
-		for (s = getdtablesize() - 1; s >= 3; s--)
-		   close(s);
+err:
+    g_critical("slirp_socketpair(): %s", strerror(errno));
+    if (s >= 0) {
+        closesocket(s);
+    }
+    if (sv[1] >= 0) {
+        closesocket(sv[1]);
+    }
+    return -1;
+}
 
 
-		i = 0;
-		bptr = g_strdup(ex); /* No need to free() this */
-		if (do_pty == 1) {
-			/* Setup "slirp.telnetd -x" */
-			argv[i++] = "slirp.telnetd";
-			argv[i++] = "-x";
-			argv[i++] = bptr;
-		} else
-		   do {
-			/* Change the string into argv[] */
-			curarg = bptr;
-			while (*bptr != ' ' && *bptr != (char)0)
-			   bptr++;
-			c = *bptr;
-			*bptr++ = (char)0;
-			argv[i++] = g_strdup(curarg);
-		   } while (c);
+static void
+fork_exec_child_setup(gpointer data)
+{
+#ifndef _WIN32
+    setsid();
+#endif
+}
 
 
-                argv[i] = NULL;
-		execvp(argv[0], (char **)argv);
+int
+fork_exec(struct socket *so, const char *ex)
+{
+    GError *err = NULL;
+    char **argv;
+    int opt, sp[2];
 
 
-		/* Ooops, failed, let's tell the user why */
-        fprintf(stderr, "Error: execvp of %s failed: %s\n",
-                argv[0], strerror(errno));
-		close(0); close(1); close(2); /* XXX */
-		exit(1);
+    DEBUG_CALL("fork_exec");
+    DEBUG_ARG("so = %p", so);
+    DEBUG_ARG("ex = %p", ex);
 
 
-	 default:
-		qemu_add_child_watch(pid);
-                closesocket(cs);
-                /*
-                 * This should never block, because we already connect()ed
-                 * on the child end before we forked.
-                 */
-                do {
-                    so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
-                } while (so->s < 0 && errno == EINTR);
-                closesocket(s);
-                socket_set_fast_reuse(so->s);
-                opt = 1;
-                qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
-		qemu_set_nonblock(so->s);
+    if (slirp_socketpair_with_oob(sp) < 0) {
+        return 0;
+    }
 
 
-		/* Append the telnet options now */
-                if (so->so_m != NULL && do_pty == 1)  {
-			sbappend(so, so->so_m);
-                        so->so_m = NULL;
-		}
+    argv = g_strsplit(ex, " ", -1);
+    g_spawn_async_with_fds(NULL /* cwd */,
+                           argv,
+                           NULL /* env */,
+                           G_SPAWN_SEARCH_PATH,
+                           fork_exec_child_setup, NULL /* data */,
+                           NULL /* child_pid */,
+                           sp[1], sp[1], sp[1],
+                           &err);
+    g_strfreev(argv);
+
+    if (err) {
+        g_critical("fork_exec: %s", err->message);
+        g_error_free(err);
+        closesocket(sp[0]);
+        closesocket(sp[1]);
+        return 0;
+    }
 
 
-		return 1;
-	}
+    so->s = sp[0];
+    closesocket(sp[1]);
+    socket_set_fast_reuse(so->s);
+    opt = 1;
+    qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
+    qemu_set_nonblock(so->s);
+    return 1;
 }
 }
-#endif
 
 
-void slirp_connection_info(Slirp *slirp, Monitor *mon)
+char *slirp_connection_info(Slirp *slirp)
 {
 {
+    GString *str = g_string_new(NULL);
     const char * const tcpstates[] = {
     const char * const tcpstates[] = {
         [TCPS_CLOSED]       = "CLOSED",
         [TCPS_CLOSED]       = "CLOSED",
         [TCPS_LISTEN]       = "LISTEN",
         [TCPS_LISTEN]       = "LISTEN",
@@ -241,8 +182,9 @@ void slirp_connection_info(Slirp *slirp, Monitor *mon)
     const char *state;
     const char *state;
     char buf[20];
     char buf[20];
 
 
-    monitor_printf(mon, "  Protocol[State]    FD  Source Address  Port   "
-                        "Dest. Address  Port RecvQ SendQ\n");
+    g_string_append_printf(str,
+        "  Protocol[State]    FD  Source Address  Port   "
+        "Dest. Address  Port RecvQ SendQ\n");
 
 
     for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
     for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
         if (so->so_state & SS_HOSTFWD) {
         if (so->so_state & SS_HOSTFWD) {
@@ -264,10 +206,10 @@ void slirp_connection_info(Slirp *slirp, Monitor *mon)
             dst_port = so->so_fport;
             dst_port = so->so_fport;
         }
         }
         snprintf(buf, sizeof(buf), "  TCP[%s]", state);
         snprintf(buf, sizeof(buf), "  TCP[%s]", state);
-        monitor_printf(mon, "%-19s %3d %15s %5d ", buf, so->s,
+        g_string_append_printf(str, "%-19s %3d %15s %5d ", buf, so->s,
                        src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*",
                        src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*",
                        ntohs(src.sin_port));
                        ntohs(src.sin_port));
-        monitor_printf(mon, "%15s %5d %5d %5d\n",
+        g_string_append_printf(str, "%15s %5d %5d %5d\n",
                        inet_ntoa(dst_addr), ntohs(dst_port),
                        inet_ntoa(dst_addr), ntohs(dst_port),
                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
     }
     }
@@ -287,10 +229,10 @@ void slirp_connection_info(Slirp *slirp, Monitor *mon)
             dst_addr = so->so_faddr;
             dst_addr = so->so_faddr;
             dst_port = so->so_fport;
             dst_port = so->so_fport;
         }
         }
-        monitor_printf(mon, "%-19s %3d %15s %5d ", buf, so->s,
+        g_string_append_printf(str, "%-19s %3d %15s %5d ", buf, so->s,
                        src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*",
                        src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*",
                        ntohs(src.sin_port));
                        ntohs(src.sin_port));
-        monitor_printf(mon, "%15s %5d %5d %5d\n",
+        g_string_append_printf(str, "%15s %5d %5d %5d\n",
                        inet_ntoa(dst_addr), ntohs(dst_port),
                        inet_ntoa(dst_addr), ntohs(dst_port),
                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
     }
     }
@@ -300,9 +242,11 @@ void slirp_connection_info(Slirp *slirp, Monitor *mon)
                      (so->so_expire - curtime) / 1000);
                      (so->so_expire - curtime) / 1000);
         src.sin_addr = so->so_laddr;
         src.sin_addr = so->so_laddr;
         dst_addr = so->so_faddr;
         dst_addr = so->so_faddr;
-        monitor_printf(mon, "%-19s %3d %15s  -    ", buf, so->s,
+        g_string_append_printf(str, "%-19s %3d %15s  -    ", buf, so->s,
                        src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*");
                        src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*");
-        monitor_printf(mon, "%15s  -    %5d %5d\n", inet_ntoa(dst_addr),
+        g_string_append_printf(str, "%15s  -    %5d %5d\n", inet_ntoa(dst_addr),
                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
     }
     }
+
+    return g_string_free(str, FALSE);
 }
 }

+ 6 - 7
slirp/misc.h

@@ -8,12 +8,12 @@
 #ifndef MISC_H
 #ifndef MISC_H
 #define MISC_H
 #define MISC_H
 
 
-struct ex_list {
-	int ex_pty;			/* Do we want a pty? */
+struct gfwd_list {
+	void *ex_chardev;
 	struct in_addr ex_addr;		/* Server address */
 	struct in_addr ex_addr;		/* Server address */
 	int ex_fport;                   /* Port to telnet to */
 	int ex_fport;                   /* Port to telnet to */
-	const char *ex_exec;            /* Command line of what to exec */
-	struct ex_list *ex_next;
+	char *ex_exec;                  /* Command line of what to exec */
+	struct gfwd_list *ex_next;
 };
 };
 
 
 #define EMU_NONE 0x0
 #define EMU_NONE 0x0
@@ -26,7 +26,6 @@ struct ex_list {
 #define EMU_REALAUDIO 0x5
 #define EMU_REALAUDIO 0x5
 #define EMU_RLOGIN 0x6
 #define EMU_RLOGIN 0x6
 #define EMU_IDENT 0x7
 #define EMU_IDENT 0x7
-#define EMU_RSH 0x8
 
 
 #define EMU_NOCONNECT 0x10	/* Don't connect */
 #define EMU_NOCONNECT 0x10	/* Don't connect */
 
 
@@ -52,7 +51,7 @@ struct slirp_quehead {
 
 
 void slirp_insque(void *, void *);
 void slirp_insque(void *, void *);
 void slirp_remque(void *);
 void slirp_remque(void *);
-int add_exec(struct ex_list **, int, char *, struct in_addr, int);
-int fork_exec(struct socket *so, const char *ex, int do_pty);
+int add_exec(struct gfwd_list **, void *, const char *, struct in_addr, int);
+int fork_exec(struct socket *so, const char *ex);
 
 
 #endif
 #endif

+ 2 - 2
slirp/ncsi.c

@@ -128,7 +128,7 @@ void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
     memset(reh->h_source, 0xff, ETH_ALEN);
     memset(reh->h_source, 0xff, ETH_ALEN);
     reh->h_proto = htons(ETH_P_NCSI);
     reh->h_proto = htons(ETH_P_NCSI);
 
 
-    for (i = 0; i < ARRAY_SIZE(ncsi_rsp_handlers); i++) {
+    for (i = 0; i < G_N_ELEMENTS(ncsi_rsp_handlers); i++) {
         if (ncsi_rsp_handlers[i].type == nh->type + 0x80) {
         if (ncsi_rsp_handlers[i].type == nh->type + 0x80) {
             handler = &ncsi_rsp_handlers[i];
             handler = &ncsi_rsp_handlers[i];
             break;
             break;
@@ -163,5 +163,5 @@ void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
     *pchecksum = htonl(checksum);
     *pchecksum = htonl(checksum);
     ncsi_rsp_len += 4;
     ncsi_rsp_len += 4;
 
 
-    slirp_output(slirp->opaque, ncsi_reply, ETH_HLEN + ncsi_rsp_len);
+    slirp->cb->output(slirp->opaque, ncsi_reply, ETH_HLEN + ncsi_rsp_len);
 }
 }

+ 15 - 17
slirp/ndp_table.c

@@ -10,18 +10,17 @@
 void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr,
 void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr,
                     uint8_t ethaddr[ETH_ALEN])
                     uint8_t ethaddr[ETH_ALEN])
 {
 {
+    char addrstr[INET6_ADDRSTRLEN];
     NdpTable *ndp_table = &slirp->ndp_table;
     NdpTable *ndp_table = &slirp->ndp_table;
     int i;
     int i;
 
 
-    DEBUG_CALL("ndp_table_add");
-#if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600)
-    char addrstr[INET6_ADDRSTRLEN];
     inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN);
     inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN);
+
+    DEBUG_CALL("ndp_table_add");
     DEBUG_ARG("ip = %s", addrstr);
     DEBUG_ARG("ip = %s", addrstr);
-#endif
-    DEBUG_ARGS((dfd, " hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
-                ethaddr[0], ethaddr[1], ethaddr[2],
-                ethaddr[3], ethaddr[4], ethaddr[5]));
+    DEBUG_ARG("hw addr = %02x:%02x:%02x:%02x:%02x:%02x",
+              ethaddr[0], ethaddr[1], ethaddr[2],
+              ethaddr[3], ethaddr[4], ethaddr[5]);
 
 
     if (IN6_IS_ADDR_MULTICAST(&ip_addr) || in6_zero(&ip_addr)) {
     if (IN6_IS_ADDR_MULTICAST(&ip_addr) || in6_zero(&ip_addr)) {
         /* Do not register multicast or unspecified addresses */
         /* Do not register multicast or unspecified addresses */
@@ -50,15 +49,14 @@ void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr,
 bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr,
 bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr,
                       uint8_t out_ethaddr[ETH_ALEN])
                       uint8_t out_ethaddr[ETH_ALEN])
 {
 {
+    char addrstr[INET6_ADDRSTRLEN];
     NdpTable *ndp_table = &slirp->ndp_table;
     NdpTable *ndp_table = &slirp->ndp_table;
     int i;
     int i;
 
 
-    DEBUG_CALL("ndp_table_search");
-#if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600)
-    char addrstr[INET6_ADDRSTRLEN];
     inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN);
     inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN);
+
+    DEBUG_CALL("ndp_table_search");
     DEBUG_ARG("ip = %s", addrstr);
     DEBUG_ARG("ip = %s", addrstr);
-#endif
 
 
     assert(!in6_zero(&ip_addr));
     assert(!in6_zero(&ip_addr));
 
 
@@ -69,18 +67,18 @@ bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr,
         out_ethaddr[3] = ip_addr.s6_addr[13];
         out_ethaddr[3] = ip_addr.s6_addr[13];
         out_ethaddr[4] = ip_addr.s6_addr[14];
         out_ethaddr[4] = ip_addr.s6_addr[14];
         out_ethaddr[5] = ip_addr.s6_addr[15];
         out_ethaddr[5] = ip_addr.s6_addr[15];
-        DEBUG_ARGS((dfd, " multicast addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
-                    out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
-                    out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]));
+        DEBUG_ARG("multicast addr = %02x:%02x:%02x:%02x:%02x:%02x",
+                  out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
+                  out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]);
         return 1;
         return 1;
     }
     }
 
 
     for (i = 0; i < NDP_TABLE_SIZE; i++) {
     for (i = 0; i < NDP_TABLE_SIZE; i++) {
         if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) {
         if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) {
             memcpy(out_ethaddr, ndp_table->table[i].eth_addr,  ETH_ALEN);
             memcpy(out_ethaddr, ndp_table->table[i].eth_addr,  ETH_ALEN);
-            DEBUG_ARGS((dfd, " found hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
-                        out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
-                        out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]));
+            DEBUG_ARG("found hw addr = %02x:%02x:%02x:%02x:%02x:%02x",
+                      out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
+                      out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]);
             return 1;
             return 1;
         }
         }
     }
     }

+ 0 - 1
slirp/sbuf.h

@@ -8,7 +8,6 @@
 #ifndef SBUF_H
 #ifndef SBUF_H
 #define SBUF_H
 #define SBUF_H
 
 
-#define sbflush(sb) sbdrop((sb),(sb)->sb_cc)
 #define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)
 #define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)
 
 
 struct sbuf {
 struct sbuf {

+ 86 - 91
slirp/slirp.c

@@ -35,6 +35,11 @@
 #include <net/if.h>
 #include <net/if.h>
 #endif
 #endif
 
 
+int slirp_debug;
+
+/* Define to 1 if you want KEEPALIVE timers */
+bool slirp_do_keepalive;
+
 /* host loopback address */
 /* host loopback address */
 struct in_addr loopback_addr;
 struct in_addr loopback_addr;
 /* host loopback network mask */
 /* host loopback network mask */
@@ -161,9 +166,7 @@ static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr,
     if (!f)
     if (!f)
         return -1;
         return -1;
 
 
-#ifdef DEBUG
-    fprintf(stderr, "IP address of your DNS(s): ");
-#endif
+    DEBUG_MISC("IP address of your DNS(s):");
     while (fgets(buff, 512, f) != NULL) {
     while (fgets(buff, 512, f) != NULL) {
         if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
         if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
             char *c = strchr(buff2, '%');
             char *c = strchr(buff2, '%');
@@ -186,26 +189,18 @@ static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr,
                 }
                 }
                 *cached_time = curtime;
                 *cached_time = curtime;
             }
             }
-#ifdef DEBUG
-            else
-                fprintf(stderr, ", ");
-#endif
+
             if (++found > 3) {
             if (++found > 3) {
-#ifdef DEBUG
-                fprintf(stderr, "(more)");
-#endif
+                DEBUG_MISC("  (more)");
                 break;
                 break;
-            }
-#ifdef DEBUG
-            else {
+            } else if (slirp_debug & DBG_MISC) {
                 char s[INET6_ADDRSTRLEN];
                 char s[INET6_ADDRSTRLEN];
                 const char *res = inet_ntop(af, tmp_addr, s, sizeof(s));
                 const char *res = inet_ntop(af, tmp_addr, s, sizeof(s));
                 if (!res) {
                 if (!res) {
-                    res = "(string conversion error)";
+                    res = "  (string conversion error)";
                 }
                 }
-                fprintf(stderr, "%s", res);
+                DEBUG_MISC("  %s", res);
             }
             }
-#endif
         }
         }
     }
     }
     fclose(f);
     fclose(f);
@@ -252,6 +247,7 @@ int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id)
 static void slirp_init_once(void)
 static void slirp_init_once(void)
 {
 {
     static int initialized;
     static int initialized;
+    const char *debug;
 #ifdef _WIN32
 #ifdef _WIN32
     WSADATA Data;
     WSADATA Data;
 #endif
 #endif
@@ -268,6 +264,18 @@ static void slirp_init_once(void)
 
 
     loopback_addr.s_addr = htonl(INADDR_LOOPBACK);
     loopback_addr.s_addr = htonl(INADDR_LOOPBACK);
     loopback_mask = htonl(IN_CLASSA_NET);
     loopback_mask = htonl(IN_CLASSA_NET);
+
+    debug = g_getenv("SLIRP_DEBUG");
+    if (debug) {
+        const GDebugKey keys[] = {
+            { "call", DBG_CALL },
+            { "misc", DBG_MISC },
+            { "error", DBG_ERROR },
+        };
+        slirp_debug = g_parse_debug_string(debug, keys, G_N_ELEMENTS(keys));
+    }
+
+
 }
 }
 
 
 static void slirp_state_save(QEMUFile *f, void *opaque);
 static void slirp_state_save(QEMUFile *f, void *opaque);
@@ -287,12 +295,15 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
                   const char *tftp_path, const char *bootfile,
                   const char *tftp_path, const char *bootfile,
                   struct in_addr vdhcp_start, struct in_addr vnameserver,
                   struct in_addr vdhcp_start, struct in_addr vnameserver,
                   struct in6_addr vnameserver6, const char **vdnssearch,
                   struct in6_addr vnameserver6, const char **vdnssearch,
-                  const char *vdomainname, void *opaque)
+                  const char *vdomainname,
+                  const SlirpCb *callbacks,
+                  void *opaque)
 {
 {
     Slirp *slirp = g_malloc0(sizeof(Slirp));
     Slirp *slirp = g_malloc0(sizeof(Slirp));
 
 
     slirp_init_once();
     slirp_init_once();
 
 
+    slirp->cb = callbacks;
     slirp->grand = g_rand_new();
     slirp->grand = g_rand_new();
     slirp->restricted = restricted;
     slirp->restricted = restricted;
 
 
@@ -339,6 +350,14 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
 
 
 void slirp_cleanup(Slirp *slirp)
 void slirp_cleanup(Slirp *slirp)
 {
 {
+    struct gfwd_list *e, *next;
+
+    for (e = slirp->guestfwd_list; e; e = next) {
+        next = e->ex_next;
+        g_free(e->ex_exec);
+        g_free(e);
+    }
+
     QTAILQ_REMOVE(&slirp_instances, slirp, entry);
     QTAILQ_REMOVE(&slirp_instances, slirp, entry);
 
 
     unregister_savevm(NULL, "slirp", slirp);
     unregister_savevm(NULL, "slirp", slirp);
@@ -560,15 +579,15 @@ void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout)
 
 
 void slirp_pollfds_poll(GArray *pollfds, int select_error)
 void slirp_pollfds_poll(GArray *pollfds, int select_error)
 {
 {
-    Slirp *slirp;
+    Slirp *slirp = QTAILQ_FIRST(&slirp_instances);
     struct socket *so, *so_next;
     struct socket *so, *so_next;
     int ret;
     int ret;
 
 
-    if (QTAILQ_EMPTY(&slirp_instances)) {
+    if (!slirp) {
         return;
         return;
     }
     }
 
 
-    curtime = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
+    curtime = slirp->cb->clock_get_ns() / SCALE_MS;
 
 
     QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
     QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
         /*
         /*
@@ -688,47 +707,6 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
                         }
                         }
                     }
                     }
                 }
                 }
-
-                /*
-                 * Probe a still-connecting, non-blocking socket
-                 * to check if it's still alive
-                 */
-#ifdef PROBE_CONN
-                if (so->so_state & SS_ISFCONNECTING) {
-                    ret = qemu_recv(so->s, &ret, 0, 0);
-
-                    if (ret < 0) {
-                        /* XXX */
-                        if (errno == EAGAIN || errno == EWOULDBLOCK ||
-                            errno == EINPROGRESS || errno == ENOTCONN) {
-                            continue; /* Still connecting, continue */
-                        }
-
-                        /* else failed */
-                        so->so_state &= SS_PERSISTENT_MASK;
-                        so->so_state |= SS_NOFDREF;
-
-                        /* tcp_input will take care of it */
-                    } else {
-                        ret = send(so->s, &ret, 0, 0);
-                        if (ret < 0) {
-                            /* XXX */
-                            if (errno == EAGAIN || errno == EWOULDBLOCK ||
-                                errno == EINPROGRESS || errno == ENOTCONN) {
-                                continue;
-                            }
-                            /* else failed */
-                            so->so_state &= SS_PERSISTENT_MASK;
-                            so->so_state |= SS_NOFDREF;
-                        } else {
-                            so->so_state &= ~SS_ISFCONNECTING;
-                        }
-
-                    }
-                    tcp_input((struct mbuf *)NULL, sizeof(struct ip), so,
-                              so->so_ffamily);
-                } /* SS_ISFCONNECTING */
-#endif
             }
             }
 
 
             /*
             /*
@@ -787,7 +765,7 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
     struct ethhdr *reh = (struct ethhdr *)arp_reply;
     struct ethhdr *reh = (struct ethhdr *)arp_reply;
     struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_reply + ETH_HLEN);
     struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_reply + ETH_HLEN);
     int ar_op;
     int ar_op;
-    struct ex_list *ex_ptr;
+    struct gfwd_list *ex_ptr;
 
 
     if (!slirp->in_enabled) {
     if (!slirp->in_enabled) {
         return;
         return;
@@ -807,7 +785,7 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
             if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
             if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
                 ah->ar_tip == slirp->vhost_addr.s_addr)
                 ah->ar_tip == slirp->vhost_addr.s_addr)
                 goto arp_ok;
                 goto arp_ok;
-            for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+            for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
                 if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
                 if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
                     goto arp_ok;
                     goto arp_ok;
             }
             }
@@ -832,7 +810,7 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
             rah->ar_sip = ah->ar_tip;
             rah->ar_sip = ah->ar_tip;
             memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
             memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
             rah->ar_tip = ah->ar_sip;
             rah->ar_tip = ah->ar_sip;
-            slirp_output(slirp->opaque, arp_reply, sizeof(arp_reply));
+            slirp->cb->output(slirp->opaque, arp_reply, sizeof(arp_reply));
         }
         }
         break;
         break;
     case ARPOP_REPLY:
     case ARPOP_REPLY:
@@ -932,11 +910,11 @@ static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
             /* target IP */
             /* target IP */
             rah->ar_tip = iph->ip_dst.s_addr;
             rah->ar_tip = iph->ip_dst.s_addr;
             slirp->client_ipaddr = iph->ip_dst;
             slirp->client_ipaddr = iph->ip_dst;
-            slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
+            slirp->cb->output(slirp->opaque, arp_req, sizeof(arp_req));
             ifm->resolution_requested = true;
             ifm->resolution_requested = true;
 
 
             /* Expire request and drop outgoing packet after 1 second */
             /* Expire request and drop outgoing packet after 1 second */
-            ifm->expiration_date = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + 1000000000ULL;
+            ifm->expiration_date = slirp->cb->clock_get_ns() + 1000000000ULL;
         }
         }
         return 0;
         return 0;
     } else {
     } else {
@@ -962,8 +940,7 @@ static int if_encap6(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
         if (!ifm->resolution_requested) {
         if (!ifm->resolution_requested) {
             ndp_send_ns(slirp, ip6h->ip_dst);
             ndp_send_ns(slirp, ip6h->ip_dst);
             ifm->resolution_requested = true;
             ifm->resolution_requested = true;
-            ifm->expiration_date =
-                qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + 1000000000ULL;
+            ifm->expiration_date = slirp->cb->clock_get_ns() + 1000000000ULL;
         }
         }
         return 0;
         return 0;
     } else {
     } else {
@@ -1011,14 +988,14 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
     }
     }
 
 
     memcpy(eh->h_dest, ethaddr, ETH_ALEN);
     memcpy(eh->h_dest, ethaddr, ETH_ALEN);
-    DEBUG_ARGS((dfd, " src = %02x:%02x:%02x:%02x:%02x:%02x\n",
-                eh->h_source[0], eh->h_source[1], eh->h_source[2],
-                eh->h_source[3], eh->h_source[4], eh->h_source[5]));
-    DEBUG_ARGS((dfd, " dst = %02x:%02x:%02x:%02x:%02x:%02x\n",
-                eh->h_dest[0], eh->h_dest[1], eh->h_dest[2],
-                eh->h_dest[3], eh->h_dest[4], eh->h_dest[5]));
+    DEBUG_ARG("src = %02x:%02x:%02x:%02x:%02x:%02x",
+              eh->h_source[0], eh->h_source[1], eh->h_source[2],
+              eh->h_source[3], eh->h_source[4], eh->h_source[5]);
+    DEBUG_ARG("dst = %02x:%02x:%02x:%02x:%02x:%02x",
+              eh->h_dest[0], eh->h_dest[1], eh->h_dest[2],
+              eh->h_dest[3], eh->h_dest[4], eh->h_dest[5]);
     memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
     memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
-    slirp_output(slirp->opaque, buf, ifm->m_len + ETH_HLEN);
+    slirp->cb->output(slirp->opaque, buf, ifm->m_len + ETH_HLEN);
     return 1;
     return 1;
 }
 }
 
 
@@ -1065,9 +1042,11 @@ int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
     return 0;
     return 0;
 }
 }
 
 
-int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
-                   struct in_addr *guest_addr, int guest_port)
+static bool
+check_guestfwd(Slirp *slirp, struct in_addr *guest_addr, int guest_port)
 {
 {
+    struct gfwd_list *tmp_ptr;
+
     if (!guest_addr->s_addr) {
     if (!guest_addr->s_addr) {
         guest_addr->s_addr = slirp->vnetwork_addr.s_addr |
         guest_addr->s_addr = slirp->vnetwork_addr.s_addr |
             (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
             (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
@@ -1076,18 +1055,36 @@ int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
         slirp->vnetwork_addr.s_addr ||
         slirp->vnetwork_addr.s_addr ||
         guest_addr->s_addr == slirp->vhost_addr.s_addr ||
         guest_addr->s_addr == slirp->vhost_addr.s_addr ||
         guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
         guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
+        return false;
+    }
+
+    /* check if the port is "bound" */
+    for (tmp_ptr = slirp->guestfwd_list; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
+        if (guest_port == tmp_ptr->ex_fport &&
+            guest_addr->s_addr == tmp_ptr->ex_addr.s_addr)
+            return false;
+    }
+
+    return true;
+}
+
+int slirp_add_exec(Slirp *slirp, void *chardev, const char *cmdline,
+                   struct in_addr *guest_addr, int guest_port)
+{
+    if (!check_guestfwd(slirp, guest_addr, guest_port)) {
         return -1;
         return -1;
     }
     }
-    return add_exec(&slirp->exec_list, do_pty, (char *)args, *guest_addr,
+
+    return add_exec(&slirp->guestfwd_list, chardev, cmdline, *guest_addr,
                     htons(guest_port));
                     htons(guest_port));
 }
 }
 
 
 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
 {
 {
-    if (so->s == -1 && so->extra) {
+    if (so->s == -1 && so->chardev) {
         /* XXX this blocks entire thread. Rewrite to use
         /* XXX this blocks entire thread. Rewrite to use
          * qemu_chr_fe_write and background I/O callbacks */
          * qemu_chr_fe_write and background I/O callbacks */
-        qemu_chr_fe_write_all(so->extra, buf, len);
+        qemu_chr_fe_write_all(so->chardev, buf, len);
         return len;
         return len;
     }
     }
 
 
@@ -1240,8 +1237,8 @@ static int sbuf_tmp_post_load(void *opaque, int version)
     }
     }
     if (tmp->woff >= requested_len ||
     if (tmp->woff >= requested_len ||
         tmp->roff >= requested_len) {
         tmp->roff >= requested_len) {
-        error_report("invalid sbuf offsets r/w=%u/%u len=%u",
-                     tmp->roff, tmp->woff, requested_len);
+        g_critical("invalid sbuf offsets r/w=%u/%u len=%u",
+                   tmp->roff, tmp->woff, requested_len);
         return -EINVAL;
         return -EINVAL;
     }
     }
 
 
@@ -1349,7 +1346,7 @@ static int ss_family_post_load(void *opaque, int version_id)
         tss->parent->ss.ss_family = AF_INET6;
         tss->parent->ss.ss_family = AF_INET6;
         break;
         break;
     default:
     default:
-        error_report("invalid ss_family type %x", tss->portable_family);
+        g_critical("invalid ss_family type %x", tss->portable_family);
         return -EINVAL;
         return -EINVAL;
     }
     }
 
 
@@ -1449,10 +1446,10 @@ static const VMStateDescription vmstate_slirp = {
 static void slirp_state_save(QEMUFile *f, void *opaque)
 static void slirp_state_save(QEMUFile *f, void *opaque)
 {
 {
     Slirp *slirp = opaque;
     Slirp *slirp = opaque;
-    struct ex_list *ex_ptr;
+    struct gfwd_list *ex_ptr;
 
 
-    for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
-        if (ex_ptr->ex_pty == 3) {
+    for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+        if (ex_ptr->ex_chardev) {
             struct socket *so;
             struct socket *so;
             so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
             so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
                                        ntohs(ex_ptr->ex_fport));
                                        ntohs(ex_ptr->ex_fport));
@@ -1471,7 +1468,7 @@ static void slirp_state_save(QEMUFile *f, void *opaque)
 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
 {
 {
     Slirp *slirp = opaque;
     Slirp *slirp = opaque;
-    struct ex_list *ex_ptr;
+    struct gfwd_list *ex_ptr;
 
 
     while (qemu_get_byte(f)) {
     while (qemu_get_byte(f)) {
         int ret;
         int ret;
@@ -1486,8 +1483,8 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
             slirp->vnetwork_addr.s_addr) {
             slirp->vnetwork_addr.s_addr) {
             return -EINVAL;
             return -EINVAL;
         }
         }
-        for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
-            if (ex_ptr->ex_pty == 3 &&
+        for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+            if (ex_ptr->ex_chardev &&
                 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
                 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
                 so->so_fport == ex_ptr->ex_fport) {
                 so->so_fport == ex_ptr->ex_fport) {
                 break;
                 break;
@@ -1495,8 +1492,6 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
         }
         }
         if (!ex_ptr)
         if (!ex_ptr)
             return -EINVAL;
             return -EINVAL;
-
-        so->extra = (void *)ex_ptr->ex_exec;
     }
     }
 
 
     return vmstate_load_state(f, &vmstate_slirp, slirp, version_id);
     return vmstate_load_state(f, &vmstate_slirp, slirp, version_id);

+ 10 - 35
slirp/slirp.h

@@ -1,8 +1,6 @@
 #ifndef SLIRP_H
 #ifndef SLIRP_H
 #define SLIRP_H
 #define SLIRP_H
 
 
-#include "slirp_config.h"
-
 #ifdef _WIN32
 #ifdef _WIN32
 
 
 typedef char *caddr_t;
 typedef char *caddr_t;
@@ -19,10 +17,6 @@ typedef char *caddr_t;
 # endif
 # endif
 #endif
 #endif
 
 
-#ifdef HAVE_SYS_BITYPES_H
-# include <sys/bitypes.h>
-#endif
-
 #ifndef _WIN32
 #ifndef _WIN32
 #include <sys/uio.h>
 #include <sys/uio.h>
 #endif
 #endif
@@ -32,29 +26,15 @@ typedef char *caddr_t;
 #include <arpa/inet.h>
 #include <arpa/inet.h>
 #endif
 #endif
 
 
-#ifndef NO_UNIX_SOCKETS
-#include <sys/un.h>
-#endif
-#ifdef HAVE_SYS_SIGNAL_H
-# include <sys/signal.h>
-#endif
 #ifndef _WIN32
 #ifndef _WIN32
 #include <sys/socket.h>
 #include <sys/socket.h>
 #endif
 #endif
 
 
-#if defined(HAVE_SYS_IOCTL_H)
+#ifndef _WIN32
 # include <sys/ioctl.h>
 # include <sys/ioctl.h>
 #endif
 #endif
 
 
-#ifdef HAVE_SYS_SELECT_H
-# include <sys/select.h>
-#endif
-
-#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-
-#ifdef HAVE_SYS_FILIO_H
+#ifdef __APPLE__
 # include <sys/filio.h>
 # include <sys/filio.h>
 #endif
 #endif
 
 
@@ -64,11 +44,6 @@ typedef char *caddr_t;
 #define remque slirp_remque
 #define remque slirp_remque
 #define quehead slirp_quehead
 #define quehead slirp_quehead
 
 
-#ifdef HAVE_SYS_STROPTS_H
-#include <sys/stropts.h>
-#endif
-
-
 #include "debug.h"
 #include "debug.h"
 
 
 #include "qemu/queue.h"
 #include "qemu/queue.h"
@@ -172,7 +147,7 @@ struct Slirp {
     char client_hostname[33];
     char client_hostname[33];
 
 
     int restricted;
     int restricted;
-    struct ex_list *exec_list;
+    struct gfwd_list *guestfwd_list;
 
 
     /* mbuf states */
     /* mbuf states */
     struct quehead m_freelist;
     struct quehead m_freelist;
@@ -220,17 +195,15 @@ struct Slirp {
     GRand *grand;
     GRand *grand;
     QEMUTimer *ra_timer;
     QEMUTimer *ra_timer;
 
 
+    const SlirpCb *cb;
     void *opaque;
     void *opaque;
 };
 };
 
 
-extern Slirp *slirp_instance;
-
-#ifndef NULL
-#define NULL (void *)0
-#endif
-
 void if_start(Slirp *);
 void if_start(Slirp *);
 
 
+int get_dns_addr(struct in_addr *pdns_addr);
+int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id);
+
 /* ncsi.c */
 /* ncsi.c */
 void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);
 void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);
 
 
@@ -238,7 +211,9 @@ void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);
 #include <netdb.h>
 #include <netdb.h>
 #endif
 #endif
 
 
-#define SO_OPTIONS DO_KEEPALIVE
+
+extern bool slirp_do_keepalive;
+
 #define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL)
 #define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL)
 
 
 /* dnssearch.c */
 /* dnssearch.c */

+ 0 - 86
slirp/slirp_config.h

@@ -1,86 +0,0 @@
-/*
- * User definable configuration options
- */
-
-/* Define if you want the connection to be probed */
-/* XXX Not working yet, so ignore this for now */
-#undef PROBE_CONN
-
-/* Define to 1 if you want KEEPALIVE timers */
-#define DO_KEEPALIVE 0
-
-/* Define this if you want slirp to write to the tty as fast as it can */
-/* This should only be set if you are using load-balancing, slirp does a */
-/* pretty good job on single modems already, and seting this will make */
-/* interactive sessions less responsive */
-/* XXXXX Talk about having fast modem as unit 0 */
-#undef FULL_BOLT
-
-/*********************************************************/
-/*
- * Autoconf defined configuration options
- * You shouldn't need to touch any of these
- */
-
-/* Define if you have sys/ioctl.h */
-#undef HAVE_SYS_IOCTL_H
-#ifndef _WIN32
-#define HAVE_SYS_IOCTL_H
-#endif
-
-/* Define if you have sys/filio.h */
-#undef HAVE_SYS_FILIO_H
-#ifdef __APPLE__
-#define HAVE_SYS_FILIO_H
-#endif
-
-/* Define if you have sys/bitypes.h */
-#undef HAVE_SYS_BITYPES_H
-
-/* Define if the machine is big endian */
-//#undef HOST_WORDS_BIGENDIAN
-
-/* Define if you have readv */
-#undef HAVE_READV
-
-/* Define if iovec needs to be declared */
-#undef DECLARE_IOVEC
-#ifdef _WIN32
-#define DECLARE_IOVEC
-#endif
-
-/* Define if you have a POSIX.1 sys/wait.h */
-#undef HAVE_SYS_WAIT_H
-
-/* Define if you have sys/select.h */
-#undef HAVE_SYS_SELECT_H
-#ifndef _WIN32
-#define HAVE_SYS_SELECT_H
-#endif
-
-/* Define if you have arpa/inet.h */
-#undef HAVE_ARPA_INET_H
-#ifndef _WIN32
-#define HAVE_ARPA_INET_H
-#endif
-
-/* Define if you have sys/signal.h */
-#undef HAVE_SYS_SIGNAL_H
-
-/* Define if you have sys/stropts.h */
-#undef HAVE_SYS_STROPTS_H
-
-/* Define to sizeof(char *) */
-#define SIZEOF_CHAR_P (HOST_LONG_BITS / 8)
-
-/* Define if you have inet_aton */
-#undef HAVE_INET_ATON
-#ifndef _WIN32
-#define HAVE_INET_ATON
-#endif
-
-/* Define if you DON'T have unix-domain sockets */
-#undef NO_UNIX_SOCKETS
-#ifdef _WIN32
-#define NO_UNIX_SOCKETS
-#endif

+ 17 - 36
slirp/socket.c

@@ -89,10 +89,6 @@ sofree(struct socket *so)
   soqfree(so, &slirp->if_fastq);
   soqfree(so, &slirp->if_fastq);
   soqfree(so, &slirp->if_batchq);
   soqfree(so, &slirp->if_batchq);
 
 
-  if (so->so_emu==EMU_RSH && so->extra) {
-	sofree(so->extra);
-	so->extra=NULL;
-  }
   if (so == slirp->tcp_last_so) {
   if (so == slirp->tcp_last_so) {
       slirp->tcp_last_so = &slirp->tcb;
       slirp->tcp_last_so = &slirp->tcb;
   } else if (so == slirp->udp_last_so) {
   } else if (so == slirp->udp_last_so) {
@@ -191,12 +187,7 @@ soread(struct socket *so)
 	 */
 	 */
 	sopreprbuf(so, iov, &n);
 	sopreprbuf(so, iov, &n);
 
 
-#ifdef HAVE_READV
-	nn = readv(so->s, (struct iovec *)iov, n);
-	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
-#else
 	nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
 	nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
-#endif
 	if (nn <= 0) {
 	if (nn <= 0) {
 		if (nn < 0 && (errno == EINTR || errno == EAGAIN))
 		if (nn < 0 && (errno == EINTR || errno == EAGAIN))
 			return 0;
 			return 0;
@@ -217,7 +208,8 @@ soread(struct socket *so)
 				}
 				}
 			}
 			}
 
 
-			DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
+			DEBUG_MISC(" --- soread() disconnected, nn = %d, errno = %d-%s",
+                       nn, errno,strerror(errno));
 			sofcantrcvmore(so);
 			sofcantrcvmore(so);
 
 
 			if (err == ECONNRESET || err == ECONNREFUSED
 			if (err == ECONNRESET || err == ECONNREFUSED
@@ -230,7 +222,6 @@ soread(struct socket *so)
 		}
 		}
 	}
 	}
 
 
-#ifndef HAVE_READV
 	/*
 	/*
 	 * If there was no error, try and read the second time round
 	 * If there was no error, try and read the second time round
 	 * We read again if n = 2 (ie, there's another part of the buffer)
 	 * We read again if n = 2 (ie, there's another part of the buffer)
@@ -247,8 +238,7 @@ soread(struct socket *so)
                 nn += ret;
                 nn += ret;
         }
         }
 
 
-	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
-#endif
+	DEBUG_MISC(" ... read nn = %d bytes", nn);
 
 
 	/* Update fields */
 	/* Update fields */
 	sb->sb_cc += nn;
 	sb->sb_cc += nn;
@@ -296,7 +286,7 @@ err:
 
 
     sofcantrcvmore(so);
     sofcantrcvmore(so);
     tcp_sockclosed(sototcpcb(so));
     tcp_sockclosed(sototcpcb(so));
-    fprintf(stderr, "soreadbuf buffer to small");
+    g_critical("soreadbuf buffer too small");
     return -1;
     return -1;
 }
 }
 
 
@@ -381,7 +371,7 @@ sosendoob(struct socket *so)
 		n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
 		n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
 #ifdef DEBUG
 #ifdef DEBUG
 		if (n != len) {
 		if (n != len) {
-			DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
+			DEBUG_ERROR("Didn't send all data urgently XXXXX");
 		}
 		}
 #endif
 #endif
 	}
 	}
@@ -390,7 +380,7 @@ sosendoob(struct socket *so)
 		return n;
 		return n;
 	}
 	}
 	so->so_urgc -= n;
 	so->so_urgc -= n;
-	DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
+	DEBUG_MISC(" ---2 sent %d bytes urgent data, %d urgent bytes left", n, so->so_urgc);
 
 
 	sb->sb_cc -= n;
 	sb->sb_cc -= n;
 	sb->sb_rptr += n;
 	sb->sb_rptr += n;
@@ -456,13 +446,7 @@ sowrite(struct socket *so)
 	}
 	}
 	/* Check if there's urgent data to send, and if so, send it */
 	/* Check if there's urgent data to send, and if so, send it */
 
 
-#ifdef HAVE_READV
-	nn = writev(so->s, (const struct iovec *)iov, n);
-
-	DEBUG_MISC((dfd, "  ... wrote nn = %d bytes\n", nn));
-#else
 	nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0);
 	nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0);
-#endif
 	/* This should never happen, but people tell me it does *shrug* */
 	/* This should never happen, but people tell me it does *shrug* */
 	if (nn < 0 && (errno == EAGAIN || errno == EINTR))
 	if (nn < 0 && (errno == EAGAIN || errno == EINTR))
 		return 0;
 		return 0;
@@ -471,15 +455,13 @@ sowrite(struct socket *so)
 		goto err_disconnected;
 		goto err_disconnected;
 	}
 	}
 
 
-#ifndef HAVE_READV
 	if (n == 2 && nn == iov[0].iov_len) {
 	if (n == 2 && nn == iov[0].iov_len) {
             int ret;
             int ret;
             ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0);
             ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0);
             if (ret > 0)
             if (ret > 0)
                 nn += ret;
                 nn += ret;
         }
         }
-        DEBUG_MISC((dfd, "  ... wrote nn = %d bytes\n", nn));
-#endif
+        DEBUG_MISC("  ... wrote nn = %d bytes", nn);
 
 
 	/* Update sbuf */
 	/* Update sbuf */
 	sb->sb_cc -= nn;
 	sb->sb_cc -= nn;
@@ -497,8 +479,8 @@ sowrite(struct socket *so)
 	return nn;
 	return nn;
 
 
 err_disconnected:
 err_disconnected:
-	DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
-		    so->so_state, errno));
+	DEBUG_MISC(" --- sowrite disconnected, so->so_state = %x, errno = %d",
+               so->so_state, errno);
 	sofcantsendmore(so);
 	sofcantsendmore(so);
 	tcp_sockclosed(sototcpcb(so));
 	tcp_sockclosed(sototcpcb(so));
 	return -1;
 	return -1;
@@ -531,8 +513,8 @@ sorecvfrom(struct socket *so)
 	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
 	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
 	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
 	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
 
 
-	    DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
-			errno,strerror(errno)));
+	    DEBUG_MISC(" udp icmp rx errno = %d-%s",
+                   errno,strerror(errno));
 	    icmp_send_error(so->so_m, ICMP_UNREACH, code, 0, strerror(errno));
 	    icmp_send_error(so->so_m, ICMP_UNREACH, code, 0, strerror(errno));
 	  } else {
 	  } else {
 	    icmp_reflect(so->so_m);
 	    icmp_reflect(so->so_m);
@@ -583,8 +565,8 @@ sorecvfrom(struct socket *so)
 
 
 	  m->m_len = recvfrom(so->s, m->m_data, len, 0,
 	  m->m_len = recvfrom(so->s, m->m_data, len, 0,
 			      (struct sockaddr *)&addr, &addrlen);
 			      (struct sockaddr *)&addr, &addrlen);
-	  DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
-		      m->m_len, errno,strerror(errno)));
+	  DEBUG_MISC(" did recvfrom %d, errno = %d-%s",
+                 m->m_len, errno,strerror(errno));
 	  if(m->m_len<0) {
 	  if(m->m_len<0) {
 	    /* Report error as ICMP */
 	    /* Report error as ICMP */
 	    switch (so->so_lfamily) {
 	    switch (so->so_lfamily) {
@@ -598,7 +580,7 @@ sorecvfrom(struct socket *so)
 		code = ICMP_UNREACH_NET;
 		code = ICMP_UNREACH_NET;
 	      }
 	      }
 
 
-	      DEBUG_MISC((dfd, " rx error, tx icmp ICMP_UNREACH:%i\n", code));
+	      DEBUG_MISC(" rx error, tx icmp ICMP_UNREACH:%i", code);
 	      icmp_send_error(so->so_m, ICMP_UNREACH, code, 0, strerror(errno));
 	      icmp_send_error(so->so_m, ICMP_UNREACH, code, 0, strerror(errno));
 	      break;
 	      break;
 	    case AF_INET6:
 	    case AF_INET6:
@@ -610,7 +592,7 @@ sorecvfrom(struct socket *so)
 		code = ICMP6_UNREACH_NO_ROUTE;
 		code = ICMP6_UNREACH_NO_ROUTE;
 	      }
 	      }
 
 
-	      DEBUG_MISC((dfd, " rx error, tx icmp6 ICMP_UNREACH:%i\n", code));
+	      DEBUG_MISC(" rx error, tx icmp6 ICMP_UNREACH:%i", code);
 	      icmp6_send_error(so->so_m, ICMP6_UNREACH, code);
 	      icmp6_send_error(so->so_m, ICMP6_UNREACH, code);
 	      break;
 	      break;
 	    default:
 	    default:
@@ -858,9 +840,8 @@ void sotranslate_out(struct socket *so, struct sockaddr_storage *addr)
             }
             }
         }
         }
 
 
-        DEBUG_MISC((dfd, " addr.sin_port=%d, "
-            "addr.sin_addr.s_addr=%.16s\n",
-            ntohs(sin->sin_port), inet_ntoa(sin->sin_addr)));
+        DEBUG_MISC(" addr.sin_port=%d, addr.sin_addr.s_addr=%.16s",
+                   ntohs(sin->sin_port), inet_ntoa(sin->sin_addr));
         break;
         break;
 
 
     case AF_INET6:
     case AF_INET6:

+ 1 - 1
slirp/socket.h

@@ -67,7 +67,7 @@ struct socket {
 
 
   struct sbuf so_rcv;		/* Receive buffer */
   struct sbuf so_rcv;		/* Receive buffer */
   struct sbuf so_snd;		/* Send buffer */
   struct sbuf so_snd;		/* Send buffer */
-  void * extra;			/* Extra pointer */
+  void * chardev;
 };
 };
 
 
 
 

+ 3 - 1
slirp/tcp.h

@@ -33,6 +33,8 @@
 #ifndef TCP_H
 #ifndef TCP_H
 #define TCP_H
 #define TCP_H
 
 
+#include <glib.h>
+
 typedef	uint32_t tcp_seq;
 typedef	uint32_t tcp_seq;
 
 
 #define      PR_SLOWHZ       2               /* 2 slow timeouts per second (approx) */
 #define      PR_SLOWHZ       2               /* 2 slow timeouts per second (approx) */
@@ -51,7 +53,7 @@ struct tcphdr {
 	uint16_t th_dport;              /* destination port */
 	uint16_t th_dport;              /* destination port */
 	tcp_seq	th_seq;			/* sequence number */
 	tcp_seq	th_seq;			/* sequence number */
 	tcp_seq	th_ack;			/* acknowledgement number */
 	tcp_seq	th_ack;			/* acknowledgement number */
-#ifdef HOST_WORDS_BIGENDIAN
+#if G_BYTE_ORDER == G_BIG_ENDIAN
 	uint8_t	th_off:4,		/* data offset */
 	uint8_t	th_off:4,		/* data offset */
 		th_x2:4;		/* (unused) */
 		th_x2:4;		/* (unused) */
 #else
 #else

+ 11 - 73
slirp/tcp_input.c

@@ -60,27 +60,6 @@
  * Set DELACK for segments received in order, but ack immediately
  * Set DELACK for segments received in order, but ack immediately
  * when segments are out of order (so fast retransmit can work).
  * when segments are out of order (so fast retransmit can work).
  */
  */
-#ifdef TCP_ACK_HACK
-#define TCP_REASS(tp, ti, m, so, flags) {\
-       if ((ti)->ti_seq == (tp)->rcv_nxt && \
-           tcpfrag_list_empty(tp) && \
-           (tp)->t_state == TCPS_ESTABLISHED) {\
-               if (ti->ti_flags & TH_PUSH) \
-                       tp->t_flags |= TF_ACKNOW; \
-               else \
-                       tp->t_flags |= TF_DELACK; \
-               (tp)->rcv_nxt += (ti)->ti_len; \
-               flags = (ti)->ti_flags & TH_FIN; \
-               if (so->so_emu) { \
-		       if (tcp_emu((so),(m))) sbappend((so), (m)); \
-	       } else \
-		       sbappend((so), (m)); \
-	} else {\
-               (flags) = tcp_reass((tp), (ti), (m)); \
-               tp->t_flags |= TF_ACKNOW; \
-       } \
-}
-#else
 #define	TCP_REASS(tp, ti, m, so, flags) { \
 #define	TCP_REASS(tp, ti, m, so, flags) { \
 	if ((ti)->ti_seq == (tp)->rcv_nxt && \
 	if ((ti)->ti_seq == (tp)->rcv_nxt && \
         tcpfrag_list_empty(tp) && \
         tcpfrag_list_empty(tp) && \
@@ -97,7 +76,7 @@
 		tp->t_flags |= TF_ACKNOW; \
 		tp->t_flags |= TF_ACKNOW; \
 	} \
 	} \
 }
 }
-#endif
+
 static void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt,
 static void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt,
                           struct tcpiphdr *ti);
                           struct tcpiphdr *ti);
 static void tcp_xmit_timer(register struct tcpcb *tp, int rtt);
 static void tcp_xmit_timer(register struct tcpcb *tp, int rtt);
@@ -232,12 +211,12 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, unsigned short af)
 	struct sockaddr_storage lhost, fhost;
 	struct sockaddr_storage lhost, fhost;
 	struct sockaddr_in *lhost4, *fhost4;
 	struct sockaddr_in *lhost4, *fhost4;
 	struct sockaddr_in6 *lhost6, *fhost6;
 	struct sockaddr_in6 *lhost6, *fhost6;
-    struct ex_list *ex_ptr;
+    struct gfwd_list *ex_ptr;
     Slirp *slirp;
     Slirp *slirp;
 
 
 	DEBUG_CALL("tcp_input");
 	DEBUG_CALL("tcp_input");
-	DEBUG_ARGS((dfd, " m = %p  iphlen = %2d  inso = %p\n",
-		    m, iphlen, inso));
+	DEBUG_ARG("m = %p  iphlen = %2d  inso = %p",
+              m, iphlen, inso);
 
 
 	/*
 	/*
 	 * If called with m == 0, then we're continuing the connect
 	 * If called with m == 0, then we're continuing the connect
@@ -415,7 +394,7 @@ findso:
              * for non-hostfwd connections. These should be dropped, unless it
              * for non-hostfwd connections. These should be dropped, unless it
              * happens to be a guestfwd.
              * happens to be a guestfwd.
              */
              */
-            for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+            for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
                 if (ex_ptr->ex_fport == ti->ti_dport &&
                 if (ex_ptr->ex_fport == ti->ti_dport &&
                     ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) {
                     ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) {
                     break;
                     break;
@@ -481,7 +460,7 @@ findso:
 	 * Reset idle time and keep-alive timer.
 	 * Reset idle time and keep-alive timer.
 	 */
 	 */
 	tp->t_idle = 0;
 	tp->t_idle = 0;
-	if (SO_OPTIONS)
+	if (slirp_do_keepalive)
 	   tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
 	   tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
 	else
 	else
 	   tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
 	   tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
@@ -637,7 +616,7 @@ findso:
 	    if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr &&
 	    if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr &&
 		so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) {
 		so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) {
 		/* May be an add exec */
 		/* May be an add exec */
-		for (ex_ptr = slirp->exec_list; ex_ptr;
+		for (ex_ptr = slirp->guestfwd_list; ex_ptr;
 		     ex_ptr = ex_ptr->ex_next) {
 		     ex_ptr = ex_ptr->ex_next) {
 		  if(ex_ptr->ex_fport == so->so_fport &&
 		  if(ex_ptr->ex_fport == so->so_fport &&
 		     so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
 		     so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
@@ -662,8 +641,7 @@ findso:
               (errno != EINPROGRESS) && (errno != EWOULDBLOCK)
               (errno != EINPROGRESS) && (errno != EWOULDBLOCK)
           ) {
           ) {
 	    uint8_t code;
 	    uint8_t code;
-	    DEBUG_MISC((dfd, " tcp fconnect errno = %d-%s\n",
-			errno,strerror(errno)));
+	    DEBUG_MISC(" tcp fconnect errno = %d-%s", errno, strerror(errno));
 	    if(errno == ECONNREFUSED) {
 	    if(errno == ECONNREFUSED) {
 	      /* ACK the SYN, send RST to refuse the connection */
 	      /* ACK the SYN, send RST to refuse the connection */
 	      tcp_respond(tp, ti, m, ti->ti_seq + 1, (tcp_seq) 0,
 	      tcp_respond(tp, ti, m, ti->ti_seq + 1, (tcp_seq) 0,
@@ -1032,8 +1010,7 @@ trimthenstep6:
 
 
 		if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
 		if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
 			if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {
 			if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {
-			  DEBUG_MISC((dfd, " dup ack  m = %p  so = %p\n",
-				      m, so));
+			  DEBUG_MISC(" dup ack  m = %p  so = %p", m, so);
 				/*
 				/*
 				 * If we have outstanding data (other than
 				 * If we have outstanding data (other than
 				 * a window probe), this is a completely
 				 * a window probe), this is a completely
@@ -1411,7 +1388,7 @@ tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)
 	int opt, optlen;
 	int opt, optlen;
 
 
 	DEBUG_CALL("tcp_dooptions");
 	DEBUG_CALL("tcp_dooptions");
-	DEBUG_ARGS((dfd, " tp = %p  cnt=%i\n", tp, cnt));
+	DEBUG_ARG("tp = %p  cnt=%i", tp, cnt);
 
 
 	for (; cnt > 0; cnt -= optlen, cp += optlen) {
 	for (; cnt > 0; cnt -= optlen, cp += optlen) {
 		opt = cp[0];
 		opt = cp[0];
@@ -1442,45 +1419,6 @@ tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)
 	}
 	}
 }
 }
 
 
-
-/*
- * Pull out of band byte out of a segment so
- * it doesn't appear in the user's data queue.
- * It is still reflected in the segment length for
- * sequencing purposes.
- */
-
-#ifdef notdef
-
-void
-tcp_pulloutofband(so, ti, m)
-	struct socket *so;
-	struct tcpiphdr *ti;
-	register struct mbuf *m;
-{
-	int cnt = ti->ti_urp - 1;
-
-	while (cnt >= 0) {
-		if (m->m_len > cnt) {
-			char *cp = mtod(m, caddr_t) + cnt;
-			struct tcpcb *tp = sototcpcb(so);
-
-			tp->t_iobc = *cp;
-			tp->t_oobflags |= TCPOOB_HAVEDATA;
-			memcpy(sp, cp+1, (unsigned)(m->m_len - cnt - 1));
-			m->m_len--;
-			return;
-		}
-		cnt -= m->m_len;
-		m = m->m_next; /* XXX WRONG! Fix it! */
-		if (m == 0)
-			break;
-	}
-	panic("tcp_pulloutofband");
-}
-
-#endif /* notdef */
-
 /*
 /*
  * Collect new round-trip time estimate
  * Collect new round-trip time estimate
  * and update averages and current timeout.
  * and update averages and current timeout.
@@ -1611,7 +1549,7 @@ tcp_mss(struct tcpcb *tp, u_int offer)
                                                (mss - (TCP_RCVSPACE % mss)) :
                                                (mss - (TCP_RCVSPACE % mss)) :
                                                0));
                                                0));
 
 
-	DEBUG_MISC((dfd, " returning mss = %d\n", mss));
+	DEBUG_MISC(" returning mss = %d", mss);
 
 
 	return mss;
 	return mss;
 }
 }

+ 1 - 1
slirp/tcp_output.c

@@ -92,7 +92,7 @@ again:
 
 
 	flags = tcp_outflags[tp->t_state];
 	flags = tcp_outflags[tp->t_state];
 
 
-	DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags));
+	DEBUG_MISC(" --- tcp_output flags = 0x%x", flags);
 
 
 	/*
 	/*
 	 * If in persist timeout with window of 0, send 1 byte.
 	 * If in persist timeout with window of 0, send 1 byte.

+ 12 - 10
slirp/tcp_subr.c

@@ -420,7 +420,7 @@ int tcp_fconnect(struct socket *so, unsigned short af)
     qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
     qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
 
 
     addr = so->fhost.ss;
     addr = so->fhost.ss;
-    DEBUG_CALL(" connect()ing")
+    DEBUG_CALL(" connect()ing");
     sotranslate_out(so, &addr);
     sotranslate_out(so, &addr);
 
 
     /* We don't care what port we get */
     /* We don't care what port we get */
@@ -541,7 +541,6 @@ static const struct tos_t tcptos[] = {
 	  {0, 23, IPTOS_LOWDELAY, 0},	/* telnet */
 	  {0, 23, IPTOS_LOWDELAY, 0},	/* telnet */
 	  {0, 80, IPTOS_THROUGHPUT, 0},	/* WWW */
 	  {0, 80, IPTOS_THROUGHPUT, 0},	/* WWW */
 	  {0, 513, IPTOS_LOWDELAY, EMU_RLOGIN|EMU_NOCONNECT},	/* rlogin */
 	  {0, 513, IPTOS_LOWDELAY, EMU_RLOGIN|EMU_NOCONNECT},	/* rlogin */
-	  {0, 514, IPTOS_LOWDELAY, EMU_RSH|EMU_NOCONNECT},	/* shell */
 	  {0, 544, IPTOS_LOWDELAY, EMU_KSH},		/* kshell */
 	  {0, 544, IPTOS_LOWDELAY, EMU_KSH},		/* kshell */
 	  {0, 543, IPTOS_LOWDELAY, 0},	/* klogin */
 	  {0, 543, IPTOS_LOWDELAY, 0},	/* klogin */
 	  {0, 6667, IPTOS_THROUGHPUT, EMU_IRC},	/* IRC */
 	  {0, 6667, IPTOS_THROUGHPUT, EMU_IRC},	/* IRC */
@@ -635,6 +634,11 @@ tcp_emu(struct socket *so, struct mbuf *m)
 			socklen_t addrlen = sizeof(struct sockaddr_in);
 			socklen_t addrlen = sizeof(struct sockaddr_in);
 			struct sbuf *so_rcv = &so->so_rcv;
 			struct sbuf *so_rcv = &so->so_rcv;
 
 
+			if (m->m_len > so_rcv->sb_datalen
+					- (so_rcv->sb_wptr - so_rcv->sb_data)) {
+			    return 1;
+			}
+
 			memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
 			memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
 			so_rcv->sb_wptr += m->m_len;
 			so_rcv->sb_wptr += m->m_len;
 			so_rcv->sb_rptr += m->m_len;
 			so_rcv->sb_rptr += m->m_len;
@@ -950,25 +954,23 @@ int tcp_ctl(struct socket *so)
 {
 {
     Slirp *slirp = so->slirp;
     Slirp *slirp = so->slirp;
     struct sbuf *sb = &so->so_snd;
     struct sbuf *sb = &so->so_snd;
-    struct ex_list *ex_ptr;
-    int do_pty;
+    struct gfwd_list *ex_ptr;
 
 
     DEBUG_CALL("tcp_ctl");
     DEBUG_CALL("tcp_ctl");
     DEBUG_ARG("so = %p", so);
     DEBUG_ARG("so = %p", so);
 
 
     if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
     if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
         /* Check if it's pty_exec */
         /* Check if it's pty_exec */
-        for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+        for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
             if (ex_ptr->ex_fport == so->so_fport &&
             if (ex_ptr->ex_fport == so->so_fport &&
                 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
                 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
-                if (ex_ptr->ex_pty == 3) {
+                if (ex_ptr->ex_chardev) {
                     so->s = -1;
                     so->s = -1;
-                    so->extra = (void *)ex_ptr->ex_exec;
+                    so->chardev = ex_ptr->ex_chardev;
                     return 1;
                     return 1;
                 }
                 }
-                do_pty = ex_ptr->ex_pty;
-                DEBUG_MISC((dfd, " executing %s\n", ex_ptr->ex_exec));
-                return fork_exec(so, ex_ptr->ex_exec, do_pty);
+                DEBUG_MISC(" executing %s", ex_ptr->ex_exec);
+                return fork_exec(so, ex_ptr->ex_exec);
             }
             }
         }
         }
     }
     }

+ 1 - 1
slirp/tcp_timer.c

@@ -262,7 +262,7 @@ tcp_timers(register struct tcpcb *tp, int timer)
 		if (tp->t_state < TCPS_ESTABLISHED)
 		if (tp->t_state < TCPS_ESTABLISHED)
 			goto dropit;
 			goto dropit;
 
 
-		if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) {
+		if (slirp_do_keepalive && tp->t_state <= TCPS_CLOSE_WAIT) {
 			if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE)
 			if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE)
 				goto dropit;
 				goto dropit;
 			/*
 			/*

+ 5 - 2
slirp/tftp.c

@@ -26,6 +26,7 @@
 #include "slirp.h"
 #include "slirp.h"
 #include "qemu-common.h"
 #include "qemu-common.h"
 #include "qemu/cutils.h"
 #include "qemu/cutils.h"
+#include "trace.h"
 
 
 static inline int tftp_session_in_use(struct tftp_session *spt)
 static inline int tftp_session_in_use(struct tftp_session *spt)
 {
 {
@@ -204,6 +205,7 @@ static void tftp_send_error(struct tftp_session *spt,
   struct mbuf *m;
   struct mbuf *m;
   struct tftp_t *tp;
   struct tftp_t *tp;
 
 
+  trace_slirp_tftp_error(msg);
   m = m_get(spt->slirp);
   m = m_get(spt->slirp);
 
 
   if (!m) {
   if (!m) {
@@ -323,6 +325,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas,
       break;
       break;
     }
     }
   }
   }
+  trace_slirp_tftp_rrq(req_fname);
 
 
   /* check mode */
   /* check mode */
   if ((pktlen - k) < 6) {
   if ((pktlen - k) < 6) {
@@ -356,7 +359,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas,
       return;
       return;
   }
   }
 
 
-  while (k < pktlen && nb_options < ARRAY_SIZE(option_name)) {
+  while (k < pktlen && nb_options < G_N_ELEMENTS(option_name)) {
       const char *key, *value;
       const char *key, *value;
 
 
       key = &tp->x.tp_buf[k];
       key = &tp->x.tp_buf[k];
@@ -400,7 +403,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas,
   }
   }
 
 
   if (nb_options > 0) {
   if (nb_options > 0) {
-      assert(nb_options <= ARRAY_SIZE(option_name));
+      assert(nb_options <= G_N_ELEMENTS(option_name));
       tftp_send_oack(spt, option_name, option_value, nb_options, tp);
       tftp_send_oack(spt, option_name, option_value, nb_options, tp);
       return;
       return;
   }
   }

+ 5 - 0
slirp/trace-events

@@ -0,0 +1,5 @@
+# See docs/devel/tracing.txt for syntax documentation.
+
+# slirp/tftp.c
+slirp_tftp_rrq(const char *file) "file: %s"
+slirp_tftp_error(const char *file) "msg: %s"

+ 2 - 3
slirp/udp.c

@@ -172,8 +172,7 @@ udp_input(register struct mbuf *m, int iphlen)
 	   */
 	   */
 	  so = socreate(slirp);
 	  so = socreate(slirp);
 	  if (udp_attach(so, AF_INET) == -1) {
 	  if (udp_attach(so, AF_INET) == -1) {
-	    DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
-			errno,strerror(errno)));
+	    DEBUG_MISC(" udp_attach errno = %d-%s", errno, strerror(errno));
 	    sofree(so);
 	    sofree(so);
 	    goto bad;
 	    goto bad;
 	  }
 	  }
@@ -209,7 +208,7 @@ udp_input(register struct mbuf *m, int iphlen)
 	  m->m_len += iphlen;
 	  m->m_len += iphlen;
 	  m->m_data -= iphlen;
 	  m->m_data -= iphlen;
 	  *ip=save_ip;
 	  *ip=save_ip;
-	  DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
+	  DEBUG_MISC("udp tx errno = %d-%s", errno, strerror(errno));
 	  icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0,
 	  icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0,
 	                  strerror(errno));
 	                  strerror(errno));
 	  goto bad;
 	  goto bad;

+ 5 - 6
slirp/udp6.c

@@ -20,7 +20,7 @@ void udp6_input(struct mbuf *m)
     struct sockaddr_in6 lhost;
     struct sockaddr_in6 lhost;
 
 
     DEBUG_CALL("udp6_input");
     DEBUG_CALL("udp6_input");
-    DEBUG_ARG("m = %lx", (long)m);
+    DEBUG_ARG("m = %p", m);
 
 
     if (slirp->restricted) {
     if (slirp->restricted) {
         goto bad;
         goto bad;
@@ -92,8 +92,7 @@ void udp6_input(struct mbuf *m)
         /* If there's no socket for this packet, create one. */
         /* If there's no socket for this packet, create one. */
         so = socreate(slirp);
         so = socreate(slirp);
         if (udp_attach(so, AF_INET6) == -1) {
         if (udp_attach(so, AF_INET6) == -1) {
-            DEBUG_MISC((dfd, " udp6_attach errno = %d-%s\n",
-                        errno, strerror(errno)));
+            DEBUG_MISC(" udp6_attach errno = %d-%s", errno, strerror(errno));
             sofree(so);
             sofree(so);
             goto bad;
             goto bad;
         }
         }
@@ -119,7 +118,7 @@ void udp6_input(struct mbuf *m)
         m->m_len += iphlen;
         m->m_len += iphlen;
         m->m_data -= iphlen;
         m->m_data -= iphlen;
         *ip = save_ip;
         *ip = save_ip;
-        DEBUG_MISC((dfd, "udp tx errno = %d-%s\n", errno, strerror(errno)));
+        DEBUG_MISC("udp tx errno = %d-%s", errno, strerror(errno));
         icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
         icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
         goto bad;
         goto bad;
     }
     }
@@ -144,8 +143,8 @@ int udp6_output(struct socket *so, struct mbuf *m,
     struct udphdr *uh;
     struct udphdr *uh;
 
 
     DEBUG_CALL("udp6_output");
     DEBUG_CALL("udp6_output");
-    DEBUG_ARG("so = %lx", (long)so);
-    DEBUG_ARG("m = %lx", (long)m);
+    DEBUG_ARG("so = %p", so);
+    DEBUG_ARG("m = %p", m);
 
 
     /* adjust for header */
     /* adjust for header */
     m->m_data -= sizeof(struct udphdr);
     m->m_data -= sizeof(struct udphdr);

+ 1 - 1
stubs/slirp.c

@@ -1,7 +1,7 @@
 #include "qemu/osdep.h"
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qemu-common.h"
 #include "qemu/host-utils.h"
 #include "qemu/host-utils.h"
-#include "slirp/slirp.h"
+#include "slirp/libslirp.h"
 
 
 void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout)
 void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout)
 {
 {