mirror of https://github.com/xemu-project/xemu.git
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 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE5h27FdQXK97JfpLZ21UOifD6VPMFAlw9ErAACgkQ21UOifD6 VPN9Yg//aAff/bSkpBXYZrtFj+EtNxFyHubloruEfsalra5FmLoiPpsCIeF0Ta1O MkglD3RCi1/wt91O+/ccerNUL4ZD9F7lLorg7Zyor2F/l+hfrY8hJwalP47Owa88 DUNrwYvVyKFU6k0EW3zwzYHYpnfjLNBhdgGGqwrZJ8kDOLNNsIGKvpge4BqfhmZU K0vfjTuAyJ4rHJYFn9T8m0LSdM4wnzPDtkPy1KL4UF2rxTM8EXKht1NtiT7QEp8U klQ8Or60PzXzJY3QU8W+ameM3YUP3YOWCLlRpt9+K65/ZY5OJI0pWNFHgqGX5pDZ NtL5XeUJqmgHza2TtSIeG1VEf/z9OKnQNFWdAv/DSEGxxrnnQF8YLsj3IUAIAP7V 5yZ8X7MtfMpmsKA9Z7JBg0T5s/sVGo68yWxNwdUTjiWD2GWwLYxWeq5VPHYc5EjC 0Sl8pPkXXBxAitZvsRghR+/Nduhyc2aZ06Oe/nhOydovijsq7eSsom2rV125UcXM DQulu+Zaqhkys5oXmrUXMmLYzz0ES1YKFRMPBjspbz6FtDTpRpkhEmvOozEiptaY 2+kztjbLgnwN/3oeag+fL4dyD2Px537wmIzZJue+e2L4+YpSOdpbKCnr54vwZ88I ubcm8WPsE4FZiNm8PxuOXjRq+T/rvgucfcmNu61+X2fJU+1MpNo= =54xe -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
6f2f34177a
5
Makefile
5
Makefile
|
@ -379,7 +379,8 @@ dummy := $(call unnest-vars,, \
|
|||
ui-obj-m \
|
||||
audio-obj-y \
|
||||
audio-obj-m \
|
||||
trace-obj-y)
|
||||
trace-obj-y \
|
||||
slirp-obj-y)
|
||||
|
||||
include $(SRC_PATH)/tests/Makefile.include
|
||||
|
||||
|
@ -452,7 +453,7 @@ CAP_CFLAGS += -DCAPSTONE_HAS_X86
|
|||
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))
|
||||
|
||||
$(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))
|
||||
|
||||
ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
|
||||
|
|
|
@ -17,6 +17,7 @@ util-obj-y += $(QAPI_MODULES:%=qapi/qapi-events-%.o)
|
|||
util-obj-y += qapi/qapi-introspect.o
|
||||
|
||||
chardev-obj-y = chardev/
|
||||
slirp-obj-$(CONFIG_SLIRP) = slirp/
|
||||
|
||||
#######################################################################
|
||||
# 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)
|
||||
common-obj-$(CONFIG_TPM) += tpm.o
|
||||
|
||||
common-obj-$(CONFIG_SLIRP) += slirp/
|
||||
|
||||
common-obj-y += backends/
|
||||
common-obj-y += chardev/
|
||||
|
||||
|
@ -193,6 +192,7 @@ trace-events-subdirs += net
|
|||
trace-events-subdirs += qapi
|
||||
trace-events-subdirs += qom
|
||||
trace-events-subdirs += scsi
|
||||
trace-events-subdirs += slirp
|
||||
trace-events-subdirs += target/arm
|
||||
trace-events-subdirs += target/i386
|
||||
trace-events-subdirs += target/mips
|
||||
|
|
|
@ -165,6 +165,7 @@ target-obj-y :=
|
|||
block-obj-y :=
|
||||
common-obj-y :=
|
||||
chardev-obj-y :=
|
||||
slirp-obj-y :=
|
||||
include $(SRC_PATH)/Makefile.objs
|
||||
dummy := $(call unnest-vars,,target-obj-y)
|
||||
target-obj-y-save := $(target-obj-y)
|
||||
|
@ -177,7 +178,8 @@ dummy := $(call unnest-vars,.., \
|
|||
qom-obj-y \
|
||||
io-obj-y \
|
||||
common-obj-y \
|
||||
common-obj-m)
|
||||
common-obj-m \
|
||||
slirp-obj-y)
|
||||
target-obj-y := $(target-obj-y-save)
|
||||
all-obj-y += $(common-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_SOFTMMU) += $(crypto-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)
|
||||
all-obj-$(CONFIG_SOFTMMU) += $(slirp-obj-y)
|
||||
|
||||
$(QEMU_PROG_BUILD): config-devices.mak
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
#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)
|
||||
/*
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "net/colo-compare.h"
|
||||
#include "migration/colo.h"
|
||||
#include "migration/migration.h"
|
||||
#include "util.h"
|
||||
|
||||
#define TYPE_COLO_COMPARE "colo-compare"
|
||||
#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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static void fill_pkt_tcp_info(void *data, uint32_t *max_ack)
|
||||
{
|
||||
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_ack = ntohl(tcphd->th_ack);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "trace.h"
|
||||
#include "colo.h"
|
||||
#include "util.h"
|
||||
|
||||
uint32_t connection_key_hash(const void *opaque)
|
||||
{
|
||||
|
|
|
@ -15,10 +15,9 @@
|
|||
#ifndef QEMU_COLO_PROXY_H
|
||||
#define QEMU_COLO_PROXY_H
|
||||
|
||||
#include "slirp/slirp.h"
|
||||
#include "qemu/jhash.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "slirp/tcp.h"
|
||||
#include "net/eth.h"
|
||||
|
||||
#define HASHTABLE_MAX_SIZE 16384
|
||||
|
||||
|
@ -81,10 +80,10 @@ typedef struct Connection {
|
|||
/* the maximum of acknowledgement number in secondary_list queue */
|
||||
uint32_t sack;
|
||||
/* offset = secondary_seq - primary_seq */
|
||||
tcp_seq offset;
|
||||
uint32_t offset;
|
||||
|
||||
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;
|
||||
|
||||
uint32_t connection_key_hash(const void *opaque);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "net/checksum.h"
|
||||
#include "net/colo.h"
|
||||
#include "migration/colo.h"
|
||||
#include "util.h"
|
||||
|
||||
#define FILTER_COLO_REWRITER(obj) \
|
||||
OBJECT_CHECK(RewriterState, (obj), TYPE_FILTER_REWRITER)
|
||||
|
@ -73,9 +74,9 @@ static int handle_primary_tcp_pkt(RewriterState *rf,
|
|||
Connection *conn,
|
||||
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)) {
|
||||
trace_colo_filter_rewriter_pkt_info(__func__,
|
||||
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,
|
||||
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)) {
|
||||
trace_colo_filter_rewriter_pkt_info(__func__,
|
||||
|
|
61
net/slirp.c
61
net/slirp.c
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "net/slirp.h"
|
||||
|
||||
|
||||
|
@ -37,12 +38,12 @@
|
|||
#include "qemu/error-report.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "slirp/libslirp.h"
|
||||
#include "slirp/ip6.h"
|
||||
#include "chardev/char-fe.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "util.h"
|
||||
|
||||
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) { }
|
||||
#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;
|
||||
|
||||
|
@ -140,6 +141,22 @@ static NetClientInfo net_slirp_info = {
|
|||
.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,
|
||||
const char *name, int restricted,
|
||||
bool ipv4, const char *vnetwork, const char *vhost,
|
||||
|
@ -279,17 +296,6 @@ static int net_slirp_init(NetClientState *peer, const char *model,
|
|||
}
|
||||
#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) {
|
||||
vprefix6 = "fec0::";
|
||||
}
|
||||
|
@ -297,7 +303,6 @@ static int net_slirp_init(NetClientState *peer, const char *model,
|
|||
error_setg(errp, "Failed to parse IPv6 prefix");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!vprefix6_len) {
|
||||
vprefix6_len = 64;
|
||||
|
@ -309,10 +314,6 @@ static int net_slirp_init(NetClientState *peer, const char *model,
|
|||
}
|
||||
|
||||
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)) {
|
||||
error_setg(errp, "Failed to parse IPv6 host");
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
ip6_host = ip6_prefix;
|
||||
ip6_host.s6_addr[15] |= 2;
|
||||
}
|
||||
|
||||
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)) {
|
||||
error_setg(errp, "Failed to parse IPv6 DNS");
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
ip6_dns = ip6_prefix;
|
||||
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,
|
||||
vhostname, tftp_server_name,
|
||||
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);
|
||||
|
||||
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);
|
||||
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);
|
||||
g_free(smb_cmdline);
|
||||
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);
|
||||
|
||||
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 "
|
||||
"forwarding rule '%s'", config_str);
|
||||
return -1;
|
||||
|
@ -800,7 +796,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
|
|||
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 "
|
||||
"forwarding rule '%s'", config_str);
|
||||
g_free(fwd);
|
||||
|
@ -827,10 +823,11 @@ void hmp_info_usernet(Monitor *mon, const QDict *qdict)
|
|||
QTAILQ_FOREACH(s, &slirp_stacks, entry) {
|
||||
int id;
|
||||
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,
|
||||
s->nc.name);
|
||||
slirp_connection_info(s->slirp, mon);
|
||||
s->nc.name, info);
|
||||
g_free(info);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
55
net/util.h
55
net/util.h
|
@ -26,6 +26,61 @@
|
|||
#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);
|
||||
|
||||
#endif /* QEMU_NET_UTIL_H */
|
||||
|
|
|
@ -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\"
|
||||
|
|
|
@ -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_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) {
|
||||
/* 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++) {
|
||||
if (arptbl->table[i].ar_sip == ip_addr) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,12 +36,7 @@
|
|||
|
||||
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,
|
||||
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);
|
||||
if (preq_addr.s_addr != htonl(0L))
|
||||
DPRINTF(" req_addr=%08" PRIx32 "\n", ntohl(preq_addr.s_addr));
|
||||
else
|
||||
else {
|
||||
DPRINTF("\n");
|
||||
}
|
||||
|
||||
if (dhcp_msg_type == 0)
|
||||
dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */
|
||||
|
|
|
@ -70,9 +70,7 @@ int cksum(struct mbuf *m, int len)
|
|||
|
||||
if (len < mlen)
|
||||
mlen = len;
|
||||
#ifdef DEBUG
|
||||
len -= mlen;
|
||||
#endif
|
||||
/*
|
||||
* Force to even boundary.
|
||||
*/
|
||||
|
@ -122,12 +120,10 @@ int cksum(struct mbuf *m, int len)
|
|||
s_util.c[0] = *(uint8_t *)w;
|
||||
|
||||
cont:
|
||||
#ifdef DEBUG
|
||||
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) {
|
||||
/* The last mbuf has odd # of bytes. Follow the
|
||||
standard (the odd byte may be shifted left by 8 bits
|
||||
|
|
|
@ -5,30 +5,37 @@
|
|||
* terms and conditions of the copyright.
|
||||
*/
|
||||
|
||||
//#define DEBUG 1
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifndef DEBUG_H_
|
||||
#define DEBUG_H_
|
||||
|
||||
#define DBG_CALL 0x1
|
||||
#define DBG_MISC 0x2
|
||||
#define DBG_ERROR 0x4
|
||||
|
||||
#define dfd stderr
|
||||
|
||||
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); }
|
||||
#define DEBUG_CALL(fmt, ...) do { \
|
||||
if (G_UNLIKELY(slirp_debug & DBG_CALL)) { \
|
||||
g_debug(fmt "...", ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define DEBUG_ARG(fmt, ...) do { \
|
||||
if (G_UNLIKELY(slirp_debug & DBG_CALL)) { \
|
||||
g_debug(" " fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DEBUG_CALL(x)
|
||||
#define DEBUG_ARG(x, y)
|
||||
#define DEBUG_ARGS(x)
|
||||
#define DEBUG_MISC(x)
|
||||
#define DEBUG_ERROR(x)
|
||||
#define DEBUG_MISC(fmt, ...) do { \
|
||||
if (G_UNLIKELY(slirp_debug & DBG_MISC)) { \
|
||||
g_debug(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
#define DEBUG_ERROR(fmt, ...) do { \
|
||||
if (G_UNLIKELY(slirp_debug & DBG_ERROR)) { \
|
||||
g_debug(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* DEBUG_H_ */
|
||||
|
|
|
@ -50,7 +50,7 @@ struct requested_infos {
|
|||
* the odata region, thus the caller must keep odata valid as long as it
|
||||
* 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)
|
||||
{
|
||||
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];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -92,14 +92,14 @@ static int dhcpv6_parse_info_request(uint8_t *odata, int olen,
|
|||
ri->want_boot_url = true;
|
||||
break;
|
||||
default:
|
||||
DEBUG_MISC((dfd, "dhcpv6: Unsupported option request %d\n",
|
||||
req_opt));
|
||||
DEBUG_MISC("dhcpv6: Unsupported option request %d",
|
||||
req_opt);
|
||||
}
|
||||
}
|
||||
break;
|
||||
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;
|
||||
|
@ -121,7 +121,7 @@ static void dhcpv6_info_request(Slirp *slirp, struct sockaddr_in6 *srcsas,
|
|||
struct mbuf *m;
|
||||
uint8_t *resp;
|
||||
|
||||
if (dhcpv6_parse_info_request(odata, olen, &ri) < 0) {
|
||||
if (dhcpv6_parse_info_request(slirp, odata, olen, &ri) < 0) {
|
||||
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);
|
||||
break;
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,12 +131,10 @@ diddit:
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef FULL_BOLT
|
||||
/*
|
||||
* This prevents us from malloc()ing too many mbufs
|
||||
*/
|
||||
if_start(ifm->slirp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -150,7 +148,7 @@ diddit:
|
|||
*/
|
||||
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;
|
||||
struct mbuf *ifm, *ifm_next, *ifqt;
|
||||
|
||||
|
|
10
slirp/ip.h
10
slirp/ip.h
|
@ -33,7 +33,9 @@
|
|||
#ifndef IP_H
|
||||
#define IP_H
|
||||
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
#include <glib.h>
|
||||
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
# undef NTOHL
|
||||
# undef NTOHS
|
||||
# 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.
|
||||
*/
|
||||
struct ip {
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
uint8_t ip_v:4, /* version */
|
||||
ip_hl:4; /* header length */
|
||||
#else
|
||||
|
@ -135,7 +137,7 @@ struct ip_timestamp {
|
|||
uint8_t ipt_code; /* IPOPT_TS */
|
||||
uint8_t ipt_len; /* size of structure (variable) */
|
||||
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 */
|
||||
ipt_flg:4; /* flags, see below */
|
||||
#else
|
||||
|
@ -175,7 +177,7 @@ struct ip_timestamp {
|
|||
|
||||
#define IP_MSS 576 /* default maximum segment size */
|
||||
|
||||
#if SIZEOF_CHAR_P == 4
|
||||
#if GLIB_SIZEOF_VOID_P == 4
|
||||
struct mbuf_ptr {
|
||||
struct mbuf *mptr;
|
||||
uint32_t dummy;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#ifndef SLIRP_IP6_H
|
||||
#define SLIRP_IP6_H
|
||||
|
||||
#include <glib.h>
|
||||
#include "net/eth.h"
|
||||
|
||||
#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.
|
||||
*/
|
||||
struct ip6 {
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
uint32_t
|
||||
ip_v:4, /* version */
|
||||
ip_tc_hi:4, /* traffic class */
|
||||
|
|
|
@ -17,7 +17,7 @@ static void ra_timer_handler(void *opaque)
|
|||
{
|
||||
Slirp *slirp = opaque;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ void icmp6_init(Slirp *slirp)
|
|||
SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
|
||||
ra_timer_handler, slirp);
|
||||
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)
|
||||
|
@ -74,9 +74,10 @@ void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code)
|
|||
Slirp *slirp = m->slirp;
|
||||
struct mbuf *t;
|
||||
struct ip6 *ip = mtod(m, struct ip6 *);
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
|
||||
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) ||
|
||||
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 *);
|
||||
rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR;
|
||||
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);
|
||||
DEBUG_ARG("target = %s", addrstr);
|
||||
#endif
|
||||
|
||||
rip->ip_nh = IPPROTO_ICMPV6;
|
||||
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)
|
||||
{
|
||||
DEBUG_CALL("ndp_send_ns");
|
||||
#if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600)
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
|
||||
inet_ntop(AF_INET6, &addr, addrstr, INET6_ADDRSTRLEN);
|
||||
|
||||
DEBUG_CALL("ndp_send_ns");
|
||||
DEBUG_ARG("target = %s", addrstr);
|
||||
#endif
|
||||
|
||||
/* Build IPv6 packet */
|
||||
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:
|
||||
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;
|
||||
|
||||
case ICMP6_NDP_NS:
|
||||
|
@ -376,8 +373,8 @@ static void ndp_input(struct mbuf *m, Slirp *slirp, struct ip6 *ip,
|
|||
|
||||
case ICMP6_NDP_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;
|
||||
}
|
||||
}
|
||||
|
@ -393,7 +390,7 @@ void icmp6_input(struct mbuf *m)
|
|||
int hlen = sizeof(struct ip6);
|
||||
|
||||
DEBUG_CALL("icmp6_input");
|
||||
DEBUG_ARG("m = %lx", (long) m);
|
||||
DEBUG_ARG("m = %p", m);
|
||||
DEBUG_ARG("m_len = %d", m->m_len);
|
||||
|
||||
if (ntohs(ip->ip_pl) < ICMP6_MINLEN) {
|
||||
|
@ -417,7 +414,7 @@ void icmp6_input(struct mbuf *m)
|
|||
icmp6_send_echoreply(m, slirp, ip, icmp);
|
||||
} else {
|
||||
/* TODO */
|
||||
error_report("external icmpv6 not supported yet");
|
||||
g_critical("external icmpv6 not supported yet");
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ struct ndp_rs { /* Router Solicitation Message */
|
|||
|
||||
struct ndp_ra { /* Router Advertisement Message */
|
||||
uint8_t chl; /* Cur Hop Limit */
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
uint8_t
|
||||
M:1,
|
||||
O:1,
|
||||
|
@ -56,7 +56,7 @@ struct ndp_ns { /* Neighbor Solicitation Message */
|
|||
} QEMU_PACKED;
|
||||
|
||||
struct ndp_na { /* Neighbor Advertisement Message */
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
uint32_t
|
||||
R:1, /* Router Flag */
|
||||
S:1, /* Solicited Flag */
|
||||
|
@ -125,7 +125,7 @@ struct ndpopt {
|
|||
#define ndpopt_linklayer ndpopt_body.linklayer_addr
|
||||
struct prefixinfo { /* Prefix Information */
|
||||
uint8_t prefix_length;
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
uint8_t L:1, A:1, reserved1:6;
|
||||
#else
|
||||
uint8_t reserved1:6, A:1, L:1;
|
||||
|
|
|
@ -31,7 +31,7 @@ void ip6_input(struct mbuf *m)
|
|||
}
|
||||
|
||||
DEBUG_CALL("ip6_input");
|
||||
DEBUG_ARG("m = %lx", (long)m);
|
||||
DEBUG_ARG("m = %p", m);
|
||||
DEBUG_ARG("m_len = %d", m->m_len);
|
||||
|
||||
if (m->m_len < sizeof(struct ip6)) {
|
||||
|
|
|
@ -19,8 +19,8 @@ int ip6_output(struct socket *so, struct mbuf *m, int fast)
|
|||
struct ip6 *ip = mtod(m, struct ip6 *);
|
||||
|
||||
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 */
|
||||
ip->ip_v = IP6VERSION;
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
#include "slirp.h"
|
||||
#include "ip_icmp.h"
|
||||
|
||||
#ifndef WITH_ICMP_ERROR_MSG
|
||||
#define WITH_ICMP_ERROR_MSG 0
|
||||
#endif
|
||||
|
||||
/* The message sent when emulating PING */
|
||||
/* 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";
|
||||
|
@ -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,
|
||||
(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_detach(so);
|
||||
}
|
||||
|
@ -165,8 +169,8 @@ icmp_input(struct mbuf *m, int hlen)
|
|||
return;
|
||||
}
|
||||
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);
|
||||
m_free(m);
|
||||
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,
|
||||
(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));
|
||||
udp_detach(so);
|
||||
}
|
||||
|
@ -253,13 +257,12 @@ icmp_send_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
|
|||
/* check msrc */
|
||||
if(!msrc) goto end_error;
|
||||
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(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 */
|
||||
|
||||
/* 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_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;
|
||||
char *cpnt;
|
||||
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);
|
||||
m->m_len+=message_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
icp->icmp_cksum = 0;
|
||||
icp->icmp_cksum = cksum(m, m->m_len);
|
||||
|
@ -457,8 +458,8 @@ void icmp_receive(struct socket *so)
|
|||
} else {
|
||||
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));
|
||||
} else {
|
||||
icmp_reflect(so->so_m);
|
||||
|
|
200
slirp/ip_input.c
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
|
||||
* level protocol in the kernel.
|
||||
|
|
|
@ -5,8 +5,20 @@
|
|||
|
||||
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,
|
||||
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,
|
||||
struct in_addr vdhcp_start, struct in_addr vnameserver,
|
||||
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_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);
|
||||
|
||||
/* 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,
|
||||
struct in_addr host_addr, int host_port,
|
||||
struct in_addr guest_addr, int guest_port);
|
||||
int slirp_remove_hostfwd(Slirp *slirp, int is_udp,
|
||||
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);
|
||||
|
||||
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,
|
||||
int guest_port, const uint8_t *buf, int size);
|
||||
|
|
33
slirp/main.h
33
slirp/main.h
|
@ -8,42 +8,9 @@
|
|||
#ifndef 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 struct in_addr loopback_addr;
|
||||
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);
|
||||
ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags);
|
||||
|
|
|
@ -232,7 +232,7 @@ dtom(Slirp *slirp, void *dat)
|
|||
}
|
||||
}
|
||||
|
||||
DEBUG_ERROR((dfd, "dtom failed"));
|
||||
DEBUG_ERROR("dtom failed");
|
||||
|
||||
return (struct mbuf *)0;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,6 @@
|
|||
* How much free room there is
|
||||
*/
|
||||
#define M_FREEROOM(m) (M_ROOM(m) - (m)->m_len)
|
||||
#define M_TRAILINGSPACE M_FREEROOM
|
||||
|
||||
struct mbuf {
|
||||
/* XXX should union some of these! */
|
||||
|
|
298
slirp/misc.c
298
slirp/misc.c
|
@ -8,14 +8,9 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "slirp.h"
|
||||
#include "libslirp.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR;
|
||||
#endif
|
||||
|
||||
inline void
|
||||
insque(void *a, void *b)
|
||||
{
|
||||
|
@ -37,189 +32,135 @@ remque(void *a)
|
|||
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 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;
|
||||
*ex_ptr = g_new(struct ex_list, 1);
|
||||
*ex_ptr = g_new0(struct gfwd_list, 1);
|
||||
(*ex_ptr)->ex_fport = port;
|
||||
(*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;
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
do {
|
||||
sv[0] = accept(s, (struct sockaddr *)&addr, &addrlen);
|
||||
} while (sv[0] < 0 && errno == EINTR);
|
||||
if (sv[0] < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
closesocket(s);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
g_critical("slirp_socketpair(): %s", strerror(errno));
|
||||
if (s >= 0) {
|
||||
closesocket(s);
|
||||
}
|
||||
if (sv[1] >= 0) {
|
||||
closesocket(sv[1]);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#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)
|
||||
static void
|
||||
fork_exec_child_setup(gpointer data)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
switch(pid) {
|
||||
case -1:
|
||||
error_report("Error: fork failed: %s", strerror(errno));
|
||||
closesocket(cs);
|
||||
close(s);
|
||||
return 0;
|
||||
|
||||
case 0:
|
||||
setsid();
|
||||
|
||||
/* Set the DISPLAY */
|
||||
close(s);
|
||||
dup2(cs, 0);
|
||||
dup2(cs, 1);
|
||||
dup2(cs, 2);
|
||||
for (s = getdtablesize() - 1; s >= 3; s--)
|
||||
close(s);
|
||||
|
||||
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);
|
||||
|
||||
argv[i] = NULL;
|
||||
execvp(argv[0], (char **)argv);
|
||||
|
||||
/* 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);
|
||||
|
||||
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);
|
||||
|
||||
/* Append the telnet options now */
|
||||
if (so->so_m != NULL && do_pty == 1) {
|
||||
sbappend(so, so->so_m);
|
||||
so->so_m = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#ifndef _WIN32
|
||||
setsid();
|
||||
#endif
|
||||
}
|
||||
|
||||
void slirp_connection_info(Slirp *slirp, Monitor *mon)
|
||||
int
|
||||
fork_exec(struct socket *so, const char *ex)
|
||||
{
|
||||
GError *err = NULL;
|
||||
char **argv;
|
||||
int opt, sp[2];
|
||||
|
||||
DEBUG_CALL("fork_exec");
|
||||
DEBUG_ARG("so = %p", so);
|
||||
DEBUG_ARG("ex = %p", ex);
|
||||
|
||||
if (slirp_socketpair_with_oob(sp) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
char *slirp_connection_info(Slirp *slirp)
|
||||
{
|
||||
GString *str = g_string_new(NULL);
|
||||
const char * const tcpstates[] = {
|
||||
[TCPS_CLOSED] = "CLOSED",
|
||||
[TCPS_LISTEN] = "LISTEN",
|
||||
|
@ -241,8 +182,9 @@ void slirp_connection_info(Slirp *slirp, Monitor *mon)
|
|||
const char *state;
|
||||
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) {
|
||||
if (so->so_state & SS_HOSTFWD) {
|
||||
|
@ -264,10 +206,10 @@ void slirp_connection_info(Slirp *slirp, Monitor *mon)
|
|||
dst_port = so->so_fport;
|
||||
}
|
||||
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) : "*",
|
||||
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),
|
||||
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_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) : "*",
|
||||
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),
|
||||
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);
|
||||
src.sin_addr = so->so_laddr;
|
||||
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) : "*");
|
||||
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);
|
||||
}
|
||||
|
||||
return g_string_free(str, FALSE);
|
||||
}
|
||||
|
|
13
slirp/misc.h
13
slirp/misc.h
|
@ -8,12 +8,12 @@
|
|||
#ifndef 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 */
|
||||
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
|
||||
|
@ -26,7 +26,6 @@ struct ex_list {
|
|||
#define EMU_REALAUDIO 0x5
|
||||
#define EMU_RLOGIN 0x6
|
||||
#define EMU_IDENT 0x7
|
||||
#define EMU_RSH 0x8
|
||||
|
||||
#define EMU_NOCONNECT 0x10 /* Don't connect */
|
||||
|
||||
|
@ -52,7 +51,7 @@ struct slirp_quehead {
|
|||
|
||||
void slirp_insque(void *, 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
|
||||
|
|
|
@ -128,7 +128,7 @@ void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
|
|||
memset(reh->h_source, 0xff, ETH_ALEN);
|
||||
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) {
|
||||
handler = &ncsi_rsp_handlers[i];
|
||||
break;
|
||||
|
@ -163,5 +163,5 @@ void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
|
|||
*pchecksum = htonl(checksum);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -10,18 +10,17 @@
|
|||
void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr,
|
||||
uint8_t ethaddr[ETH_ALEN])
|
||||
{
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
NdpTable *ndp_table = &slirp->ndp_table;
|
||||
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);
|
||||
|
||||
DEBUG_CALL("ndp_table_add");
|
||||
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)) {
|
||||
/* 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,
|
||||
uint8_t out_ethaddr[ETH_ALEN])
|
||||
{
|
||||
char addrstr[INET6_ADDRSTRLEN];
|
||||
NdpTable *ndp_table = &slirp->ndp_table;
|
||||
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);
|
||||
|
||||
DEBUG_CALL("ndp_table_search");
|
||||
DEBUG_ARG("ip = %s", addrstr);
|
||||
#endif
|
||||
|
||||
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[4] = ip_addr.s6_addr[14];
|
||||
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;
|
||||
}
|
||||
|
||||
for (i = 0; i < NDP_TABLE_SIZE; i++) {
|
||||
if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#ifndef SBUF_H
|
||||
#define SBUF_H
|
||||
|
||||
#define sbflush(sb) sbdrop((sb),(sb)->sb_cc)
|
||||
#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)
|
||||
|
||||
struct sbuf {
|
||||
|
|
177
slirp/slirp.c
177
slirp/slirp.c
|
@ -35,6 +35,11 @@
|
|||
#include <net/if.h>
|
||||
#endif
|
||||
|
||||
int slirp_debug;
|
||||
|
||||
/* Define to 1 if you want KEEPALIVE timers */
|
||||
bool slirp_do_keepalive;
|
||||
|
||||
/* host loopback address */
|
||||
struct in_addr loopback_addr;
|
||||
/* 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)
|
||||
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) {
|
||||
if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
|
||||
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;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
fprintf(stderr, ", ");
|
||||
#endif
|
||||
|
||||
if (++found > 3) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "(more)");
|
||||
#endif
|
||||
DEBUG_MISC(" (more)");
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
} else if (slirp_debug & DBG_MISC) {
|
||||
char s[INET6_ADDRSTRLEN];
|
||||
const char *res = inet_ntop(af, tmp_addr, s, sizeof(s));
|
||||
if (!res) {
|
||||
res = "(string conversion error)";
|
||||
res = " (string conversion error)";
|
||||
}
|
||||
fprintf(stderr, "%s", res);
|
||||
DEBUG_MISC(" %s", res);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
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 int initialized;
|
||||
const char *debug;
|
||||
#ifdef _WIN32
|
||||
WSADATA Data;
|
||||
#endif
|
||||
|
@ -268,6 +264,18 @@ static void slirp_init_once(void)
|
|||
|
||||
loopback_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
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);
|
||||
|
@ -287,12 +295,15 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
|
|||
const char *tftp_path, const char *bootfile,
|
||||
struct in_addr vdhcp_start, struct in_addr vnameserver,
|
||||
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_init_once();
|
||||
|
||||
slirp->cb = callbacks;
|
||||
slirp->grand = g_rand_new();
|
||||
slirp->restricted = restricted;
|
||||
|
||||
|
@ -339,6 +350,14 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
|
|||
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
Slirp *slirp;
|
||||
Slirp *slirp = QTAILQ_FIRST(&slirp_instances);
|
||||
struct socket *so, *so_next;
|
||||
int ret;
|
||||
|
||||
if (QTAILQ_EMPTY(&slirp_instances)) {
|
||||
if (!slirp) {
|
||||
return;
|
||||
}
|
||||
|
||||
curtime = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
||||
curtime = slirp->cb->clock_get_ns() / SCALE_MS;
|
||||
|
||||
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 slirp_arphdr *rah = (struct slirp_arphdr *)(arp_reply + ETH_HLEN);
|
||||
int ar_op;
|
||||
struct ex_list *ex_ptr;
|
||||
struct gfwd_list *ex_ptr;
|
||||
|
||||
if (!slirp->in_enabled) {
|
||||
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 ||
|
||||
ah->ar_tip == slirp->vhost_addr.s_addr)
|
||||
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)
|
||||
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;
|
||||
memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
|
||||
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;
|
||||
case ARPOP_REPLY:
|
||||
|
@ -932,11 +910,11 @@ static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
|
|||
/* target IP */
|
||||
rah->ar_tip = iph->ip_dst.s_addr;
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
} else {
|
||||
|
@ -962,8 +940,7 @@ static int if_encap6(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
|
|||
if (!ifm->resolution_requested) {
|
||||
ndp_send_ns(slirp, ip6h->ip_dst);
|
||||
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;
|
||||
} else {
|
||||
|
@ -1011,14 +988,14 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
|
|||
}
|
||||
|
||||
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);
|
||||
slirp_output(slirp->opaque, buf, ifm->m_len + ETH_HLEN);
|
||||
slirp->cb->output(slirp->opaque, buf, ifm->m_len + ETH_HLEN);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1065,9 +1042,11 @@ int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
|
|||
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) {
|
||||
guest_addr->s_addr = slirp->vnetwork_addr.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 ||
|
||||
guest_addr->s_addr == slirp->vhost_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 add_exec(&slirp->exec_list, do_pty, (char *)args, *guest_addr,
|
||||
|
||||
return add_exec(&slirp->guestfwd_list, chardev, cmdline, *guest_addr,
|
||||
htons(guest_port));
|
||||
}
|
||||
|
||||
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
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
@ -1240,8 +1237,8 @@ static int sbuf_tmp_post_load(void *opaque, int version)
|
|||
}
|
||||
if (tmp->woff >= 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;
|
||||
}
|
||||
|
||||
|
@ -1349,7 +1346,7 @@ static int ss_family_post_load(void *opaque, int version_id)
|
|||
tss->parent->ss.ss_family = AF_INET6;
|
||||
break;
|
||||
default:
|
||||
error_report("invalid ss_family type %x", tss->portable_family);
|
||||
g_critical("invalid ss_family type %x", tss->portable_family);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1449,10 +1446,10 @@ static const VMStateDescription vmstate_slirp = {
|
|||
static void slirp_state_save(QEMUFile *f, void *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;
|
||||
so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
|
||||
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)
|
||||
{
|
||||
Slirp *slirp = opaque;
|
||||
struct ex_list *ex_ptr;
|
||||
struct gfwd_list *ex_ptr;
|
||||
|
||||
while (qemu_get_byte(f)) {
|
||||
int ret;
|
||||
|
@ -1486,8 +1483,8 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
|
|||
slirp->vnetwork_addr.s_addr) {
|
||||
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_fport == ex_ptr->ex_fport) {
|
||||
break;
|
||||
|
@ -1495,8 +1492,6 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
|
|||
}
|
||||
if (!ex_ptr)
|
||||
return -EINVAL;
|
||||
|
||||
so->extra = (void *)ex_ptr->ex_exec;
|
||||
}
|
||||
|
||||
return vmstate_load_state(f, &vmstate_slirp, slirp, version_id);
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#ifndef SLIRP_H
|
||||
#define SLIRP_H
|
||||
|
||||
#include "slirp_config.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
typedef char *caddr_t;
|
||||
|
@ -19,10 +17,6 @@ typedef char *caddr_t;
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_BITYPES_H
|
||||
# include <sys/bitypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
@ -32,29 +26,15 @@ typedef char *caddr_t;
|
|||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifndef NO_UNIX_SOCKETS
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SIGNAL_H
|
||||
# include <sys/signal.h>
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SYS_IOCTL_H)
|
||||
#ifndef _WIN32
|
||||
# include <sys/ioctl.h>
|
||||
#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>
|
||||
#endif
|
||||
|
||||
|
@ -64,11 +44,6 @@ typedef char *caddr_t;
|
|||
#define remque slirp_remque
|
||||
#define quehead slirp_quehead
|
||||
|
||||
#ifdef HAVE_SYS_STROPTS_H
|
||||
#include <sys/stropts.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include "qemu/queue.h"
|
||||
|
@ -172,7 +147,7 @@ struct Slirp {
|
|||
char client_hostname[33];
|
||||
|
||||
int restricted;
|
||||
struct ex_list *exec_list;
|
||||
struct gfwd_list *guestfwd_list;
|
||||
|
||||
/* mbuf states */
|
||||
struct quehead m_freelist;
|
||||
|
@ -220,17 +195,15 @@ struct Slirp {
|
|||
GRand *grand;
|
||||
QEMUTimer *ra_timer;
|
||||
|
||||
const SlirpCb *cb;
|
||||
void *opaque;
|
||||
};
|
||||
|
||||
extern Slirp *slirp_instance;
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif
|
||||
|
||||
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 */
|
||||
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>
|
||||
#endif
|
||||
|
||||
#define SO_OPTIONS DO_KEEPALIVE
|
||||
|
||||
extern bool slirp_do_keepalive;
|
||||
|
||||
#define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL)
|
||||
|
||||
/* dnssearch.c */
|
||||
|
|
|
@ -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
|
|
@ -89,10 +89,6 @@ sofree(struct socket *so)
|
|||
soqfree(so, &slirp->if_fastq);
|
||||
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) {
|
||||
slirp->tcp_last_so = &slirp->tcb;
|
||||
} else if (so == slirp->udp_last_so) {
|
||||
|
@ -191,12 +187,7 @@ soread(struct socket *so)
|
|||
*/
|
||||
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);
|
||||
#endif
|
||||
if (nn <= 0) {
|
||||
if (nn < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
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);
|
||||
|
||||
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
|
||||
* We read again if n = 2 (ie, there's another part of the buffer)
|
||||
|
@ -247,8 +238,7 @@ soread(struct socket *so)
|
|||
nn += ret;
|
||||
}
|
||||
|
||||
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
|
||||
#endif
|
||||
DEBUG_MISC(" ... read nn = %d bytes", nn);
|
||||
|
||||
/* Update fields */
|
||||
sb->sb_cc += nn;
|
||||
|
@ -296,7 +286,7 @@ err:
|
|||
|
||||
sofcantrcvmore(so);
|
||||
tcp_sockclosed(sototcpcb(so));
|
||||
fprintf(stderr, "soreadbuf buffer to small");
|
||||
g_critical("soreadbuf buffer too small");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -381,7 +371,7 @@ sosendoob(struct socket *so)
|
|||
n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
|
||||
#ifdef DEBUG
|
||||
if (n != len) {
|
||||
DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
|
||||
DEBUG_ERROR("Didn't send all data urgently XXXXX");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -390,7 +380,7 @@ sosendoob(struct socket *so)
|
|||
return 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_rptr += n;
|
||||
|
@ -456,13 +446,7 @@ sowrite(struct socket *so)
|
|||
}
|
||||
/* 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);
|
||||
#endif
|
||||
/* This should never happen, but people tell me it does *shrug* */
|
||||
if (nn < 0 && (errno == EAGAIN || errno == EINTR))
|
||||
return 0;
|
||||
|
@ -471,15 +455,13 @@ sowrite(struct socket *so)
|
|||
goto err_disconnected;
|
||||
}
|
||||
|
||||
#ifndef HAVE_READV
|
||||
if (n == 2 && nn == iov[0].iov_len) {
|
||||
int ret;
|
||||
ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0);
|
||||
if (ret > 0)
|
||||
nn += ret;
|
||||
}
|
||||
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
|
||||
#endif
|
||||
DEBUG_MISC(" ... wrote nn = %d bytes", nn);
|
||||
|
||||
/* Update sbuf */
|
||||
sb->sb_cc -= nn;
|
||||
|
@ -497,8 +479,8 @@ sowrite(struct socket *so)
|
|||
return nn;
|
||||
|
||||
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);
|
||||
tcp_sockclosed(sototcpcb(so));
|
||||
return -1;
|
||||
|
@ -531,8 +513,8 @@ sorecvfrom(struct socket *so)
|
|||
if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
|
||||
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));
|
||||
} else {
|
||||
icmp_reflect(so->so_m);
|
||||
|
@ -583,8 +565,8 @@ sorecvfrom(struct socket *so)
|
|||
|
||||
m->m_len = recvfrom(so->s, m->m_data, len, 0,
|
||||
(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) {
|
||||
/* Report error as ICMP */
|
||||
switch (so->so_lfamily) {
|
||||
|
@ -598,7 +580,7 @@ sorecvfrom(struct socket *so)
|
|||
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));
|
||||
break;
|
||||
case AF_INET6:
|
||||
|
@ -610,7 +592,7 @@ sorecvfrom(struct socket *so)
|
|||
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);
|
||||
break;
|
||||
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;
|
||||
|
||||
case AF_INET6:
|
||||
|
|
|
@ -67,7 +67,7 @@ struct socket {
|
|||
|
||||
struct sbuf so_rcv; /* Receive buffer */
|
||||
struct sbuf so_snd; /* Send buffer */
|
||||
void * extra; /* Extra pointer */
|
||||
void * chardev;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#ifndef TCP_H
|
||||
#define TCP_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef uint32_t tcp_seq;
|
||||
|
||||
#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */
|
||||
|
@ -51,7 +53,7 @@ struct tcphdr {
|
|||
uint16_t th_dport; /* destination port */
|
||||
tcp_seq th_seq; /* sequence 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 */
|
||||
th_x2:4; /* (unused) */
|
||||
#else
|
||||
|
|
|
@ -60,27 +60,6 @@
|
|||
* Set DELACK for segments received in order, but ack immediately
|
||||
* 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) { \
|
||||
if ((ti)->ti_seq == (tp)->rcv_nxt && \
|
||||
tcpfrag_list_empty(tp) && \
|
||||
|
@ -97,7 +76,7 @@
|
|||
tp->t_flags |= TF_ACKNOW; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
static void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt,
|
||||
struct tcpiphdr *ti);
|
||||
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_in *lhost4, *fhost4;
|
||||
struct sockaddr_in6 *lhost6, *fhost6;
|
||||
struct ex_list *ex_ptr;
|
||||
struct gfwd_list *ex_ptr;
|
||||
Slirp *slirp;
|
||||
|
||||
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
|
||||
|
@ -415,7 +394,7 @@ findso:
|
|||
* for non-hostfwd connections. These should be dropped, unless it
|
||||
* 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 &&
|
||||
ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) {
|
||||
break;
|
||||
|
@ -481,7 +460,7 @@ findso:
|
|||
* Reset idle time and keep-alive timer.
|
||||
*/
|
||||
tp->t_idle = 0;
|
||||
if (SO_OPTIONS)
|
||||
if (slirp_do_keepalive)
|
||||
tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
|
||||
else
|
||||
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
|
||||
|
@ -637,7 +616,7 @@ findso:
|
|||
if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr &&
|
||||
so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) {
|
||||
/* 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) {
|
||||
if(ex_ptr->ex_fport == so->so_fport &&
|
||||
so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
|
||||
|
@ -662,8 +641,7 @@ findso:
|
|||
(errno != EINPROGRESS) && (errno != EWOULDBLOCK)
|
||||
) {
|
||||
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) {
|
||||
/* ACK the SYN, send RST to refuse the connection */
|
||||
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 (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
|
||||
* 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;
|
||||
|
||||
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) {
|
||||
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
|
||||
* and update averages and current timeout.
|
||||
|
@ -1611,7 +1549,7 @@ tcp_mss(struct tcpcb *tp, u_int offer)
|
|||
(mss - (TCP_RCVSPACE % mss)) :
|
||||
0));
|
||||
|
||||
DEBUG_MISC((dfd, " returning mss = %d\n", mss));
|
||||
DEBUG_MISC(" returning mss = %d", mss);
|
||||
|
||||
return mss;
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ again:
|
|||
|
||||
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.
|
||||
|
|
|
@ -420,7 +420,7 @@ int tcp_fconnect(struct socket *so, unsigned short af)
|
|||
qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
|
||||
|
||||
addr = so->fhost.ss;
|
||||
DEBUG_CALL(" connect()ing")
|
||||
DEBUG_CALL(" connect()ing");
|
||||
sotranslate_out(so, &addr);
|
||||
|
||||
/* 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, 80, IPTOS_THROUGHPUT, 0}, /* WWW */
|
||||
{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, 543, IPTOS_LOWDELAY, 0}, /* klogin */
|
||||
{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);
|
||||
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);
|
||||
so_rcv->sb_wptr += m->m_len;
|
||||
so_rcv->sb_rptr += m->m_len;
|
||||
|
@ -950,25 +954,23 @@ int tcp_ctl(struct socket *so)
|
|||
{
|
||||
Slirp *slirp = so->slirp;
|
||||
struct sbuf *sb = &so->so_snd;
|
||||
struct ex_list *ex_ptr;
|
||||
int do_pty;
|
||||
struct gfwd_list *ex_ptr;
|
||||
|
||||
DEBUG_CALL("tcp_ctl");
|
||||
DEBUG_ARG("so = %p", so);
|
||||
|
||||
if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
|
||||
/* 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 &&
|
||||
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->extra = (void *)ex_ptr->ex_exec;
|
||||
so->chardev = ex_ptr->ex_chardev;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -262,7 +262,7 @@ tcp_timers(register struct tcpcb *tp, int timer)
|
|||
if (tp->t_state < TCPS_ESTABLISHED)
|
||||
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)
|
||||
goto dropit;
|
||||
/*
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "slirp.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "trace.h"
|
||||
|
||||
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 tftp_t *tp;
|
||||
|
||||
trace_slirp_tftp_error(msg);
|
||||
m = m_get(spt->slirp);
|
||||
|
||||
if (!m) {
|
||||
|
@ -323,6 +325,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas,
|
|||
break;
|
||||
}
|
||||
}
|
||||
trace_slirp_tftp_rrq(req_fname);
|
||||
|
||||
/* check mode */
|
||||
if ((pktlen - k) < 6) {
|
||||
|
@ -356,7 +359,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas,
|
|||
return;
|
||||
}
|
||||
|
||||
while (k < pktlen && nb_options < ARRAY_SIZE(option_name)) {
|
||||
while (k < pktlen && nb_options < G_N_ELEMENTS(option_name)) {
|
||||
const char *key, *value;
|
||||
|
||||
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) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -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"
|
|
@ -172,8 +172,7 @@ udp_input(register struct mbuf *m, int iphlen)
|
|||
*/
|
||||
so = socreate(slirp);
|
||||
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);
|
||||
goto bad;
|
||||
}
|
||||
|
@ -209,7 +208,7 @@ udp_input(register struct mbuf *m, int iphlen)
|
|||
m->m_len += iphlen;
|
||||
m->m_data -= iphlen;
|
||||
*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,
|
||||
strerror(errno));
|
||||
goto bad;
|
||||
|
|
11
slirp/udp6.c
11
slirp/udp6.c
|
@ -20,7 +20,7 @@ void udp6_input(struct mbuf *m)
|
|||
struct sockaddr_in6 lhost;
|
||||
|
||||
DEBUG_CALL("udp6_input");
|
||||
DEBUG_ARG("m = %lx", (long)m);
|
||||
DEBUG_ARG("m = %p", m);
|
||||
|
||||
if (slirp->restricted) {
|
||||
goto bad;
|
||||
|
@ -92,8 +92,7 @@ void udp6_input(struct mbuf *m)
|
|||
/* If there's no socket for this packet, create one. */
|
||||
so = socreate(slirp);
|
||||
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);
|
||||
goto bad;
|
||||
}
|
||||
|
@ -119,7 +118,7 @@ void udp6_input(struct mbuf *m)
|
|||
m->m_len += iphlen;
|
||||
m->m_data -= iphlen;
|
||||
*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);
|
||||
goto bad;
|
||||
}
|
||||
|
@ -144,8 +143,8 @@ int udp6_output(struct socket *so, struct mbuf *m,
|
|||
struct udphdr *uh;
|
||||
|
||||
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 */
|
||||
m->m_data -= sizeof(struct udphdr);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "slirp/slirp.h"
|
||||
#include "slirp/libslirp.h"
|
||||
|
||||
void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue