Added support for using external slirp library instead of builtin one.

- Added configure option --enable-using-libslirp to turn on the search for the
  library. In config.h BX_HAVE_LIBSLIRP is set to 1 if found. The network Makefile
  is set up accordingly. If not enabled or not found, the builtin slirp code is used.
- Moved samba server code and host forwarding code to eth_slirp.cc.
- Modified builtin slirp API to reduce differences.
- NOTE: IPv6 support present in libslirp is not yet enabled (needs more testing).
- TODO: Update builtin slirp code based on libslirp 4.7.0 code.
This commit is contained in:
Volker Ruppert 2024-04-07 19:57:25 +02:00
parent e1d67d9ce0
commit 0ff2905998
8 changed files with 643 additions and 431 deletions

View File

@ -861,6 +861,8 @@ typedef Bit32u bx_phy_address;
#define BX_NETMOD_SLIRP 0
#define BX_NETMOD_SOCKET 0
#define BX_HAVE_LIBSLIRP 0
// Soundcard and gameport support
#define BX_SUPPORT_SB16 0
#define BX_SUPPORT_ES1370 0

134
bochs/configure vendored
View File

@ -911,6 +911,9 @@ CDROM_OBJS
DISPLAY_DLL_TARGETS
DISPLAY_EXTRA_OBJS
DISPLAY_OBJS
SLIRP_LINK_OPTS
SLIRP_OBJS2
SLIRP_OBJS
NETDEV_DLL_TARGETS
NETLOW_OBJS
NETDEV_OBJS
@ -1092,6 +1095,7 @@ enable_win32usbdbg
enable_ne2000
enable_pnic
enable_e1000
enable_using_libslirp
enable_raw_serial
enable_clgd54xx
enable_voodoo
@ -1836,6 +1840,7 @@ Optional Features:
--enable-ne2000 enable NE2000 support (no)
--enable-pnic enable PCI pseudo NIC support (no)
--enable-e1000 enable Intel(R) Gigabit Ethernet support (no)
--enable-using-libslirp enable using libslirp instead of builtin slirp (no)
--enable-raw-serial use raw serial port access (no - incomplete)
--enable-clgd54xx enable CLGD54XX emulation (no)
--enable-voodoo enable 3dfx Voodoo Graphics emulation (no)
@ -6170,7 +6175,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 6173 "configure"' > conftest.$ac_ext
echo '#line 6178 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@ -7656,11 +7661,11 @@ else $as_nop
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7659: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7664: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7663: \$? = $ac_status" >&5
echo "$as_me:7668: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
@ -7890,11 +7895,11 @@ else $as_nop
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7893: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7898: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7897: \$? = $ac_status" >&5
echo "$as_me:7902: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
@ -7958,11 +7963,11 @@ else $as_nop
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7961: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7966: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7965: \$? = $ac_status" >&5
echo "$as_me:7970: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@ -9753,7 +9758,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 9756 "configure"
#line 9761 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -9848,7 +9853,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 9851 "configure"
#line 9856 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -11966,11 +11971,11 @@ else $as_nop
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:11969: $lt_compile\"" >&5)
(eval echo "\"\$as_me:11974: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:11973: \$? = $ac_status" >&5
echo "$as_me:11978: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
@ -12034,11 +12039,11 @@ else $as_nop
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:12037: $lt_compile\"" >&5)
(eval echo "\"\$as_me:12042: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:12041: \$? = $ac_status" >&5
echo "$as_me:12046: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@ -13057,7 +13062,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 13060 "configure"
#line 13065 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -13152,7 +13157,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 13155 "configure"
#line 13160 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -13972,11 +13977,11 @@ else $as_nop
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:13975: $lt_compile\"" >&5)
(eval echo "\"\$as_me:13980: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:13979: \$? = $ac_status" >&5
echo "$as_me:13984: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
@ -14040,11 +14045,11 @@ else $as_nop
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:14043: $lt_compile\"" >&5)
(eval echo "\"\$as_me:14048: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:14047: \$? = $ac_status" >&5
echo "$as_me:14052: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@ -16008,11 +16013,11 @@ else $as_nop
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:16011: $lt_compile\"" >&5)
(eval echo "\"\$as_me:16016: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:16015: \$? = $ac_status" >&5
echo "$as_me:16020: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
@ -16242,11 +16247,11 @@ else $as_nop
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:16245: $lt_compile\"" >&5)
(eval echo "\"\$as_me:16250: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:16249: \$? = $ac_status" >&5
echo "$as_me:16254: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
@ -16310,11 +16315,11 @@ else $as_nop
-e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:16313: $lt_compile\"" >&5)
(eval echo "\"\$as_me:16318: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:16317: \$? = $ac_status" >&5
echo "$as_me:16322: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@ -18105,7 +18110,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 18108 "configure"
#line 18113 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -18200,7 +18205,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 18203 "configure"
#line 18208 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -19893,7 +19898,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 19896 "configure"
#line 19901 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -24855,28 +24860,68 @@ fi
NETLOW_OBJS=''
SLIRP_OBJS=''
SLIRP_OBJS2=''
SLIRP_LINK_OPTS=''
if test "$networking" = yes; then
NETLOW_OBJS='eth_null.o eth_vnet.o'
ethernet_modules='null vnet'
can_compile_slirp=0
case "$target" in
*-cygwin* | *-mingw32* | *-msys)
can_compile_slirp=1
DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -liphlpapi"
;;
*-pc-windows* | *-pc-winnt*)
can_compile_slirp=1
DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS iphlpapi.lib"
;;
*)
ac_fn_c_check_header_compile "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "$ac_includes_default"
if test "x$ac_cv_header_netinet_in_h" = xyes
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for slirp networking support" >&5
printf %s "checking for slirp networking support... " >&6; }
# Check whether --enable-using-libslirp was given.
if test ${enable_using_libslirp+y}
then :
can_compile_slirp=1
enableval=$enable_using_libslirp; if test "$enableval" = yes; then
if test "x$PKG_CONFIG" != x; then
$PKG_CONFIG --exists slirp
if test x$? = x0; then
can_compile_slirp=1
if test "$bx_plugins" = 1; then
SLIRP_LINK_OPTS="`$PKG_CONFIG --libs slirp`"
else
DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS `$PKG_CONFIG --libs slirp`"
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: libslirp" >&5
printf "%s\n" "libslirp" >&6; }
printf "%s\n" "#define BX_HAVE_LIBSLIRP 1" >>confdefs.h
fi
fi
fi
fi
;;
esac
if test $can_compile_slirp = 0; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: builtin" >&5
printf "%s\n" "builtin" >&6; }
case "$target" in
*-cygwin* | *-mingw32* | *-msys)
can_compile_slirp=1
DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -liphlpapi"
SLIRP_OBJS='$(SLIRP_OBJS)'
;;
*-pc-windows* | *-pc-winnt*)
can_compile_slirp=1
DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS iphlpapi.lib"
SLIRP_OBJS='$(SLIRP_OBJS)'
;;
*)
ac_fn_c_check_header_compile "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "$ac_includes_default"
if test "x$ac_cv_header_netinet_in_h" = xyes
then :
can_compile_slirp=1
fi
if test $can_compile_slirp = 1; then
if test "$bx_plugins" = 1; then
SLIRP_OBJS2='$(SLIRP_OBJS:.o=.lo)'
else
SLIRP_OBJS='$(SLIRP_OBJS)'
fi
fi
;;
esac
fi
if test $can_compile_slirp = 1; then
NETLOW_OBJS="$NETLOW_OBJS eth_slirp.o"
ethernet_modules="$ethernet_modules slirp"
@ -25010,6 +25055,9 @@ fi
if test "$bx_plugins" = 0; then
case $target in
*-pc-windows*)

