- apply patch from splite@purdue.edu that add an ethernet packet mover
for Linux!!! I tested this using host OS kernel 2.2.14, and was able to use telnet, ftp, irc, lynx, etc. Because it is a packet filter solution, you aren't able to talk to the host machine, only to other machines on the network. The patch itself is in patches/patch.ethlinux-splite.
This commit is contained in:
parent
d7b6442ad6
commit
75c87e2113
107
bochs/configure
vendored
107
bochs/configure
vendored
@ -3196,6 +3196,39 @@ else
|
||||
echo "$ac_t""no" 1>&6
|
||||
fi
|
||||
|
||||
ac_safe=`echo "netpacket/packet.h" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for netpacket/packet.h""... $ac_c" 1>&6
|
||||
echo "configure:3202: checking for netpacket/packet.h" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3207 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <netpacket/packet.h>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:3212: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_header_$ac_safe=yes"
|
||||
else
|
||||
echo "$ac_err" >&5
|
||||
echo "configure: failed program was:" >&5
|
||||
cat conftest.$ac_ext >&5
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_header_$ac_safe=no"
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
|
||||
echo "$ac_t""yes" 1>&6
|
||||
NE2K_OBJS="$NE2K_OBJS eth_linux.o"
|
||||
else
|
||||
echo "$ac_t""no" 1>&6
|
||||
fi
|
||||
|
||||
else
|
||||
echo "$ac_t""no" 1>&6
|
||||
cat >> confdefs.h <<\EOF
|
||||
@ -3220,7 +3253,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking for i440FX PCI support""... $ac_c" 1>&6
|
||||
echo "configure:3224: checking for i440FX PCI support" >&5
|
||||
echo "configure:3257: checking for i440FX PCI support" >&5
|
||||
# Check whether --enable-pci or --disable-pci was given.
|
||||
if test "${enable_pci+set}" = set; then
|
||||
enableval="$enable_pci"
|
||||
@ -3255,7 +3288,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking for port e9 hack""... $ac_c" 1>&6
|
||||
echo "configure:3259: checking for port e9 hack" >&5
|
||||
echo "configure:3292: checking for port e9 hack" >&5
|
||||
# Check whether --enable-port-e9-hack or --disable-port-e9-hack was given.
|
||||
if test "${enable_port_e9_hack+set}" = set; then
|
||||
enableval="$enable_port_e9_hack"
|
||||
@ -3286,7 +3319,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking for use of .cpp as suffix""... $ac_c" 1>&6
|
||||
echo "configure:3290: checking for use of .cpp as suffix" >&5
|
||||
echo "configure:3323: checking for use of .cpp as suffix" >&5
|
||||
# Check whether --enable-cpp or --disable-cpp was given.
|
||||
if test "${enable_cpp+set}" = set; then
|
||||
enableval="$enable_cpp"
|
||||
@ -3328,7 +3361,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking for Bochs internal debugger support""... $ac_c" 1>&6
|
||||
echo "configure:3332: checking for Bochs internal debugger support" >&5
|
||||
echo "configure:3365: checking for Bochs internal debugger support" >&5
|
||||
# Check whether --enable-debugger or --disable-debugger was given.
|
||||
if test "${enable_debugger+set}" = set; then
|
||||
enableval="$enable_debugger"
|
||||
@ -3366,7 +3399,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking for disassembler support""... $ac_c" 1>&6
|
||||
echo "configure:3370: checking for disassembler support" >&5
|
||||
echo "configure:3403: checking for disassembler support" >&5
|
||||
# Check whether --enable-disasm or --disable-disasm was given.
|
||||
if test "${enable_disasm+set}" = set; then
|
||||
enableval="$enable_disasm"
|
||||
@ -3413,7 +3446,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking whether to use readline""... $ac_c" 1>&6
|
||||
echo "configure:3417: checking whether to use readline" >&5
|
||||
echo "configure:3450: checking whether to use readline" >&5
|
||||
# Check whether --enable-readline or --disable-readline was given.
|
||||
if test "${enable_readline+set}" = set; then
|
||||
enableval="$enable_readline"
|
||||
@ -3435,7 +3468,7 @@ fi
|
||||
|
||||
if test "$want_readline" = yes; then
|
||||
echo $ac_n "checking for readline in -lreadline""... $ac_c" 1>&6
|
||||
echo "configure:3439: checking for readline in -lreadline" >&5
|
||||
echo "configure:3472: checking for readline in -lreadline" >&5
|
||||
ac_lib_var=`echo readline'_'readline | sed 'y%./+-%__p_%'`
|
||||
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
@ -3443,7 +3476,7 @@ else
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-lreadline $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3447 "configure"
|
||||
#line 3480 "configure"
|
||||
#include "confdefs.h"
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
@ -3454,7 +3487,7 @@ int main() {
|
||||
readline()
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:3458: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:3491: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_$ac_lib_var=yes"
|
||||
else
|
||||
@ -3489,17 +3522,17 @@ fi
|
||||
|
||||
ac_safe=`echo "readline/history.h" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for readline/history.h""... $ac_c" 1>&6
|
||||
echo "configure:3493: checking for readline/history.h" >&5
|
||||
echo "configure:3526: checking for readline/history.h" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 3498 "configure"
|
||||
#line 3531 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <readline/history.h>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:3503: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:3536: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -3527,7 +3560,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking for loader support""... $ac_c" 1>&6
|
||||
echo "configure:3531: checking for loader support" >&5
|
||||
echo "configure:3564: checking for loader support" >&5
|
||||
# Check whether --enable-loader or --disable-loader was given.
|
||||
if test "${enable_loader+set}" = set; then
|
||||
enableval="$enable_loader"
|
||||
@ -3565,7 +3598,7 @@ fi
|
||||
INSTRUMENT_DIR='instrument/stubs'
|
||||
|
||||
echo $ac_n "checking for instrumentation support""... $ac_c" 1>&6
|
||||
echo "configure:3569: checking for instrumentation support" >&5
|
||||
echo "configure:3602: checking for instrumentation support" >&5
|
||||
# Check whether --enable-instrumentation or --disable-instrumentation was given.
|
||||
if test "${enable_instrumentation+set}" = set; then
|
||||
enableval="$enable_instrumentation"
|
||||
@ -3700,7 +3733,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking for VGA emulation""... $ac_c" 1>&6
|
||||
echo "configure:3704: checking for VGA emulation" >&5
|
||||
echo "configure:3737: checking for VGA emulation" >&5
|
||||
# Check whether --enable-vga or --disable-vga was given.
|
||||
if test "${enable_vga+set}" = set; then
|
||||
enableval="$enable_vga"
|
||||
@ -3734,7 +3767,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking for FPU emulation""... $ac_c" 1>&6
|
||||
echo "configure:3738: checking for FPU emulation" >&5
|
||||
echo "configure:3771: checking for FPU emulation" >&5
|
||||
FPU_VAR=''
|
||||
FPU_GLUE_OBJ=''
|
||||
# Check whether --enable-fpu or --disable-fpu was given.
|
||||
@ -3779,7 +3812,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking for x86 debugger support""... $ac_c" 1>&6
|
||||
echo "configure:3783: checking for x86 debugger support" >&5
|
||||
echo "configure:3816: checking for x86 debugger support" >&5
|
||||
# Check whether --enable-x86-debugger or --disable-x86-debugger was given.
|
||||
if test "${enable_x86_debugger+set}" = set; then
|
||||
enableval="$enable_x86_debugger"
|
||||
@ -3815,7 +3848,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking for CDROM support""... $ac_c" 1>&6
|
||||
echo "configure:3819: checking for CDROM support" >&5
|
||||
echo "configure:3852: checking for CDROM support" >&5
|
||||
# Check whether --enable-cdrom or --disable-cdrom was given.
|
||||
if test "${enable_cdrom+set}" = set; then
|
||||
enableval="$enable_cdrom"
|
||||
@ -3857,7 +3890,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking for Sound Blaster 16 support""... $ac_c" 1>&6
|
||||
echo "configure:3861: checking for Sound Blaster 16 support" >&5
|
||||
echo "configure:3894: checking for Sound Blaster 16 support" >&5
|
||||
# Check whether --enable-sb16 or --disable-sb16 was given.
|
||||
if test "${enable_sb16+set}" = set; then
|
||||
enableval="$enable_sb16"
|
||||
@ -4006,7 +4039,7 @@ fi
|
||||
|
||||
|
||||
echo $ac_n "checking for gui library to use""... $ac_c" 1>&6
|
||||
echo "configure:4010: checking for gui library to use" >&5
|
||||
echo "configure:4043: checking for gui library to use" >&5
|
||||
|
||||
if (test "$with_x11" != yes) && \
|
||||
(test "$with_beos" != yes) && \
|
||||
@ -4152,7 +4185,7 @@ fi
|
||||
|
||||
if test "$use_curses" = yes; then
|
||||
echo $ac_n "checking for mvaddch in -lcurses""... $ac_c" 1>&6
|
||||
echo "configure:4156: checking for mvaddch in -lcurses" >&5
|
||||
echo "configure:4189: checking for mvaddch in -lcurses" >&5
|
||||
ac_lib_var=`echo curses'_'mvaddch | sed 'y%./+-%__p_%'`
|
||||
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
@ -4160,7 +4193,7 @@ else
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-lcurses $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 4164 "configure"
|
||||
#line 4197 "configure"
|
||||
#include "confdefs.h"
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
@ -4171,7 +4204,7 @@ int main() {
|
||||
mvaddch()
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:4175: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:4208: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_$ac_lib_var=yes"
|
||||
else
|
||||
@ -4192,7 +4225,7 @@ else
|
||||
fi
|
||||
|
||||
echo $ac_n "checking for mvaddch in -lncurses""... $ac_c" 1>&6
|
||||
echo "configure:4196: checking for mvaddch in -lncurses" >&5
|
||||
echo "configure:4229: checking for mvaddch in -lncurses" >&5
|
||||
ac_lib_var=`echo ncurses'_'mvaddch | sed 'y%./+-%__p_%'`
|
||||
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
@ -4200,7 +4233,7 @@ else
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-lncurses $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 4204 "configure"
|
||||
#line 4237 "configure"
|
||||
#include "confdefs.h"
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
@ -4211,7 +4244,7 @@ int main() {
|
||||
mvaddch()
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:4215: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:4248: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_$ac_lib_var=yes"
|
||||
else
|
||||
@ -4232,7 +4265,7 @@ else
|
||||
fi
|
||||
|
||||
echo $ac_n "checking for mvaddch in -ltermlib""... $ac_c" 1>&6
|
||||
echo "configure:4236: checking for mvaddch in -ltermlib" >&5
|
||||
echo "configure:4269: checking for mvaddch in -ltermlib" >&5
|
||||
ac_lib_var=`echo termlib'_'mvaddch | sed 'y%./+-%__p_%'`
|
||||
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
@ -4240,7 +4273,7 @@ else
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-ltermlib $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 4244 "configure"
|
||||
#line 4277 "configure"
|
||||
#include "confdefs.h"
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
@ -4251,7 +4284,7 @@ int main() {
|
||||
mvaddch()
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:4255: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:4288: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_$ac_lib_var=yes"
|
||||
else
|
||||
@ -4280,18 +4313,18 @@ fi
|
||||
if test "$with_rfb" = yes; then
|
||||
# first see if compiler takes "-pthread" argument
|
||||
echo $ac_n "checking for -pthread arg to compiler""... $ac_c" 1>&6
|
||||
echo "configure:4284: checking for -pthread arg to compiler" >&5
|
||||
echo "configure:4317: checking for -pthread arg to compiler" >&5
|
||||
CFLAGS_SAVE="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 4288 "configure"
|
||||
#line 4321 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <pthread.h>
|
||||
int main() {
|
||||
pthread_create(0,0,0,0);
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:4295: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:4328: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
|
||||
# it compiles with -pthread
|
||||
@ -4307,7 +4340,7 @@ else
|
||||
# now try with -lpthread
|
||||
CFLAGS="$CFLAGS_SAVE"
|
||||
echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6
|
||||
echo "configure:4311: checking for pthread_create in -lpthread" >&5
|
||||
echo "configure:4344: checking for pthread_create in -lpthread" >&5
|
||||
ac_lib_var=`echo pthread'_'pthread_create | sed 'y%./+-%__p_%'`
|
||||
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
@ -4315,7 +4348,7 @@ else
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-lpthread $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 4319 "configure"
|
||||
#line 4352 "configure"
|
||||
#include "confdefs.h"
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
@ -4326,7 +4359,7 @@ int main() {
|
||||
pthread_create()
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:4330: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:4363: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_$ac_lib_var=yes"
|
||||
else
|
||||
@ -4378,7 +4411,7 @@ fi
|
||||
# Extract the first word of "gzip", so it can be a program name with args.
|
||||
set dummy gzip; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:4382: checking for $ac_word" >&5
|
||||
echo "configure:4415: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_GZIP'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -4413,7 +4446,7 @@ fi
|
||||
# Extract the first word of "tar", so it can be a program name with args.
|
||||
set dummy tar; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:4417: checking for $ac_word" >&5
|
||||
echo "configure:4450: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_TAR'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
|
@ -311,6 +311,7 @@ AC_ARG_ENABLE(ne2000,
|
||||
AC_DEFINE(BX_NE2K_SUPPORT, 1)
|
||||
NE2K_OBJS='ne2k.o eth.o eth_null.o'
|
||||
AC_CHECK_HEADER(net/bpf.h, NE2K_OBJS="$NE2K_OBJS eth_fbsd.o")
|
||||
AC_CHECK_HEADER(netpacket/packet.h, NE2K_OBJS="$NE2K_OBJS eth_linux.o")
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
AC_DEFINE(BX_NE2K_SUPPORT, 0)
|
||||
|
@ -75,6 +75,6 @@ private:
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
#define ETH_FBSD 1
|
||||
#endif
|
||||
#if (0 && defined(linux))
|
||||
#if defined(linux)
|
||||
#define ETH_LINUX 1
|
||||
#endif
|
||||
|
276
bochs/iodev/eth_linux.cc
Normal file
276
bochs/iodev/eth_linux.cc
Normal file
@ -0,0 +1,276 @@
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
//
|
||||
// MandrakeSoft S.A.
|
||||
// 43, rue d'Aboukir
|
||||
// 75002 Paris - France
|
||||
// http://www.linux-mandrake.com/
|
||||
// http://www.mandrakesoft.com/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
// Peter Grehan (grehan@iprg.nokia.com) coded all of this
|
||||
// NE2000/ether stuff.
|
||||
|
||||
// eth_linux.cc - A Linux socket filter adaptation of the FreeBSD BPF driver
|
||||
// <splite@purdue.edu> 21 June 2001
|
||||
//
|
||||
// Problems and limitations:
|
||||
// - packets cannot be sent from BOCHS to the host
|
||||
// - Linux kernel sometimes gets network watchdog timeouts under emulation
|
||||
// - author doesn't know C++
|
||||
//
|
||||
// The config line in .bochsrc should look something like:
|
||||
//
|
||||
// ne2k: ioaddr=0x280, irq=10, mac=00:a:b:c:1:2, ethmod=linux, ethdev=eth0
|
||||
//
|
||||
|
||||
#include "bochs.h"
|
||||
#ifdef ETH_LINUX
|
||||
#define LOG_THIS this->
|
||||
|
||||
extern "C" {
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netpacket/packet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/filter.h>
|
||||
};
|
||||
|
||||
#define BX_PACKET_POLL 1000 // Poll for a frame every 1000 usecs
|
||||
|
||||
#define BX_PACKET_BUFSIZ 2048 // Enough for an ether frame
|
||||
|
||||
// template filter for a unicast mac address and all
|
||||
// multicast/broadcast frames
|
||||
static const struct sock_filter macfilter[] = {
|
||||
BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2),
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xaaaaaaaa, 0, 2),
|
||||
BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 0),
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0000aaaa, 2, 0),
|
||||
BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 0),
|
||||
BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x01, 0, 1),
|
||||
BPF_STMT(BPF_RET, 1514),
|
||||
BPF_STMT(BPF_RET, 0),
|
||||
};
|
||||
#define BX_LSF_ICNT 8 // number of lsf instructions in macfilter
|
||||
|
||||
#if 0
|
||||
// template filter for all frames
|
||||
static const struct sock_filter promiscfilter[] = {
|
||||
BPF_STMT(BPF_RET, 1514)
|
||||
};
|
||||
#endif
|
||||
|
||||
//
|
||||
// Define the class. This is private to this module
|
||||
//
|
||||
class bx_linux_pktmover_c : public eth_pktmover_c {
|
||||
public:
|
||||
bx_linux_pktmover_c(const char *netif,
|
||||
const char *macaddr,
|
||||
eth_rx_handler_t rxh,
|
||||
void *rxarg);
|
||||
void sendpkt(void *buf, unsigned io_len);
|
||||
|
||||
private:
|
||||
unsigned char *linux_macaddr[6];
|
||||
int fd;
|
||||
int ifindex;
|
||||
static void rx_timer_handler(void *);
|
||||
void rx_timer(void);
|
||||
int rx_timer_index;
|
||||
struct sock_filter filter[BX_LSF_ICNT];
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Define the static class that registers the derived pktmover class,
|
||||
// and allocates one on request.
|
||||
//
|
||||
class bx_linux_locator_c : public eth_locator_c {
|
||||
public:
|
||||
bx_linux_locator_c(void) : eth_locator_c("linux") {}
|
||||
protected:
|
||||
eth_pktmover_c *allocate(const char *netif,
|
||||
const char *macaddr,
|
||||
eth_rx_handler_t rxh,
|
||||
void *rxarg) {
|
||||
return (new bx_linux_pktmover_c(netif, macaddr, rxh, rxarg));
|
||||
}
|
||||
} bx_linux_match;
|
||||
|
||||
|
||||
//
|
||||
// Define the methods for the bx_linux_pktmover derived class
|
||||
//
|
||||
|
||||
// the constructor
|
||||
//
|
||||
bx_linux_pktmover_c::bx_linux_pktmover_c(const char *netif,
|
||||
const char *macaddr,
|
||||
eth_rx_handler_t rxh,
|
||||
void *rxarg)
|
||||
{
|
||||
struct sockaddr_ll sll;
|
||||
struct packet_mreq mr;
|
||||
struct ifreq ifr;
|
||||
struct sock_fprog fp;
|
||||
|
||||
memcpy(linux_macaddr, macaddr, 6);
|
||||
|
||||
// Open packet socket
|
||||
//
|
||||
if ((this->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
|
||||
if (errno == EACCES)
|
||||
BX_INFO(("eth_linux: must be root or have CAP_NET_RAW capability to open socket\n"));
|
||||
else
|
||||
BX_INFO(("eth_linux: could not open socket\n"));
|
||||
this->fd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Translate interface name to index
|
||||
//
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strcpy(ifr.ifr_name, netif);
|
||||
if (ioctl(this->fd, SIOCGIFINDEX, &ifr) == -1) {
|
||||
BX_INFO(("eth_linux: could not get index for interface %s\n", netif));
|
||||
close(fd);
|
||||
this->fd = -1;
|
||||
return;
|
||||
}
|
||||
this->ifindex = ifr.ifr_ifindex;
|
||||
|
||||
|
||||
// Bind to given interface
|
||||
//
|
||||
memset(&sll, 0, sizeof(sll));
|
||||
sll.sll_family = AF_PACKET;
|
||||
sll.sll_ifindex = this->ifindex;
|
||||
if (bind(fd, (struct sockaddr *)&sll, (socklen_t)sizeof(sll)) == -1) {
|
||||
BX_INFO(("eth_linux: could not bind to interface %s\n", netif));
|
||||
close(fd);
|
||||
this->fd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Put the device into promisc mode.
|
||||
//
|
||||
memset(&mr, 0, sizeof(mr));
|
||||
mr.mr_ifindex = this->ifindex;
|
||||
mr.mr_type = PACKET_MR_PROMISC;
|
||||
if (setsockopt(this->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (void *)&mr, (socklen_t)sizeof(mr)) == -1) {
|
||||
BX_INFO(("eth_linux: could not enable promisc mode: %s\n", strerror(errno)));
|
||||
close(this->fd);
|
||||
this->fd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up non-blocking i/o
|
||||
if (fcntl(this->fd, F_SETFL, O_NONBLOCK) == -1) {
|
||||
BX_INFO(("eth_linux: could not set non-blocking i/o on socket\n"));
|
||||
close(this->fd);
|
||||
this->fd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Install a filter
|
||||
#ifdef notdef
|
||||
memcpy(&this->filter, promiscfilter, sizeof(promiscfilter));
|
||||
fp.len = 1;
|
||||
#endif
|
||||
memcpy(&this->filter, macfilter, sizeof(macfilter));
|
||||
this->filter[1].k = (macaddr[2] & 0xff) << 24 | (macaddr[3] & 0xff) << 16 |
|
||||
(macaddr[4] & 0xff) << 8 | (macaddr[5] & 0xff);
|
||||
this->filter[3].k = (macaddr[0] & 0xff) << 8 | (macaddr[1] & 0xff);
|
||||
fp.len = BX_LSF_ICNT;
|
||||
fp.filter = this->filter;
|
||||
BX_INFO(("eth_linux: fp.len=%d fp.filter=%lx", fp.len, fp.filter));
|
||||
if (setsockopt(this->fd, SOL_SOCKET, SO_ATTACH_FILTER, &fp, sizeof(fp)) < 0) {
|
||||
BX_INFO(("eth_linux: could not set socket filter: %s", strerror(errno)));
|
||||
close(this->fd);
|
||||
this->fd = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the rx poll
|
||||
this->rx_timer_index =
|
||||
bx_pc_system.register_timer(this, this->rx_timer_handler, BX_PACKET_POLL,
|
||||
1, 1); // continuous, active
|
||||
|
||||
this->rxh = rxh;
|
||||
this->rxarg = rxarg;
|
||||
BX_INFO(("eth_linux: enabled NE2K emulation on interface %s\n", netif));
|
||||
}
|
||||
|
||||
// the output routine - called with pre-formatted ethernet frame.
|
||||
void
|
||||
bx_linux_pktmover_c::sendpkt(void *buf, unsigned io_len)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (this->fd != -1)
|
||||
status = write(this->fd, buf, io_len);
|
||||
if (status == -1)
|
||||
BX_INFO(("eth_linux: write failed: %s", strerror(errno)));
|
||||
}
|
||||
|
||||
// The receive poll process
|
||||
void
|
||||
bx_linux_pktmover_c::rx_timer_handler(void *this_ptr)
|
||||
{
|
||||
bx_linux_pktmover_c *class_ptr = (bx_linux_pktmover_c *) this_ptr;
|
||||
|
||||
class_ptr->rx_timer();
|
||||
}
|
||||
|
||||
void
|
||||
bx_linux_pktmover_c::rx_timer(void)
|
||||
{
|
||||
int nbytes = 0;
|
||||
Bit8u rxbuf[BX_PACKET_BUFSIZ];
|
||||
struct sockaddr_ll sll;
|
||||
socklen_t fromlen;
|
||||
static unsigned char bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
|
||||
|
||||
if (this->fd == -1)
|
||||
return;
|
||||
|
||||
fromlen = sizeof(sll);
|
||||
nbytes = recvfrom(this->fd, rxbuf, sizeof(rxbuf), 0, (struct sockaddr *)&sll, &fromlen);
|
||||
|
||||
if (nbytes == -1) {
|
||||
if (errno != EAGAIN)
|
||||
BX_INFO(("eth_linux: error receiving packet: %s\n", strerror(errno)));
|
||||
return;
|
||||
}
|
||||
|
||||
// this should be done with LSF someday
|
||||
// filter out packets sourced by us
|
||||
if (memcmp(sll.sll_addr, this->linux_macaddr, 6) == 0)
|
||||
return;
|
||||
// let through broadcast, multicast, and our mac address
|
||||
// if ((memcmp(rxbuf, bcast_addr, 6) == 0) || (memcmp(rxbuf, this->linux_macaddr, 6) == 0) || rxbuf[0] & 0x01) {
|
||||
BX_DEBUG(("eth_linux: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11]));
|
||||
(*rxh)(rxarg, rxbuf, nbytes);
|
||||
// }
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user