Bochs/bochs/iodev/eth_win32.cc
Stanislav Shwartsman 5873b26a82 Speed up compilation process.
bochs.h already not include iodev.h which reduces compilation dependences for almost all cpu and fpu files, now cpu files will not be recompiled if iodev includes was changed
2004-06-19 15:20:15 +00:00

360 lines
12 KiB
C++

/////////////////////////////////////////////////////////////////////////
// $Id: eth_win32.cc,v 1.18 2004-06-19 15:20:11 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// 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
//
// eth_win32.cc - packet mover for win32
// All win32 coding by Don Becker <x-odus@iname.com>
// with patches from various sources
//
// Various networking docs:
// http://www.graphcomp.com/info/rfc/
// rfc0826: arp
// rfc0903: rarp
//
// For ethernet support under win32 to work, you must install WinPCap.
// Download it from http://netgroup-serv.polito.it/winpcap
// Define BX_PLUGGABLE in files that can be compiled into plugins. For
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
// is used to know when we are exporting symbols and when we are importing.
#define BX_PLUGGABLE
#include "iodev.h"
#if BX_NE2K_SUPPORT
// windows.h included by bochs.h
#define LOG_THIS bx_devices.pluginNE2kDevice->
#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020
#define Packet_ALIGNMENT sizeof(int)
#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1))
typedef int bpf_int32;
typedef u_int bpf_u_int32;
/*
* The instruction encondings.
*/
/* instruction classes */
#define BPF_CLASS(code) ((code) & 0x07)
#define BPF_LD 0x00
#define BPF_LDX 0x01
#define BPF_ST 0x02
#define BPF_STX 0x03
#define BPF_ALU 0x04
#define BPF_JMP 0x05
#define BPF_RET 0x06
#define BPF_MISC 0x07
/* ld/ldx fields */
#define BPF_SIZE(code) ((code) & 0x18)
#define BPF_W 0x00
#define BPF_H 0x08
#define BPF_B 0x10
#define BPF_MODE(code) ((code) & 0xe0)
#define BPF_IMM 0x00
#define BPF_ABS 0x20
#define BPF_IND 0x40
#define BPF_MEM 0x60
#define BPF_LEN 0x80
#define BPF_MSH 0xa0
/* alu/jmp fields */
#define BPF_OP(code) ((code) & 0xf0)
#define BPF_ADD 0x00
#define BPF_SUB 0x10
#define BPF_MUL 0x20
#define BPF_DIV 0x30
#define BPF_OR 0x40
#define BPF_AND 0x50
#define BPF_LSH 0x60
#define BPF_RSH 0x70
#define BPF_NEG 0x80
#define BPF_JA 0x00
#define BPF_JEQ 0x10
#define BPF_JGT 0x20
#define BPF_JGE 0x30
#define BPF_JSET 0x40
#define BPF_SRC(code) ((code) & 0x08)
#define BPF_K 0x00
#define BPF_X 0x08
/* ret - BPF_K and BPF_X also apply */
#define BPF_RVAL(code) ((code) & 0x18)
#define BPF_A 0x10
/* misc */
#define BPF_MISCOP(code) ((code) & 0xf8)
#define BPF_TAX 0x00
#define BPF_TXA 0x80
#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
/*
* The instruction data structure.
*/
struct bpf_insn {
u_short code;
u_char jt;
u_char jf;
bpf_int32 k;
};
struct bpf_program {
u_int bf_len;
struct bpf_insn *bf_insns;
};
struct bpf_hdr {
struct timeval bh_tstamp; /* time stamp */
UINT bh_caplen; /* length of captured portion */
UINT bh_datalen; /* original length of packet */
USHORT bh_hdrlen; /* length of bpf header (this struct
plus alignment padding) */
};
#define MAX_LINK_NAME_LENGTH 64
// Why don't these definitions come from including winpcap.h or something?
// -Bryce
typedef struct _ADAPTER {
HANDLE hFile;
TCHAR SymbolicLink[MAX_LINK_NAME_LENGTH];
int NumWrites;
HANDLE ReadEvent;
UINT ReadTimeOut; // WARNING: maybe invalid before winpcap 2.2
} ADAPTER, *LPADAPTER;
typedef struct _PACKET {
HANDLE hEvent;
OVERLAPPED OverLapped;
PVOID Buffer;
UINT Length;
UINT ulBytesReceived;
BOOLEAN bIoComplete;
} PACKET, *LPPACKET;
HINSTANCE hPacket;
LPADAPTER lpAdapter = 0;
LPPACKET pkSend;
LPPACKET pkRecv;
char buffer[256000];
DWORD dwVersion, dwMajorVersion;
char AdapterList[10][1024];
char cMacAddr[6];
void *rx_Arg;
char netdev[512];
BOOL IsNT = FALSE;
eth_rx_handler_t rx_handler;
LPADAPTER (*PacketOpenAdapter) (LPTSTR);
VOID (*PacketCloseAdapter) (LPADAPTER);
BOOLEAN (*PacketSetHwFilter) (LPADAPTER, ULONG);
BOOLEAN (*PacketSetBpf) (LPADAPTER, struct bpf_program *);
BOOLEAN (*PacketGetAdapterNames) (PTSTR, PULONG);
BOOLEAN (*PacketSendPacket) (LPADAPTER, LPPACKET, BOOLEAN);
BOOLEAN (*PacketReceivePacket) (LPADAPTER, LPPACKET, BOOLEAN);
BOOLEAN (*PacketSetBuff) (LPADAPTER, int);
BOOLEAN (*PacketSetReadTimeout) (LPADAPTER, int);
LPPACKET (*PacketAllocatePacket) (void);
VOID (*PacketInitPacket) (LPPACKET, PVOID, UINT);
VOID (*PacketFreePacket) (LPPACKET);
// template filter for a unicast mac address and all
// multicast/broadcast frames
static const struct bpf_insn 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 the class. This is private to this module
//
class bx_win32_pktmover_c : public eth_pktmover_c {
public:
bx_win32_pktmover_c(const char *netif, const char *macaddr,
eth_rx_handler_t rxh, void *rxarg);
void sendpkt(void *buf, unsigned io_len);
private:
struct bpf_insn filter[8];
int rx_timer_index;
static void rx_timer_handler(void *);
};
//
// Define the static class that registers the derived pktmover class,
// and allocates one on request.
//
class bx_win32_locator_c : public eth_locator_c {
public:
bx_win32_locator_c(void) : eth_locator_c("win32") {}
protected:
eth_pktmover_c *allocate(const char *netif, const char *macaddr, eth_rx_handler_t rxh, void *rxarg) {
return (new bx_win32_pktmover_c(netif, macaddr, rxh, rxarg));
}
} bx_win32_match;
//
// Define the methods for the bx_win32_pktmover derived class
//
// the constructor
bx_win32_pktmover_c::bx_win32_pktmover_c(const char *netif,
const char *macaddr,
eth_rx_handler_t rxh,
void *rxarg)
{
// Open Packet Driver Here.
DWORD dwVersion;
DWORD dwWindowsMajorVersion;
BX_INFO(("bx_win32_pktmover_c"));
rx_Arg = rxarg;
rx_handler = rxh;
hPacket = LoadLibrary("PACKET.DLL");
memcpy(cMacAddr, macaddr, 6);
if(hPacket) {
PacketOpenAdapter = (LPADAPTER (*)(LPTSTR)) GetProcAddress(hPacket, "PacketOpenAdapter");
PacketCloseAdapter = (VOID (*)(LPADAPTER)) GetProcAddress(hPacket, "PacketCloseAdapter");
PacketSetHwFilter = (BOOLEAN (*)(LPADAPTER, ULONG)) GetProcAddress(hPacket, "PacketSetHwFilter");
PacketSetBpf = (BOOLEAN (*)(LPADAPTER, struct bpf_program *)) GetProcAddress(hPacket, "PacketSetBpf");
PacketGetAdapterNames = (BOOLEAN (*)(PTSTR, PULONG)) GetProcAddress(hPacket, "PacketGetAdapterNames");
PacketSendPacket = (BOOLEAN (*)(LPADAPTER, LPPACKET, BOOLEAN)) GetProcAddress(hPacket, "PacketSendPacket");
PacketReceivePacket = (BOOLEAN (*)(LPADAPTER, LPPACKET, BOOLEAN)) GetProcAddress(hPacket, "PacketReceivePacket");
PacketSetBuff = (BOOLEAN (*)(LPADAPTER, int)) GetProcAddress(hPacket, "PacketSetBuff");
PacketSetReadTimeout = (BOOLEAN (*)(LPADAPTER, int)) GetProcAddress(hPacket, "PacketSetReadTimeout");
PacketAllocatePacket = (LPPACKET (*)(void)) GetProcAddress(hPacket, "PacketAllocatePacket");
PacketInitPacket = (VOID (*)(LPPACKET, PVOID, UINT)) GetProcAddress(hPacket, "PacketInitPacket");
PacketFreePacket = (VOID (*)(LPPACKET)) GetProcAddress(hPacket, "PacketFreePacket");
} else {
BX_PANIC(("Could not load WPCap Drivers for ethernet support!"));
}
memset(&netdev, 0, sizeof(netdev));
dwVersion=GetVersion();
dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
if (!(dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4))
{ // Windows NT/2k
int nLen = MultiByteToWideChar(CP_ACP, 0, netif, -1, NULL, 0);
MultiByteToWideChar(CP_ACP, 0, netif, -1, (WCHAR *)netdev, nLen);
IsNT = TRUE;
} else { // Win9x
strcpy(netdev, netif);
}
lpAdapter = PacketOpenAdapter(netdev);
if(!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE)) {
BX_PANIC(("Could not open adapter for ethernet reception"));
return;
}
PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_PROMISCUOUS);
/* The code below sets a BPF mac address filter
that seems to really kill performance, for now
im just using code to filter, and it works
better
*/
// 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);
// bp.bf_len = 8;
// bp.bf_insns = &this->filter[0];
// if(!PacketSetBpf(lpAdapter, &bp)) {
// BX_PANIC(("Could not set mac address BPF filter"));
// }
PacketSetBuff(lpAdapter, 512000);
PacketSetReadTimeout(lpAdapter, -1);
if((pkSend = PacketAllocatePacket()) == NULL) {
BX_PANIC(("Could not allocate a send packet"));
}
if((pkRecv = PacketAllocatePacket()) == NULL) {
BX_PANIC(("Could not allocate a recv packet"));
}
rx_timer_index = bx_pc_system.register_timer(this, this->rx_timer_handler, 10000, 1, 1, "eth_win32");
}
void
bx_win32_pktmover_c::sendpkt(void *buf, unsigned io_len)
{
// SendPacket Here.
//fprintf(stderr, "[ETH-WIN32] Sending Packet: size=%i\n", io_len);
PacketInitPacket(pkSend, (char *)buf, io_len);
if(!PacketSendPacket(lpAdapter, pkSend, TRUE)) {
fprintf(stderr, "[ETH-WIN32] Error sending packet: %lu\n", GetLastError());
}
}
void bx_win32_pktmover_c::rx_timer_handler (void *this_ptr)
{
// Recieve Packet ????
char *pBuf;
unsigned char *pPacket;
unsigned int iOffset = 0;
struct bpf_hdr *hdr;
int pktlen;
static unsigned char bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
PacketInitPacket(pkRecv, (char *)buffer, 256000);
//fprintf(stderr, "[ETH-WIN32] poll packet\n");
if (WaitForSingleObject(lpAdapter->ReadEvent,0) == WAIT_OBJECT_0 || IsNT) {
PacketReceivePacket(lpAdapter, pkRecv, TRUE);
pBuf = (char *)pkRecv->Buffer;
iOffset = 0;
while(iOffset < pkRecv->ulBytesReceived)
{
hdr = (struct bpf_hdr *)(pBuf + iOffset);
pPacket = (unsigned char *)(pBuf + iOffset + hdr->bh_hdrlen);
if (memcmp(pPacket + 6, cMacAddr, 6) != 0) // src field != ours
{
if(memcmp(pPacket, cMacAddr, 6) == 0 || memcmp(pPacket, bcast_addr, 6) == 0)
{
//fprintf(stderr, "[ETH-WIN32] RX packet: size=%i, dst=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, src=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", hdr->bh_caplen, pPacket[0], pPacket[1], pPacket[2], pPacket[3], pPacket[4], pPacket[5], pPacket[6], pPacket[7], pPacket[8], pPacket[9], pPacket[10], pPacket[11]);
pktlen = hdr->bh_caplen;
if (pktlen < 60) pktlen = 60;
(*rx_handler)(rx_Arg, pPacket, pktlen);
}
}
iOffset = Packet_WORDALIGN(iOffset + (hdr->bh_hdrlen + hdr->bh_caplen));
}
}
}
#endif /* if BX_NE2K_SUPPORT */