View File

@ -1759,23 +1759,56 @@ AC_ARG_ENABLE(e1000,
)
NETLOW_OBJS=''
SLIRP_OBJS=''
SLIRP_OBJS2=''
SLIRP_LINK_OPTS=''
if test "$networking" = yes; then
NETLOW_OBJS='eth_null.o eth_vnet.o'
ethernet_modules='null vnet'
can_compile_slirp=0
case "$target" in
*-cygwin* | *-mingw32* | *-msys)
can_compile_slirp=1
DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -liphlpapi"
;;
*-pc-windows* | *-pc-winnt*)
can_compile_slirp=1
DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS iphlpapi.lib"
;;
*)
AC_CHECK_HEADER([netinet/in.h], [ can_compile_slirp=1 ], [])
;;
esac
AC_MSG_CHECKING(for slirp networking support)
AC_ARG_ENABLE(using-libslirp,
AS_HELP_STRING([--enable-using-libslirp], [enable using libslirp instead of builtin slirp (no)]),
[if test "$enableval" = yes; then
if test "x$PKG_CONFIG" != x; then
$PKG_CONFIG --exists slirp
if test x$? = x0; then
can_compile_slirp=1
if test "$bx_plugins" = 1; then
SLIRP_LINK_OPTS="`$PKG_CONFIG --libs slirp`"
else
DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS `$PKG_CONFIG --libs slirp`"
fi
AC_MSG_RESULT(libslirp)
AC_DEFINE(BX_HAVE_LIBSLIRP, 1)
fi
fi
fi], [])
if test $can_compile_slirp = 0; then
AC_MSG_RESULT(builtin)
case "$target" in
*-cygwin* | *-mingw32* | *-msys)
can_compile_slirp=1
DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -liphlpapi"
SLIRP_OBJS='$(SLIRP_OBJS)'
;;
*-pc-windows* | *-pc-winnt*)
can_compile_slirp=1
DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS iphlpapi.lib"
SLIRP_OBJS='$(SLIRP_OBJS)'
;;
*)
AC_CHECK_HEADER([netinet/in.h],[can_compile_slirp=1])
if test $can_compile_slirp = 1; then
if test "$bx_plugins" = 1; then
SLIRP_OBJS2='$(SLIRP_OBJS:.o=.lo)'
else
SLIRP_OBJS='$(SLIRP_OBJS)'
fi
fi
;;
esac
fi
if test $can_compile_slirp = 1; then
NETLOW_OBJS="$NETLOW_OBJS eth_slirp.o"
ethernet_modules="$ethernet_modules slirp"
@ -1864,6 +1897,9 @@ fi
AC_SUBST(NETDEV_OBJS)
AC_SUBST(NETLOW_OBJS)
AC_SUBST(NETDEV_DLL_TARGETS)
AC_SUBST(SLIRP_OBJS)
AC_SUBST(SLIRP_OBJS2)
AC_SUBST(SLIRP_LINK_OPTS)
dnl // serial mode 'socket' needs ws2_32.dll in non-plugin mode

View File

