1 /////////////////////////////////////////////////////////////////////////
2 // $Id: eth_win32.cc,v 1.28 2008/12/11 18:01:56 vruppert Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2001 MandrakeSoft S.A.
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 // eth_win32.cc - packet mover for win32
28 // All win32 coding by Don Becker <x-odus@iname.com>
29 // with patches from various sources
31 // Various networking docs:
32 // http://www.graphcomp.com/info/rfc/
36 // For ethernet support under win32 to work, you must install WinPCap.
37 // Download it from http://netgroup-serv.polito.it/winpcap
39 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
40 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
41 // is used to know when we are exporting symbols and when we are importing.
44 #define NO_DEVICE_INCLUDES
47 #if BX_NETWORKING && defined(ETH_WIN32)
51 // windows.h included by bochs.h
52 #define LOG_THIS bx_devices.pluginNE2kDevice->
54 #define BX_ETH_WIN32_LOGGING 0
56 #define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020
57 #define Packet_ALIGNMENT sizeof(int)
58 #define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1))
60 typedef int bpf_int32
;
61 typedef u_int bpf_u_int32
;
64 * The instruction encondings.
67 /* instruction classes */
69 #define BPF_CLASS(code) ((code) & 0x07)
80 #define BPF_SIZE(code) ((code) & 0x18)
84 #define BPF_MODE(code) ((code) & 0xe0)
93 #define BPF_OP(code) ((code) & 0xf0)
107 #define BPF_JSET 0x40
108 #define BPF_SRC(code) ((code) & 0x08)
112 /* ret - BPF_K and BPF_X also apply */
113 #define BPF_RVAL(code) ((code) & 0x18)
117 #define BPF_MISCOP(code) ((code) & 0xf8)
121 #define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
122 #define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
125 * The instruction data structure.
136 struct bpf_insn
*bf_insns
;
140 struct timeval bh_tstamp
; /* time stamp */
141 UINT bh_caplen
; /* length of captured portion */
142 UINT bh_datalen
; /* original length of packet */
143 USHORT bh_hdrlen
; /* length of bpf header (this struct
144 plus alignment padding) */
147 #define MAX_LINK_NAME_LENGTH 64
149 // Why don't these definitions come from including winpcap.h or something?
151 typedef struct _ADAPTER
{
153 TCHAR SymbolicLink
[MAX_LINK_NAME_LENGTH
];
156 UINT ReadTimeOut
; // WARNING: maybe invalid before winpcap 2.2
157 } ADAPTER
, *LPADAPTER
;
159 typedef struct _PACKET
{
161 OVERLAPPED OverLapped
;
164 UINT ulBytesReceived
;
169 LPADAPTER lpAdapter
= 0;
173 DWORD dwVersion
, dwMajorVersion
;
174 char AdapterList
[10][1024];
180 eth_rx_handler_t rx_handler
;
182 LPADAPTER (*PacketOpenAdapter
) (LPTSTR
);
183 VOID (*PacketCloseAdapter
) (LPADAPTER
);
184 BOOLEAN (*PacketSetHwFilter
) (LPADAPTER
, ULONG
);
185 BOOLEAN (*PacketSetBpf
) (LPADAPTER
, struct bpf_program
*);
186 BOOLEAN (*PacketGetAdapterNames
) (PTSTR
, PULONG
);
187 BOOLEAN (*PacketSendPacket
) (LPADAPTER
, LPPACKET
, BOOLEAN
);
188 BOOLEAN (*PacketReceivePacket
) (LPADAPTER
, LPPACKET
, BOOLEAN
);
189 BOOLEAN (*PacketSetBuff
) (LPADAPTER
, int);
190 BOOLEAN (*PacketSetReadTimeout
) (LPADAPTER
, int);
191 LPPACKET (*PacketAllocatePacket
) (void);
192 VOID (*PacketInitPacket
) (LPPACKET
, PVOID
, UINT
);
193 VOID (*PacketFreePacket
) (LPPACKET
);
195 // template filter for a unicast mac address and all
196 // multicast/broadcast frames
197 static const struct bpf_insn macfilter
[] = {
198 BPF_STMT(BPF_LD
|BPF_W
|BPF_ABS
, 2),
199 BPF_JUMP(BPF_JMP
|BPF_JEQ
|BPF_K
, 0xaaaaaaaa, 0, 2),
200 BPF_STMT(BPF_LD
|BPF_H
|BPF_ABS
, 0),
201 BPF_JUMP(BPF_JMP
|BPF_JEQ
|BPF_K
, 0x0000aaaa, 2, 0),
202 BPF_STMT(BPF_LD
|BPF_B
|BPF_ABS
, 0),
203 BPF_JUMP(BPF_JMP
|BPF_JSET
|BPF_K
, 0x01, 0, 1),
204 BPF_STMT(BPF_RET
, 1514),
205 BPF_STMT(BPF_RET
, 0),
209 // Define the class. This is private to this module
211 class bx_win32_pktmover_c
: public eth_pktmover_c
{
213 bx_win32_pktmover_c(const char *netif
, const char *macaddr
,
214 eth_rx_handler_t rxh
, void *rxarg
, const char *script
);
215 void sendpkt(void *buf
, unsigned io_len
);
217 struct bpf_insn filter
[8];
219 static void rx_timer_handler(void *);
221 #if BX_ETH_WIN32_LOGGING
227 // Define the static class that registers the derived pktmover class,
228 // and allocates one on request.
230 class bx_win32_locator_c
: public eth_locator_c
{
232 bx_win32_locator_c(void) : eth_locator_c("win32") {}
234 eth_pktmover_c
*allocate(const char *netif
, const char *macaddr
,
235 eth_rx_handler_t rxh
,
236 void *rxarg
, const char *script
) {
237 return (new bx_win32_pktmover_c(netif
, macaddr
, rxh
, rxarg
, script
));
242 // Define the methods for the bx_win32_pktmover derived class
246 bx_win32_pktmover_c::bx_win32_pktmover_c(
247 const char *netif
, const char *macaddr
,
248 eth_rx_handler_t rxh
, void *rxarg
, const char *script
)
250 // Open Packet Driver Here.
252 DWORD dwWindowsMajorVersion
;
254 BX_INFO(("bx_win32_pktmover_c"));
258 hPacket
= LoadLibrary("PACKET.DLL");
259 memcpy(cMacAddr
, macaddr
, 6);
261 PacketOpenAdapter
= (LPADAPTER (*)(LPTSTR
)) GetProcAddress(hPacket
, "PacketOpenAdapter");
262 PacketCloseAdapter
= (VOID (*)(LPADAPTER
)) GetProcAddress(hPacket
, "PacketCloseAdapter");
263 PacketSetHwFilter
= (BOOLEAN (*)(LPADAPTER
, ULONG
)) GetProcAddress(hPacket
, "PacketSetHwFilter");
264 PacketSetBpf
= (BOOLEAN (*)(LPADAPTER
, struct bpf_program
*)) GetProcAddress(hPacket
, "PacketSetBpf");
265 PacketGetAdapterNames
= (BOOLEAN (*)(PTSTR
, PULONG
)) GetProcAddress(hPacket
, "PacketGetAdapterNames");
266 PacketSendPacket
= (BOOLEAN (*)(LPADAPTER
, LPPACKET
, BOOLEAN
)) GetProcAddress(hPacket
, "PacketSendPacket");
267 PacketReceivePacket
= (BOOLEAN (*)(LPADAPTER
, LPPACKET
, BOOLEAN
)) GetProcAddress(hPacket
, "PacketReceivePacket");
268 PacketSetBuff
= (BOOLEAN (*)(LPADAPTER
, int)) GetProcAddress(hPacket
, "PacketSetBuff");
269 PacketSetReadTimeout
= (BOOLEAN (*)(LPADAPTER
, int)) GetProcAddress(hPacket
, "PacketSetReadTimeout");
270 PacketAllocatePacket
= (LPPACKET (*)(void)) GetProcAddress(hPacket
, "PacketAllocatePacket");
271 PacketInitPacket
= (VOID (*)(LPPACKET
, PVOID
, UINT
)) GetProcAddress(hPacket
, "PacketInitPacket");
272 PacketFreePacket
= (VOID (*)(LPPACKET
)) GetProcAddress(hPacket
, "PacketFreePacket");
274 BX_PANIC(("Could not load WPCap Drivers for ethernet support!"));
277 memset(&netdev
, 0, sizeof(netdev
));
278 dwVersion
=GetVersion();
279 dwWindowsMajorVersion
= (DWORD
)(LOBYTE(LOWORD(dwVersion
)));
280 if (!(dwVersion
>= 0x80000000 && dwWindowsMajorVersion
>= 4))
282 int nLen
= MultiByteToWideChar(CP_ACP
, 0, netif
, -1, NULL
, 0);
283 MultiByteToWideChar(CP_ACP
, 0, netif
, -1, (WCHAR
*)netdev
, nLen
);
286 strcpy(netdev
, netif
);
289 lpAdapter
= PacketOpenAdapter(netdev
);
290 if (!lpAdapter
|| (lpAdapter
->hFile
== INVALID_HANDLE_VALUE
)) {
291 BX_PANIC(("Could not open adapter for ethernet reception"));
294 PacketSetHwFilter(lpAdapter
, NDIS_PACKET_TYPE_PROMISCUOUS
);
296 /* The code below sets a BPF mac address filter
297 that seems to really kill performance, for now
298 im just using code to filter, and it works
302 // memcpy(&this->filter, macfilter, sizeof(macfilter));
303 // this->filter[1].k = (macaddr[2] & 0xff) << 24 | (macaddr[3] & 0xff) << 16 | (macaddr[4] & 0xff) << 8 | (macaddr[5] & 0xff);
304 // this->filter[3].k = (macaddr[0] & 0xff) << 8 | (macaddr[1] & 0xff);
306 // bp.bf_insns = &this->filter[0];
307 // if (!PacketSetBpf(lpAdapter, &bp)) {
308 // BX_PANIC(("Could not set mac address BPF filter"));
311 PacketSetBuff(lpAdapter
, 512000);
312 PacketSetReadTimeout(lpAdapter
, -1);
314 if ((pkSend
= PacketAllocatePacket()) == NULL
) {
315 BX_PANIC(("Could not allocate a send packet"));
318 if ((pkRecv
= PacketAllocatePacket()) == NULL
) {
319 BX_PANIC(("Could not allocate a recv packet"));
322 bx_pc_system
.register_timer(this, this->rx_timer_handler
, 10000, 1, 1, "eth_win32");
324 #if BX_ETH_WIN32_LOGGING
325 pktlog_txt
= fopen ("ne2k-pktlog.txt", "wb");
326 if (!pktlog_txt
) BX_PANIC (("ne2k-pktlog.txt failed"));
327 fprintf (pktlog_txt
, "win32 packetmover readable log file\n");
328 fprintf (pktlog_txt
, "host adapter = %s\n", netif
);
329 fprintf (pktlog_txt
, "guest MAC address = ");
332 fprintf (pktlog_txt
, "%02x%s", 0xff & macaddr
[i
], i
<5?":" : "\n");
333 fprintf (pktlog_txt
, "--\n");
339 bx_win32_pktmover_c::sendpkt(void *buf
, unsigned io_len
)
341 #if BX_ETH_WIN32_LOGGING
342 fprintf (pktlog_txt
, "a packet from guest to host, length %u\n", io_len
);
343 Bit8u
*charbuf
= (Bit8u
*)buf
;
345 for (n
=0; n
<io_len
; n
++) {
346 if (((n
% 16) == 0) && n
>0)
347 fprintf (pktlog_txt
, "\n");
348 fprintf (pktlog_txt
, "%02x ", (unsigned)charbuf
[n
]);
350 fprintf (pktlog_txt
, "\n--\n");
355 PacketInitPacket(pkSend
, (char *)buf
, io_len
);
357 if (!PacketSendPacket(lpAdapter
, pkSend
, TRUE
)) {
358 fprintf(stderr
, "[ETH-WIN32] Error sending packet: %lu\n", GetLastError());
362 void bx_win32_pktmover_c::rx_timer_handler (void *this_ptr
)
364 bx_win32_pktmover_c
*class_ptr
= (bx_win32_pktmover_c
*) this_ptr
;
366 class_ptr
->rx_timer();
369 void bx_win32_pktmover_c::rx_timer(void)
371 // Recieve Packet ????
373 unsigned char *pPacket
;
374 unsigned int iOffset
= 0;
378 PacketInitPacket(pkRecv
, (char *)buffer
, 256000);
379 if (WaitForSingleObject(lpAdapter
->ReadEvent
,0) == WAIT_OBJECT_0
|| IsNT
) {
380 PacketReceivePacket(lpAdapter
, pkRecv
, TRUE
);
381 pBuf
= (char *)pkRecv
->Buffer
;
383 while(iOffset
< pkRecv
->ulBytesReceived
)
385 hdr
= (struct bpf_hdr
*)(pBuf
+ iOffset
);
386 pPacket
= (unsigned char *)(pBuf
+ iOffset
+ hdr
->bh_hdrlen
);
387 if (memcmp(pPacket
+ 6, cMacAddr
, 6) != 0) // src field != ours
389 if(memcmp(pPacket
, cMacAddr
, 6) == 0 || memcmp(pPacket
, broadcast_macaddr
, 6) == 0)
391 pktlen
= hdr
->bh_caplen
;
392 if (pktlen
< 60) pktlen
= 60;
393 #if BX_ETH_WIN32_LOGGING
394 fprintf (pktlog_txt
, "a packet from host to guest, length %u\n", pktlen
);
395 Bit8u
*charbuf
= (Bit8u
*)pPacket
;
397 for (n
=0; n
<pktlen
; n
++) {
398 if (((n
% 16) == 0) && n
>0)
399 fprintf (pktlog_txt
, "\n");
400 fprintf (pktlog_txt
, "%02x ", (unsigned)charbuf
[n
]);
402 fprintf (pktlog_txt
, "\n--\n");
405 (*rx_handler
)(rx_Arg
, pPacket
, pktlen
);
408 iOffset
= Packet_WORDALIGN(iOffset
+ (hdr
->bh_hdrlen
+ hdr
->bh_caplen
));
412 #endif /* if BX_NETWORKING && defined ETH_WIN32 */