- 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:
Bryce Denney 2001-06-26 07:46:42 +00:00
parent d7b6442ad6
commit 75c87e2113
4 changed files with 348 additions and 38 deletions

107
bochs/configure vendored
View File

@ -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

View File

@ -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)

View File

@ -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
View 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