@ -1,4 +1,4 @@
# Copyright (C) 2012-2021 The Bochs Project
# Copyright (C) 2012-2024 The Bochs Project
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@ -87,8 +87,8 @@ OBJS_THAT_CAN_BE_PLUGINS = \
$(NETLOW_OBJS)
OBJS_THAT_SUPPORT_OTHER_PLUGINS = \
netutil.o \
$(SLIRP_OBJS)
@SLIRP_OBJS@ \
netutil.o
NONPLUGIN_OBJS = @IODEV_EXT_NON_PLUGIN_OBJS@
PLUGIN_OBJS = @IODEV_EXT_PLUGIN_OBJS@
@ -120,8 +120,8 @@ libbx_%.la: %.lo
$(LIBTOOL) --mode=link --tag CXX $(CXX) $(LDFLAGS) -module $< -o $@ -rpath $(PLUGIN_PATH)
# special link rules for plugins that require more than one object file
libbx_eth_slirp.la: eth_slirp.lo $(SLIRP_OBJS:.o=.lo)
$(LIBTOOL) --mode=link --tag CXX $(CXX) $(LDFLAGS) -module eth_slirp.lo $(SLIRP_OBJS:.o=.lo) -o libbx_eth_slirp.la -rpath $(PLUGIN_PATH)
libbx_eth_slirp.la: eth_slirp.lo @SLIRP_OBJS2@
$(LIBTOOL) --mode=link --tag CXX $(CXX) $(LDFLAGS) -module eth_slirp.lo @SLIRP_OBJS2@ -o libbx_eth_slirp.la -rpath $(PLUGIN_PATH) @SLIRP_LINK_OPTS@
libbx_eth_vnet.la: eth_vnet.lo netutil.lo
$(LIBTOOL) --mode=link --tag CXX $(CXX) $(LDFLAGS) -module eth_vnet.lo netutil.lo -o libbx_eth_vnet.la -rpath $(PLUGIN_PATH)
@ -134,8 +134,8 @@ bx_%.dll: %.o
bx_eth_null.dll: eth_null.o
@LINK_DLL@ eth_null.o $(WIN32_DLL_IMPORT_LIBRARY)
bx_eth_slirp.dll: eth_slirp.o $(SLIRP_OBJS)
@LINK_DLL@ eth_slirp.o $(SLIRP_OBJS) $(WIN32_DLL_IMPORT_LIBRARY) $(NETMOD_LINK_OPTS@LINK_VAR@)
bx_eth_slirp.dll: eth_slirp.o @SLIRP_OBJS@
@LINK_DLL@ eth_slirp.o @SLIRP_OBJS@ $(WIN32_DLL_IMPORT_LIBRARY) $(NETMOD_LINK_OPTS@LINK_VAR@)
bx_eth_socket.dll: eth_socket.o
@LINK_DLL@ eth_socket.o $(WIN32_DLL_IMPORT_LIBRARY) $(NETMOD_LINK_OPTS@LINK_VAR@)

View File

@ -1,8 +1,6 @@
/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2014-2021 The Bochs Project
// Copyright (C) 2014-2024 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -35,8 +33,13 @@
#if BX_NETWORKING && BX_NETMOD_SLIRP
#if BX_HAVE_LIBSLIRP
#include <slirp/libslirp.h>
#include <signal.h>
#else
#include "slirp/slirp.h"
#include "slirp/libslirp.h"
#endif
static unsigned int bx_slirp_instances = 0;
@ -60,13 +63,6 @@ static int rx_timer_index = BX_NULL_TIMER_HANDLE;
fd_set rfds, wfds, xfds;
int nfds;
extern int slirp_hostfwd(Slirp *s, const char *redir_str, int legacy_format);
#ifndef WIN32
extern int slirp_smb(Slirp *s, char *smb_tmpdir, const char *exported_dir,
struct in_addr vserver_addr);
void slirp_smb_cleanup(Slirp *s, char *smb_tmpdir);
#endif
class bx_slirp_pktmover_c : public eth_pktmover_c {
public:
bx_slirp_pktmover_c(const char *netif, const char *macaddr,
@ -80,9 +76,7 @@ private:
Slirp *slirp;
unsigned netdev_speed;
int restricted;
struct in_addr net, mask, host, dhcp, dns;
char *bootfile, *hostname, **dnssearch;
SlirpConfig config;
char *hostfwd[MAX_HOSTFWD];
int n_hostfwd;
#ifndef WIN32
@ -95,6 +89,14 @@ private:
bool parse_slirp_conf(const char *conf);
static void rx_timer_handler(void *);
void rx_timer(void);
#ifndef WIN32
int slirp_smb(Slirp *s, char *smb_tmpdir, const char *exported_dir,
struct in_addr vserver_addr);
void slirp_smb_cleanup(Slirp *s, char *smb_tmpdir);
#endif
int slirp_hostfwd(Slirp *s, const char *redir_str, int legacy_format);
};
class bx_slirp_locator_c : public eth_locator_c {
@ -109,6 +111,158 @@ protected:
} bx_slirp_match;
#if BX_HAVE_LIBSLIRP
static slirp_ssize_t send_packet(const void *buf, size_t len, void *opaque);
static void guest_error(const char *msg, void *opaque)
{
fprintf(stderr, "guest_error\n");
}
static int64_t clock_get_ns(void *opaque)
{
return bx_pc_system.time_usec() * 1000;
}
static int npoll;
static void register_poll_fd(int fd, void *opaque)
{
npoll++;
}
static void unregister_poll_fd(int fd, void *opaque)
{
npoll--;
}
static void notify(void *opaque)
{
// Nothing here yet
}
static struct SlirpCb callbacks = {
.send_packet = send_packet,
.guest_error = guest_error,
.clock_get_ns = clock_get_ns,
.register_poll_fd = register_poll_fd,
.unregister_poll_fd = unregister_poll_fd,
.notify = notify,
};
#endif
bx_slirp_pktmover_c::bx_slirp_pktmover_c(const char *netif,
const char *macaddr,
eth_rx_handler_t rxh,
eth_rx_status_t rxstat,
logfunctions *netdev,
const char *script)
{
#if !BX_HAVE_LIBSLIRP
logfunctions *slirplog;
char prefix[10];
#endif
slirp = NULL;
pktlog_fn = NULL;
n_hostfwd = 0;
/* default settings according to historic slirp */
memset(&config, 0, sizeof(config));
#if BX_HAVE_LIBSLIRP
config.version = 4;
config.in_enabled = true;
config.disable_host_loopback = false;
config.enable_emu = false;
config.disable_dns = false;
config.tftp_server_name = "tftp";
#endif
config.restricted = false;
config.vnetwork.s_addr = htonl(0x0a000200); /* 10.0.2.0 */
config.vnetmask.s_addr = htonl(0xffffff00); /* 255.255.255.0 */
config.vhost.s_addr = htonl(0x0a000202); /* 10.0.2.2 */
config.vdhcp_start.s_addr = htonl(0x0a00020f); /* 10.0.2.15 */
config.vnameserver.s_addr = htonl(0x0a000203); /* 10.0.2.3 */
config.tftp_path = netif;
#ifndef WIN32
smb_export = NULL;
smb_tmpdir = NULL;
smb_srv.s_addr = 0;
#endif
this->netdev = netdev;
#if BX_HAVE_LIBSLIRP
BX_INFO(("slirp network driver (libslirp version %s)", slirp_version_string()));
#else
if (sizeof(struct arphdr) != 28) {
BX_FATAL(("system error: invalid ARP header structure size"));
}
BX_INFO(("slirp network driver"));
#endif
this->rxh = rxh;
this->rxstat = rxstat;
Bit32u status = this->rxstat(this->netdev) & BX_NETDEV_SPEED;
this->netdev_speed = (status == BX_NETDEV_1GBIT) ? 1000 :
(status == BX_NETDEV_100MBIT) ? 100 : 10;
if (bx_slirp_instances == 0) {
rx_timer_index =
DEV_register_timer(this, this->rx_timer_handler, 1000, 1, 1,
"eth_slirp");
#ifndef WIN32
signal(SIGPIPE, SIG_IGN);
#endif
}
if ((strlen(script) > 0) && (strcmp(script, "none"))) {
if (!parse_slirp_conf(script)) {
BX_ERROR(("reading slirp config failed"));
}
}
#if BX_HAVE_LIBSLIRP
slirp = slirp_new(&config, &callbacks, this);
#else
slirplog = new logfunctions();
sprintf(prefix, "SLIRP%d", bx_slirp_instances);
slirplog->put(prefix);
slirp = slirp_new(&config, this, slirplog);
#endif
if (n_hostfwd > 0) {
for (int i = 0; i < n_hostfwd; i++) {
slirp_hostfwd(slirp, hostfwd[i], 0);
}
}
#ifndef WIN32
if (smb_export != NULL) {
smb_tmpdir = (char*)malloc(128);
if (slirp_smb(slirp, smb_tmpdir, smb_export, smb_srv) < 0) {
BX_ERROR(("failed to initialize SMB support"));
}
}
#endif
if (pktlog_fn != NULL) {
pktlog_txt = fopen(pktlog_fn, "wb");
slirp_logging = (pktlog_txt != NULL);
if (slirp_logging) {
fprintf(pktlog_txt, "slirp packetmover readable log file\n");
if (strlen(netif) > 0) {
fprintf(pktlog_txt, "TFTP root = %s\n", netif);
} else {
fprintf(pktlog_txt, "TFTP service disabled\n");
}
fprintf(pktlog_txt, "guest MAC address = ");
int i;
for (i=0; i<6; i++)
fprintf(pktlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "\n");
fprintf(pktlog_txt, "--\n");
fflush(pktlog_txt);
}
free(pktlog_fn);
} else {
slirp_logging = 0;
}
bx_slirp_instances++;
}
bx_slirp_pktmover_c::~bx_slirp_pktmover_c()
{
if (slirp != NULL) {
@ -120,14 +274,14 @@ bx_slirp_pktmover_c::~bx_slirp_pktmover_c()
free(smb_export);
}
#endif
if (bootfile != NULL) free(bootfile);
if (hostname != NULL) free(hostname);
if (dnssearch != NULL) {
if (config.bootfile != NULL) free((void*)config.bootfile);
if (config.vhostname != NULL) free((void*)config.vhostname);
if (config.vdnssearch != NULL) {
size_t i = 0;
while (dnssearch[i] != NULL) {
free(dnssearch[i++]);
while (config.vdnssearch[i] != NULL) {
free((void*)config.vdnssearch[i++]);
}
free(dnssearch);
free((void*)config.vdnssearch);
}
while (n_hostfwd > 0) {
free(hostfwd[--n_hostfwd]);
@ -187,18 +341,18 @@ bool bx_slirp_pktmover_c::parse_slirp_conf(const char *conf)
len2 = strip_whitespace(val);
if ((len1 == 0) || (len2 == 0)) continue;
if (!stricmp(param, "restricted")) {
restricted = atoi(val);
config.restricted = atoi(val);
} else if (!stricmp(param, "hostname")) {
if (len2 < 33) {
hostname = (char*)malloc(len2+1);
strcpy(hostname, val);
config.vhostname = (char*)malloc(len2+1);
strcpy((char*)config.vhostname, val);
} else {
BX_ERROR(("slirp: wrong format for 'hostname'"));
}
} else if (!stricmp(param, "bootfile")) {
if (len2 < 128) {
bootfile = (char*)malloc(len2+1);
strcpy(bootfile, val);
config.bootfile = (char*)malloc(len2+1);
strcpy((char*)config.bootfile, val);
} else {
BX_ERROR(("slirp: wrong format for 'bootfile'"));
}
@ -208,38 +362,38 @@ bool bx_slirp_pktmover_c::parse_slirp_conf(const char *conf)
for (i = 0; i < len2; i++) {
if (val[i] == ',') count++;
}
dnssearch = (char**)malloc((count + 1) * sizeof(char*));
config.vdnssearch = (const char**)malloc((count + 1) * sizeof(char*));
i = 0;
tmp = strtok(val, ",");
while (tmp != NULL) {
len2 = strip_whitespace(tmp);
dnssearch[i] = (char*)malloc(len2+1);
strcpy(dnssearch[i], tmp);
config.vdnssearch[i] = (char*)malloc(len2+1);
strcpy((char*)config.vdnssearch[i], tmp);
i++;
tmp = strtok(NULL, ",");
}
dnssearch[i] = NULL;
config.vdnssearch[i] = NULL;
} else {
BX_ERROR(("slirp: wrong format for 'dnssearch'"));
}
} else if (!stricmp(param, "net")) {
if (!inet_aton(val, &net)) {
if (!inet_aton(val, &config.vnetwork)) {
BX_ERROR(("slirp: wrong format for 'net'"));
}
} else if (!stricmp(param, "mask")) {
if (!inet_aton(val, &mask)) {
if (!inet_aton(val, &config.vnetmask)) {
BX_ERROR(("slirp: wrong format for 'mask'"));
}
} else if (!stricmp(param, "host")) {
if (!inet_aton(val, &host)) {
if (!inet_aton(val, &config.vhost)) {
BX_ERROR(("slirp: wrong format for 'host'"));
}
} else if (!stricmp(param, "dhcpstart")) {
if (!inet_aton(val, &dhcp)) {
if (!inet_aton(val, &config.vdhcp_start)) {
BX_ERROR(("slirp: wrong format for 'dhcpstart'"));
}
} else if (!stricmp(param, "dns")) {
if (!inet_aton(val, &dns)) {
if (!inet_aton(val, &config.vnameserver)) {
BX_ERROR(("slirp: wrong format for 'dns'"));
}
#ifndef WIN32
@ -284,102 +438,6 @@ bool bx_slirp_pktmover_c::parse_slirp_conf(const char *conf)
return 1;
}
bx_slirp_pktmover_c::bx_slirp_pktmover_c(const char *netif,
const char *macaddr,
eth_rx_handler_t rxh,
eth_rx_status_t rxstat,
logfunctions *netdev,
const char *script)
{
logfunctions *slirplog;
char prefix[10];
restricted = 0;
slirp = NULL;
hostname = NULL;
bootfile = NULL;
dnssearch = NULL;
pktlog_fn = NULL;
n_hostfwd = 0;
/* default settings according to historic slirp */
net.s_addr = htonl(0x0a000200); /* 10.0.2.0 */
mask.s_addr = htonl(0xffffff00); /* 255.255.255.0 */
host.s_addr = htonl(0x0a000202); /* 10.0.2.2 */
dhcp.s_addr = htonl(0x0a00020f); /* 10.0.2.15 */
dns.s_addr = htonl(0x0a000203); /* 10.0.2.3 */
#ifndef WIN32
smb_export = NULL;
smb_tmpdir = NULL;
smb_srv.s_addr = 0;
#endif
this->netdev = netdev;
if (sizeof(struct arphdr) != 28) {
BX_FATAL(("system error: invalid ARP header structure size"));
}
BX_INFO(("slirp network driver"));
this->rxh = rxh;
this->rxstat = rxstat;
Bit32u status = this->rxstat(this->netdev) & BX_NETDEV_SPEED;
this->netdev_speed = (status == BX_NETDEV_1GBIT) ? 1000 :
(status == BX_NETDEV_100MBIT) ? 100 : 10;
if (bx_slirp_instances == 0) {
rx_timer_index =
DEV_register_timer(this, this->rx_timer_handler, 1000, 1, 1,
"eth_slirp");
#ifndef WIN32
signal(SIGPIPE, SIG_IGN);
#endif
}
if ((strlen(script) > 0) && (strcmp(script, "none"))) {
if (!parse_slirp_conf(script)) {
BX_ERROR(("reading slirp config failed"));
}
}
slirplog = new logfunctions();
sprintf(prefix, "SLIRP%d", bx_slirp_instances);
slirplog->put(prefix);
slirp = slirp_init(restricted, net, mask, host, hostname, netif, bootfile, dhcp, dns,
(const char**)dnssearch, this, slirplog);
if (n_hostfwd > 0) {
for (int i = 0; i < n_hostfwd; i++) {
slirp_hostfwd(slirp, hostfwd[i], 0);
}
}
#ifndef WIN32
if (smb_export != NULL) {
smb_tmpdir = (char*)malloc(128);
if (slirp_smb(slirp, smb_tmpdir, smb_export, smb_srv) < 0) {
BX_ERROR(("failed to initialize SMB support"));
}
}
#endif
if (pktlog_fn != NULL) {
pktlog_txt = fopen(pktlog_fn, "wb");
slirp_logging = (pktlog_txt != NULL);
if (slirp_logging) {
fprintf(pktlog_txt, "slirp packetmover readable log file\n");
if (strlen(netif) > 0) {
fprintf(pktlog_txt, "TFTP root = %s\n", netif);
} else {
fprintf(pktlog_txt, "TFTP service disabled\n");
}
fprintf(pktlog_txt, "guest MAC address = ");
int i;
for (i=0; i<6; i++)
fprintf(pktlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "\n");
fprintf(pktlog_txt, "--\n");
fflush(pktlog_txt);
}
free(pktlog_fn);
} else {
slirp_logging = 0;
}
bx_slirp_instances++;
}
void bx_slirp_pktmover_c::sendpkt(void *buf, unsigned io_len)
{
if (slirp_logging) {
@ -389,6 +447,39 @@ void bx_slirp_pktmover_c::sendpkt(void *buf, unsigned io_len)
}
void bx_slirp_pktmover_c::rx_timer_handler(void *this_ptr)
{
((bx_slirp_pktmover_c*)this_ptr)->rx_timer();
}
#if BX_HAVE_LIBSLIRP
static int add_poll_cb(int fd, int events, void *opaque)
{
if (events & SLIRP_POLL_IN)
FD_SET(fd, &rfds);
if (events & SLIRP_POLL_OUT)
FD_SET(fd, &wfds);
if (events & SLIRP_POLL_PRI)
FD_SET(fd, &xfds);
if (nfds < fd)
nfds = fd;
return fd;
}
static int get_revents_cb(int idx, void *opaque)
{
int event = 0;
if (FD_ISSET(idx, &rfds))
event |= SLIRP_POLL_IN;
if (FD_ISSET(idx, &wfds))
event |= SLIRP_POLL_OUT;
if (FD_ISSET(idx, &xfds))
event |= SLIRP_POLL_PRI;
return event;
}
#endif
void bx_slirp_pktmover_c::rx_timer(void)
{
Bit32u timeout = 0;
int ret;
@ -402,11 +493,19 @@ void bx_slirp_pktmover_c::rx_timer_handler(void *this_ptr)
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&xfds);
#if BX_HAVE_LIBSLIRP
slirp_pollfds_fill(slirp, &timeout, add_poll_cb, this);
#else
slirp_select_fill(&nfds, &rfds, &wfds, &xfds, &timeout);
#endif
tv.tv_sec = 0;
tv.tv_usec = 0;
ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
#if BX_HAVE_LIBSLIRP
slirp_pollfds_poll(slirp, (ret < 0), get_revents_cb, this);
#else
slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
#endif
}
int slirp_can_output(void *this_ptr)
@ -439,4 +538,223 @@ void bx_slirp_pktmover_c::receive(void *pkt, unsigned pkt_len)
}
}
#if BX_HAVE_LIBSLIRP
static slirp_ssize_t send_packet(const void *buf, size_t len, void *opaque)
{
bx_slirp_pktmover_c *class_ptr = (bx_slirp_pktmover_c *)opaque;
class_ptr->receive((void*)buf, len);
return len;
}
#endif
#if !defined(_WIN32) && !defined(__CYGWIN__)
#define CONFIG_SMBD_COMMAND "/usr/sbin/smbd"
#include <pwd.h>
/* automatic user mode samba server configuration */
int bx_slirp_pktmover_c::slirp_smb(Slirp *s, char *smb_tmpdir, const char *exported_dir,
struct in_addr vserver_addr)
{
static int instance;
int i;
char smb_conf[128], smb_cmdline[150];
char share[64], error_msg[256];
struct passwd *passwd;
FILE *f;
passwd = getpwuid(geteuid());
if (!passwd) {
BX_ERROR(("failed to retrieve user name"));
return -1;
}
if (access(CONFIG_SMBD_COMMAND, F_OK)) {
BX_ERROR(("could not find '%s', please install it", CONFIG_SMBD_COMMAND));
return -1;
}
if (access(exported_dir, R_OK | X_OK)) {
snprintf(error_msg, sizeof(error_msg), "error accessing shared directory '%s': %s",
exported_dir, strerror(errno));
BX_ERROR(("%s", error_msg));
return -1;
}
i = strlen(exported_dir) - 2;
while ((i > 0) && (exported_dir[i] != '/')) i--;
snprintf(share, sizeof(share), "%s", &exported_dir[i+1]);
if (share[strlen(share)-1] == '/') share[strlen(share)-1] = '\0';
snprintf(smb_tmpdir, 128, "/tmp/bochs-smb.%ld-%d",
(long)getpid(), instance++);
if (mkdir(smb_tmpdir, 0700) < 0) {
snprintf(error_msg, sizeof(error_msg), "could not create samba server dir '%s'",
smb_tmpdir);
BX_ERROR(("%s", error_msg));
return -1;
}
snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_tmpdir, "smb.conf");
f = fopen(smb_conf, "w");
if (!f) {
slirp_smb_cleanup(s, smb_tmpdir);
snprintf(error_msg, sizeof(error_msg), "could not create samba server configuration file '%s'",
smb_conf);
BX_ERROR(("%s", error_msg));
return -1;
}
fprintf(f,
"[global]\n"
"private dir=%s\n"
"interfaces=127.0.0.1\n"
"bind interfaces only=yes\n"
"pid directory=%s\n"
"lock directory=%s\n"
"state directory=%s\n"
"cache directory=%s\n"
"ncalrpc dir=%s/ncalrpc\n"
"log file=%s/log.smbd\n"
"smb passwd file=%s/smbpasswd\n"
"security = user\n"
"map to guest = Bad User\n"
"[%s]\n"
"path=%s\n"
"read only=no\n"
"guest ok=yes\n"
"force user=%s\n",
smb_tmpdir,
smb_tmpdir,
smb_tmpdir,
smb_tmpdir,
smb_tmpdir,
smb_tmpdir,
smb_tmpdir,
smb_tmpdir,
share,
exported_dir,
passwd->pw_name
);
fclose(f);
snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
CONFIG_SMBD_COMMAND, smb_conf);
if ((slirp_add_exec(s, smb_cmdline, &vserver_addr, 139) < 0) ||
(slirp_add_exec(s, smb_cmdline, &vserver_addr, 445) < 0)) {
slirp_smb_cleanup(s, smb_tmpdir);
BX_ERROR(("conflicting/invalid smbserver address"));
return -1;
}
return 0;
}
void bx_slirp_pktmover_c::slirp_smb_cleanup(Slirp *s, char *smb_tmpdir)
{
char cmd[128];
char error_msg[256];
int ret;
if (smb_tmpdir[0] != '\0') {
snprintf(cmd, sizeof(cmd), "rm -rf %s", smb_tmpdir);
ret = system(cmd);
if (ret == -1 || !WIFEXITED(ret)) {
snprintf(error_msg, sizeof(error_msg), "'%s' failed.", cmd);
BX_ERROR(("%s", error_msg));
} else if (WEXITSTATUS(ret)) {
snprintf(error_msg, sizeof(error_msg), "'%s' failed. Error code: %d",
cmd, WEXITSTATUS(ret));
BX_ERROR(("%s", error_msg));
}
smb_tmpdir[0] = '\0';
}
}
#endif
static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
{
const char *p, *p1;
int len;
p = *pp;
p1 = strchr(p, sep);
if (!p1)
return -1;
len = p1 - p;
p1++;
if (buf_size > 0) {
if (len > buf_size - 1)
len = buf_size - 1;
memcpy(buf, p, len);
buf[len] = '\0';
}
*pp = p1;
return 0;
}
int bx_slirp_pktmover_c::slirp_hostfwd(Slirp *s, const char *redir_str, int legacy_format)
{
struct in_addr host_addr;
struct in_addr guest_addr;
int host_port, guest_port;
const char *p;
char buf[256];
int is_udp;
char *end;
host_addr.s_addr = INADDR_ANY;
guest_addr.s_addr = 0;
p = redir_str;
if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
goto fail_syntax;
}
if (!strcmp(buf, "tcp") || buf[0] == '\0') {
is_udp = 0;
} else if (!strcmp(buf, "udp")) {
is_udp = 1;
} else {
goto fail_syntax;
}
if (!legacy_format) {
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
goto fail_syntax;
}
if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
goto fail_syntax;
}
}
if (get_str_sep(buf, sizeof(buf), &p, legacy_format ? ':' : '-') < 0) {
goto fail_syntax;
}
host_port = strtol(buf, &end, 0);
if (*end != '\0' || host_port < 1 || host_port > 65535) {
goto fail_syntax;
}
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
goto fail_syntax;
}
if (buf[0] != '\0' && !inet_aton(buf, &guest_addr)) {
goto fail_syntax;
}
guest_port = strtol(p, &end, 0);
if (*end != '\0' || guest_port < 1 || guest_port > 65535) {
goto fail_syntax;
}
if (slirp_add_hostfwd(s, is_udp, host_addr, host_port, guest_addr,
guest_port) < 0) {
BX_ERROR(("could not set up host forwarding rule '%s'", redir_str));
return -1;
}
return 0;
fail_syntax:
BX_ERROR(("invalid host forwarding rule '%s'", redir_str));
return -1;
}
#endif /* if BX_NETWORKING && BX_NETMOD_SLIRP */

View File

@ -138,220 +138,4 @@ int qemu_socket(int domain, int type, int protocol)
return ret;
}
#if !defined(_WIN32) && !defined(__CYGWIN__)
#define CONFIG_SMBD_COMMAND "/usr/sbin/smbd"
#include <pwd.h>
/* automatic user mode samba server configuration */
void slirp_smb_cleanup(Slirp *s, char *smb_tmpdir)
{
char cmd[128];
char error_msg[256];
int ret;
if (smb_tmpdir[0] != '\0') {
snprintf(cmd, sizeof(cmd), "rm -rf %s", smb_tmpdir);
ret = system(cmd);
if (ret == -1 || !WIFEXITED(ret)) {
snprintf(error_msg, sizeof(error_msg), "'%s' failed.", cmd);
slirp_warning(s, error_msg);
} else if (WEXITSTATUS(ret)) {
snprintf(error_msg, sizeof(error_msg), "'%s' failed. Error code: %d",
cmd, WEXITSTATUS(ret));
slirp_warning(s, error_msg);
}
smb_tmpdir[0] = '\0';
}
}
int slirp_smb(Slirp *s, char *smb_tmpdir, const char *exported_dir,
struct in_addr vserver_addr)
{
static int instance;
int i;
char smb_conf[128], smb_cmdline[150];
char share[64], error_msg[256];
struct passwd *passwd;
FILE *f;
passwd = getpwuid(geteuid());
if (!passwd) {
sprintf(error_msg, "failed to retrieve user name");
slirp_warning(s, error_msg);
return -1;
}
if (access(CONFIG_SMBD_COMMAND, F_OK)) {
sprintf(error_msg, "could not find '%s', please install it",
CONFIG_SMBD_COMMAND);
slirp_warning(s, error_msg);
return -1;
}
if (access(exported_dir, R_OK | X_OK)) {
snprintf(error_msg, sizeof(error_msg), "error accessing shared directory '%s': %s",
exported_dir, strerror(errno));
slirp_warning(s, error_msg);
return -1;
}
i = strlen(exported_dir) - 2;
while ((i > 0) && (exported_dir[i] != '/')) i--;
snprintf(share, sizeof(share), "%s", &exported_dir[i+1]);
if (share[strlen(share)-1] == '/') share[strlen(share)-1] = '\0';
snprintf(smb_tmpdir, 128, "/tmp/bochs-smb.%ld-%d",
(long)getpid(), instance++);
if (mkdir(smb_tmpdir, 0700) < 0) {
snprintf(error_msg, sizeof(error_msg), "could not create samba server dir '%s'",
smb_tmpdir);
slirp_warning(s, error_msg);
return -1;
}
snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_tmpdir, "smb.conf");
f = fopen(smb_conf, "w");
if (!f) {
slirp_smb_cleanup(s, smb_tmpdir);
snprintf(error_msg, sizeof(error_msg), "could not create samba server configuration file '%s'",
smb_conf);
slirp_warning(s, error_msg);
return -1;
}
fprintf(f,
"[global]\n"
"private dir=%s\n"
"interfaces=127.0.0.1\n"
"bind interfaces only=yes\n"
"pid directory=%s\n"
"lock directory=%s\n"
"state directory=%s\n"
"cache directory=%s\n"
"ncalrpc dir=%s/ncalrpc\n"
"log file=%s/log.smbd\n"
"smb passwd file=%s/smbpasswd\n"
"security = user\n"
"map to guest = Bad User\n"
"[%s]\n"
"path=%s\n"
"read only=no\n"
"guest ok=yes\n"
"force user=%s\n",
smb_tmpdir,
smb_tmpdir,
smb_tmpdir,
smb_tmpdir,
smb_tmpdir,
smb_tmpdir,
smb_tmpdir,
smb_tmpdir,
share,
exported_dir,
passwd->pw_name
);
fclose(f);
snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
CONFIG_SMBD_COMMAND, smb_conf);
if (slirp_add_exec(s, 0, smb_cmdline, &vserver_addr, 139) < 0 ||
slirp_add_exec(s, 0, smb_cmdline, &vserver_addr, 445) < 0) {
slirp_smb_cleanup(s, smb_tmpdir);
sprintf(error_msg, "conflicting/invalid smbserver address");
slirp_warning(s, error_msg);
return -1;
}
return 0;
}
#endif
static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
{
const char *p, *p1;
int len;
p = *pp;
p1 = strchr(p, sep);
if (!p1)
return -1;
len = p1 - p;
p1++;
if (buf_size > 0) {
if (len > buf_size - 1)
len = buf_size - 1;
memcpy(buf, p, len);
buf[len] = '\0';
}
*pp = p1;
return 0;
}
int slirp_hostfwd(Slirp *s, const char *redir_str, int legacy_format)
{
struct in_addr host_addr;
struct in_addr guest_addr;
int host_port, guest_port;
const char *p;
char buf[256], error_msg[256];
int is_udp;
char *end;
host_addr.s_addr = INADDR_ANY;
guest_addr.s_addr = 0;
p = redir_str;
if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
goto fail_syntax;
}
if (!strcmp(buf, "tcp") || buf[0] == '\0') {
is_udp = 0;
} else if (!strcmp(buf, "udp")) {
is_udp = 1;
} else {
goto fail_syntax;
}
if (!legacy_format) {
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
goto fail_syntax;
}
if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
goto fail_syntax;
}
}
if (get_str_sep(buf, sizeof(buf), &p, legacy_format ? ':' : '-') < 0) {
goto fail_syntax;
}
host_port = strtol(buf, &end, 0);
if (*end != '\0' || host_port < 1 || host_port > 65535) {
goto fail_syntax;
}
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
goto fail_syntax;
}
if (buf[0] != '\0' && !inet_aton(buf, &guest_addr)) {
goto fail_syntax;
}
guest_port = strtol(p, &end, 0);
if (*end != '\0' || guest_port < 1 || guest_port > 65535) {
goto fail_syntax;
}
if (slirp_add_hostfwd(s, is_udp, host_addr, host_port, guest_addr,
guest_port) < 0) {
sprintf(error_msg, "could not set up host forwarding rule '%s'", redir_str);
slirp_warning(s, error_msg);
return -1;
}
return 0;
fail_syntax:
sprintf(error_msg, "invalid host forwarding rule '%s'", redir_str);
slirp_warning(s, error_msg);
return -1;
}
#endif

View File

@ -10,6 +10,12 @@
struct Slirp;
typedef struct Slirp Slirp;
typedef struct SlirpConfig {
int restricted;
struct in_addr vnetwork, vnetmask, vhost, vdhcp_start, vnameserver;
const char *bootfile, *vhostname, **vdnssearch, *tftp_path;
} SlirpConfig;
int get_dns_addr(struct in_addr *pdns_addr);
Slirp *slirp_init(int restricted, struct in_addr vnetwork,
@ -18,6 +24,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
const char *bootfile, struct in_addr vdhcp_start,
struct in_addr vnameserver, const char **vdnssearch,
void *opaque, void *logfn);
Slirp *slirp_new(SlirpConfig *cfg, void *opaque, void *logfn);
void slirp_cleanup(Slirp *slirp);
void slirp_select_fill(int *pnfds, fd_set *readfds, fd_set *writefds,
@ -37,7 +44,7 @@ int slirp_add_hostfwd(Slirp *slirp, int is_udp,
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, const void *args,
struct in_addr *guest_addr, int guest_port);
void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr,

View File

@ -210,19 +210,14 @@ static void slirp_init_once(void)
loopback_mask = htonl(IN_CLASSA_NET);
}
Slirp *slirp_init(int restricted, struct in_addr vnetwork,
struct in_addr vnetmask, struct in_addr vhost,
const char *vhostname, const char *tftp_path,
const char *bootfile, struct in_addr vdhcp_start,
struct in_addr vnameserver, const char **vdnssearch,
void *opaque, void *logfn)
Slirp *slirp_new(SlirpConfig *cfg, void *opaque, void *logfn)
{
Slirp *slirp = (Slirp*)malloc(sizeof(Slirp));
memset(slirp, 0, sizeof(Slirp));
slirp_init_once();
slirp->restricted = restricted;
slirp->restricted = cfg->restricted;
if_init(slirp);
ip_init(slirp);
@ -230,24 +225,24 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
/* Initialise mbufs *after* setting the MTU */
m_init(slirp);
slirp->vnetwork_addr = vnetwork;
slirp->vnetwork_mask = vnetmask;
slirp->vhost_addr = vhost;
if (vhostname) {
slirp->vnetwork_addr = cfg->vnetwork;
slirp->vnetwork_mask = cfg->vnetmask;
slirp->vhost_addr = cfg->vhost;
if (cfg->vhostname) {
pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
vhostname);
cfg->vhostname);
}
if (tftp_path) {
slirp->tftp_prefix = strdup(tftp_path);
if (cfg->tftp_path) {
slirp->tftp_prefix = strdup(cfg->tftp_path);
}
if (bootfile) {
slirp->bootp_filename = strdup(bootfile);
if (cfg->bootfile) {
slirp->bootp_filename = strdup(cfg->bootfile);
}
slirp->vdhcp_startaddr = vdhcp_start;
slirp->vnameserver_addr = vnameserver;
slirp->vdhcp_startaddr = cfg->vdhcp_start;
slirp->vnameserver_addr = cfg->vnameserver;
if (vdnssearch) {
translate_dnssearch(slirp, vdnssearch);
if (cfg->vdnssearch) {
translate_dnssearch(slirp, cfg->vdnssearch);
}
slirp->opaque = opaque;
@ -258,6 +253,28 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
return slirp;
}
Slirp *slirp_init(int restricted, struct in_addr vnetwork,
struct in_addr vnetmask, struct in_addr vhost,
const char *vhostname, const char *tftp_path,
const char *bootfile, struct in_addr vdhcp_start,
struct in_addr vnameserver, const char **vdnssearch,
void *opaque, void *logfn)
{
SlirpConfig cfg;
memset(&cfg, 0, sizeof(cfg));
cfg.restricted = restricted;
cfg.vnetwork = vnetwork;
cfg.vnetmask = vnetmask;
cfg.vhost = vhost;
cfg.vhostname = vhostname;
cfg.tftp_path = tftp_path;
cfg.bootfile = bootfile;
cfg.vdhcp_start = vdhcp_start;
cfg.vnameserver = vnameserver;
cfg.vdnssearch = vdnssearch;
return slirp_new(&cfg, opaque, logfn);
}
void slirp_cleanup(Slirp *slirp)
{
struct ex_list *ex_ptr;
@ -867,7 +884,7 @@ 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,
int slirp_add_exec(Slirp *slirp, const void *args,
struct in_addr *guest_addr, int guest_port)
{
if (!guest_addr->s_addr) {
@ -880,7 +897,7 @@ int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
return -1;
}
return add_exec(&slirp->exec_list, do_pty, (char *)args, *guest_addr,
return add_exec(&slirp->exec_list, 0, (char *)args, *guest_addr,
htons(guest_port));
}