VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetFlt/win/VBoxNetFltCommon-win.h@ 29667

Last change on this file since 29667 was 29643, checked in by vboxsync, 15 years ago

netflt/win: always set no-loopback flag for intnet->wire packets to prevent ndis misbehave

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.5 KB
Line 
1/* $Id: VBoxNetFltCommon-win.h 29643 2010-05-18 15:26:50Z vboxsync $ */
2/** @file
3 * VBoxNetFltCommon.h - Network Filter Driver (Host), Windows Specific Code. Common headeer with commonly used defines and decls
4 */
5
6/*
7 * Copyright (C) 2008 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17/*
18 * Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample.
19 * Copyright (c) 1993-1999, Microsoft Corporation
20 */
21
22#ifndef ___VBoxNetFltCommon_win_h___
23#define ___VBoxNetFltCommon_win_h___
24
25//#define NTSTRSAFE_LIB
26
27#ifdef DEBUG
28//# define DEBUG_NETFLT_PACKETS
29# ifndef DEBUG_misha
30# define DEBUG_NETFLT_NOASSERT
31# endif
32/* # define DEBUG_NETFLT_LOOPBACK */
33
34/* receive logic has several branches */
35/* the DEBUG_NETFLT_RECV* macros used to debug the ProtocolReceive callback
36 * which is typically not used in case the underlying miniport indicates the packets with NdisMIndicateReceivePacket
37 * the best way to debug the ProtocolReceive (which in turn has several branches) is to enable the DEBUG_NETFLT_RECV
38 * one by one in the below order, i.e.
39 * first DEBUG_NETFLT_RECV
40 * then DEBUG_NETFLT_RECV + DEBUG_NETFLT_RECV_NOPACKET */
41//# define DEBUG_NETFLT_RECV
42//# define DEBUG_NETFLT_RECV_NOPACKET
43//# define DEBUG_NETFLT_RECV_TRANSFERDATA
44#endif
45
46#define LOG_GROUP LOG_GROUP_NET_FLT_DRV
47
48#include <VBox/intnet.h>
49#include <VBox/log.h>
50#include <VBox/err.h>
51#include <VBox/version.h>
52#include <iprt/initterm.h>
53#include <iprt/assert.h>
54#include <iprt/spinlock.h>
55#include <iprt/semaphore.h>
56#include <iprt/process.h>
57#include <iprt/alloc.h>
58#include <iprt/alloca.h>
59#include <iprt/time.h>
60#include <iprt/net.h>
61
62RT_C_DECLS_BEGIN
63#include <ndis.h>
64RT_C_DECLS_END
65
66
67
68#define VBOXNETFLT_OS_SPECFIC 1
69
70#ifdef VBOX_NETFLT_ONDEMAND_BIND
71# define VBOXNETFLT_PROTOCOL_NAME L"VBoxNetFltPt"
72#else
73# ifndef VBOXNETADP
74# define VBOXNETFLT_PROTOCOL_NAME L"VBoxNetFlt"
75
76/** this is to support ioctl interface */
77# define LINKNAME_STRING L"\\DosDevices\\Global\\VBoxNetFlt"
78# define NTDEVICE_STRING L"\\Device\\VBoxNetFlt"
79# else
80# define LINKNAME_STRING L"\\DosDevices\\Global\\VBoxNetAdp"
81# define NTDEVICE_STRING L"\\Device\\VBoxNetAdp"
82# endif
83//# define VBOXNETFLT_WIN_IOCTL_INIT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_WRITE_ACCESS)
84//# define VBOXNETFLT_WIN_IOCTL_FINI CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_NEITHER, FILE_WRITE_ACCESS)
85#endif
86
87/** version
88 * NOTE: we are NOT using NDIS 5.1 features now, the code under "#ifdef NDIS51xxx" is not tested and may not work and should be removed soon */
89#ifdef NDIS51_MINIPORT
90# define VBOXNETFLT_MAJOR_NDIS_VERSION 5
91# define VBOXNETFLT_MINOR_NDIS_VERSION 1
92#else
93# define VBOXNETFLT_MAJOR_NDIS_VERSION 5
94# define VBOXNETFLT_MINOR_NDIS_VERSION 0
95#endif
96
97#ifdef NDIS51
98# define VBOXNETFLT_PROT_MAJOR_NDIS_VERSION 5
99# define VBOXNETFLT_PROT_MINOR_NDIS_VERSION 0
100#else
101# define VBOXNETFLT_PROT_MAJOR_NDIS_VERSION 5
102# define VBOXNETFLT_PROT_MINOR_NDIS_VERSION 0
103#endif
104
105/** advance declaration */
106typedef struct _ADAPT ADAPT, *PADAPT;
107
108typedef struct VBOXNETFLTINS *PVBOXNETFLTINS;
109
110/** configuration */
111
112/** received packets queue size. the queue is used when the driver is working in a pass-thru mode */
113#define MAX_RECEIVE_PACKET_ARRAY_SIZE 40
114
115/** Ndis Packet pool settings
116 * these are applied to both receive and send packet pools */
117#define MAX_PACKET_POOL_SIZE 0x0000FFFF
118#define MIN_PACKET_POOL_SIZE 0x000000FF
119
120/** packet queue size used when the driver is working in the "active" mode */
121#define PACKET_INFO_POOL_SIZE 0x0000FFFF
122
123#ifndef VBOXNETADP
124/** memory tag used for memory allocations
125 * (VBNF stands for VBox NetFlt) */
126# define MEM_TAG 'FNBV'
127#else
128/** memory tag used for memory allocations
129 * (VBNA stands for VBox NetAdp) */
130# define MEM_TAG 'ANBV'
131#endif
132
133/** receive and transmit Ndis buffer pool size */
134#define TX_BUFFER_POOL_SIZE 128
135#define RX_BUFFER_POOL_SIZE 128
136
137#define ETH_HEADER_SIZE 14
138
139#define PACKET_QUEUE_SG_SEGS_ALLOC 32
140
141#define VBOX_NETFLT_PACKET_HEADER_MATCH_SIZE 24
142
143#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
144# define VBOXNETFLT_PACKETMATCH_LENGTH (ETH_HEADER_SIZE + 2)
145#endif
146
147#ifdef VBOXNETADP
148#define VBOXNETADP_HEADER_SIZE 14
149#define VBOXNETADP_MAX_DATA_SIZE 1500
150#define VBOXNETADP_MAX_PACKET_SIZE VBOXNETADP_HEADER_SIZE + VBOXNETADP_MAX_DATA_SIZE
151#define VBOXNETADP_MIN_PACKET_SIZE 60
152#define VBOXNETADP_LINK_SPEED 1000000 //The unit of measurement is 100 bps, 100Mbps
153#define VBOXNETADP_MAX_LOOKAHEAD_SIZE VBOXNETADP_MAX_DATA_SIZE
154#define VBOXNETADP_VENDOR_ID 0x080027
155#define VBOXNETADP_VENDOR_DRIVER_VERSION 0x00010000
156#define VBOXNETADP_VENDOR_DESC "Sun"
157#define VBOXNETADP_MAX_MCAST_LIST 32
158#define VBOXNETADP_ETH_ADDRESS_LENGTH 6
159
160//#define VBOXNETADP_REPORT_DISCONNECTED
161#endif
162/* type defs */
163
164/** Flag specifying that the type of enqueued packet
165 * if set the info contains the PINTNETSG packet
166 * if clear the packet info contains the PNDIS_PACKET packet
167 * Typically the packet queue we are maintaining contains PNDIS_PACKETs only,
168 * however in case the underlying miniport indicates a packet with the NDIS_STATUS_RESOURCES status
169 * we MUST return the packet back to the miniport immediately
170 * this is why we are creating the INTNETSG, copying the ndis packet info there and enqueueing it */
171#define PACKET_SG 0x00000001
172
173/** the flag specifying that the packet source
174 * if set the packet comes from the host (upperlying protocol)
175 * if clear the packet comes from the wire (underlying miniport) */
176#define PACKET_SRC_HOST 0x00000002
177
178#ifndef VBOXNETFLT_NO_PACKET_QUEUE
179/** flag specifying the packet was originated by our driver
180 * i.e. we could use it on our needs and should not return it
181 * we are enqueueing "our" packets on ProtocolReceive call-back when
182 * Ndis does not give us a receive acket (the driver below us has called NdisM..IndicateReceive)
183 * this is supported for Ndis Packet only */
184#define PACKET_MINE 0x00000004
185
186/** flag passed to vboxNetFltWinQuEnqueuePacket specifying that the packet should be copied
187 * this is supported for Ndis Packet only */
188#define PACKET_COPY 0x00000008
189#endif
190
191/** packet queue element containing the packet info */
192typedef struct _PACKET_INFO
193{
194 /** list entry used for enqueueing the info */
195 LIST_ENTRY ListEntry;
196 /** pointer to the pool containing this packet info */
197 struct _PACKET_INFO_POOL * pPool;
198 /** flags describing the referenced packet. Contains PACKET_xxx flags (i.e. PACKET_SG, PACKET_SRC_HOST) */
199 uint32_t fFlags;
200 /** pointer to the packet this info represents */
201 PVOID pPacket;
202}PACKET_INFO, *PPACKET_INFO;
203
204/* paranoid check to make sure the elements in the packet info array are properly aligned */
205C_ASSERT((sizeof(PACKET_INFO) & (sizeof(PVOID) - 1)) == 0);
206
207/** represents the packet queue */
208typedef LIST_ENTRY PACKET_QUEUE, *PPACKET_QUEUE;
209
210/*
211 * we are using non-interlocked versions of LIST_ENTRY-related operations macros and synchronize
212 * access to the queue and its elements by aquiring/releasing a spinlock using Ndis[Acquire,Release]Spinlock
213 *
214 * we are NOT using interlocked versions of insert/remove head/tail list functions because we need to iterate though
215 * the queue elements as well as remove elements from the midle of the queue
216 *
217 * * @todo: it seems that we can switch to using interlocked versions of list-entry functions
218 * since we have removed all functionality (mentioned above, i.e. queue elements iteration, etc.) that might prevent us from doing this
219 */
220typedef struct _INTERLOCKED_PACKET_QUEUE
221{
222 /** queue */
223 PACKET_QUEUE Queue;
224 /** queue lock */
225 NDIS_SPIN_LOCK Lock;
226}INTERLOCKED_PACKET_QUEUE, *PINTERLOCKED_PACKET_QUEUE;
227
228typedef struct _SINGLE_LIST
229{
230 /** queue */
231 SINGLE_LIST_ENTRY Head;
232 /** pointer to the list tail. used to enqueue elements to the tail of the list */
233 PSINGLE_LIST_ENTRY pTail;
234} SINGLE_LIST, *PSINGLE_LIST;
235
236typedef struct _INTERLOCKED_SINGLE_LIST
237{
238 /** queue */
239 SINGLE_LIST List;
240 /** queue lock */
241 NDIS_SPIN_LOCK Lock;
242} INTERLOCKED_SINGLE_LIST, *PINTERLOCKED_SINGLE_LIST;
243
244/** packet info pool contains free packet info elements to be used for the packet queue
245 * we are using the pool mechanism to allocate packet queue elements
246 * the pool mechanism is pretty simple now, we are allocating a bunch of memory
247 * for maintaining PACKET_INFO_POOL_SIZE queue elements and just returning null when the pool is exhausted
248 * This mechanism seems to be enough for now since we are using PACKET_INFO_POOL_SIZE = 0xffff which is
249 * the maximum size of packets the ndis packet pool supports */
250typedef struct _PACKET_INFO_POOL
251{
252 /** free packet info queue */
253 INTERLOCKED_PACKET_QUEUE Queue;
254 /** memory bugger used by the pool */
255 PVOID pBuffer;
256}PACKET_INFO_POOL, *PPACKET_INFO_POOL;
257
258typedef enum VBOXNETDEVOPSTATE
259{
260 kVBoxNetDevOpState_InvalidValue = 0,
261 kVBoxNetDevOpState_Initializing,
262 kVBoxNetDevOpState_Initialized,
263 kVBoxNetDevOpState_Deinitializing,
264 kVBoxNetDevOpState_Deinitialized,
265
266} VBOXNETDEVOPSTATE;
267
268typedef enum VBOXADAPTSTATE
269{
270 /** The usual invalid state. */
271 kVBoxAdaptState_Invalid = 0,
272 /** Initialization. */
273 kVBoxAdaptState_Connecting,
274 /** Connected fuly functional state */
275 kVBoxAdaptState_Connected,
276 /** Disconnecting */
277 kVBoxAdaptState_Disconnecting,
278 /** Disconnected */
279 kVBoxAdaptState_Disconnected,
280} VBOXADAPTSTATE;
281
282/** structure used to maintain the state and reference count of the miniport and protocol */
283typedef struct _ADAPT_DEVICE
284{
285 /** initialize state */
286 VBOXNETDEVOPSTATE OpState;
287 /** ndis power state */
288 NDIS_DEVICE_POWER_STATE PowerState;
289 /** reference count */
290 uint32_t cReferences;
291/* NDIS_HANDLE hHandle; */
292} ADAPT_DEVICE, *PADAPT_DEVICE;
293
294/* packet filter processing mode constants */
295#define VBOXNETFLT_PFP_NETFLT 1
296#define VBOXNETFLT_PFP_PASSTHRU 2
297
298/** represents filter driver device context*/
299typedef struct _ADAPT
300{
301#ifndef VBOXNETADP
302 /** handle the lower miniport */
303 NDIS_HANDLE hBindingHandle;
304 /** Protocol's Device state */
305 ADAPT_DEVICE PTState;
306#endif
307#ifndef VBOX_NETFLT_ONDEMAND_BIND
308 /** NDIS Handle to for miniport up-calls */
309 NDIS_HANDLE hMiniportHandle;
310 /** miniport device state */
311 ADAPT_DEVICE MPState;
312 /** ndis packet pool used for receives */
313 NDIS_HANDLE hRecvPacketPoolHandle;
314 /** ndis buffer pool used for receives */
315 NDIS_HANDLE hRecvBufferPoolHandle;
316#ifndef VBOXNETADP
317 /** This is used to wrap a request coming down to us.
318 * This exploits the fact that requests are serialized down to us.*/
319 NDIS_REQUEST Request;
320 /** Ndis Request Bytes needed */
321 PULONG BytesNeeded;
322 /** Ndis Request Bytes Read or Written */
323 PULONG BytesReadOrWritten;
324#else
325 volatile ULONG cTxSuccess;
326 volatile ULONG cRxSuccess;
327 volatile ULONG cTxError;
328 volatile ULONG cRxError;
329#endif
330 /** driver bind adapter state. */
331 VBOXADAPTSTATE enmState;
332#ifndef VBOXNETADP
333 /** true if we should indicate the receive complete used by the ProtocolReceeive mechanism */
334 bool bIndicateRcvComplete;
335
336 /** TRUE iff a request is pending at the miniport below */
337 bool bOutstandingRequests;
338 /** TRUE iff a request is queued at this IM miniport*/
339 bool bQueuedRequest;
340 /** @todo join all boolean states to one field treated as flags bitmap */
341 /** true iff we are processing Set packet filter OID */
342 uint8_t fProcessingPacketFilter;
343 /** true iff the upper protocol filter cache was initialized */
344 bool bUpperProtSetFilterInitialized;
345 /** trus if the adapter is closing */
346 bool bClosingAdapter;
347 /** Pending transfer data packet queue (i.e. packets that were indicated as pending on NdisTransferData call */
348 INTERLOCKED_SINGLE_LIST TransferDataList;
349 /* mac options initialized on OID_GEN_MAC_OPTIONS */
350 ULONG fMacOptions;
351 /** For initializing the miniport edge */
352 NDIS_STRING DeviceName;
353 /** For blocking UnbindAdapter while an IM Init is in progress.*/
354 NDIS_EVENT MiniportInitEvent;
355 /** The last indicated media status */
356 NDIS_STATUS LastIndicatedStatus;
357 /** The latest suppressed media status */
358 NDIS_STATUS LatestUnIndicateStatus;
359 /** when working in the passthru mode the driver puts the received packets to this array
360 * instead of passing them up immediately
361 * we are flushing the packets on ProtocolReceiveComplete or when the underlying miniport
362 * indicates NDIS_STATUS_RESOURCES or when this array is full */
363 PNDIS_PACKET aReceivedPackets[MAX_RECEIVE_PACKET_ARRAY_SIZE];
364 /** number of packets in the aReceivedPackets array*/
365 ULONG cReceivedPacketCount;
366 /** packet filter flags set by the upper protocols */
367 ULONG fUpperProtocolSetFilter;
368 /** packet filter flags set by the upper protocols */
369 ULONG fSetFilterBuffer;
370 /** packet filter flags set by us */
371 ULONG fOurSetFilter;
372#endif /* !VBOXNETADP */
373#endif /* !VBOX_NETFLT_ONDEMAND_BIND */
374
375#ifndef VBOXNETADP
376#if defined(DEBUG_NETFLT_LOOPBACK) || !defined(VBOX_LOOPBACK_USEFLAGS)
377 /** used for maintaining the pending send packets for handling packet loopback */
378 INTERLOCKED_SINGLE_LIST SendPacketQueue;
379#endif
380 /** used for serializing calls to the NdisRequest in the vboxNetFltWinSynchNdisRequest */
381 RTSEMFASTMUTEX hSynchRequestMutex;
382 /** event used to synchronize with the Ndis Request completion in the vboxNetFltWinSynchNdisRequest */
383 KEVENT hSynchCompletionEvent;
384 /** status of the Ndis Request initiated by the vboxNetFltWinSynchNdisRequest */
385 NDIS_STATUS volatile fSynchCompletionStatus;
386 /** pointer to the Ndis Request being executed by the vboxNetFltWinSynchNdisRequest */
387 PNDIS_REQUEST volatile pSynchRequest;
388 /** ndis packet pool used for sends */
389 NDIS_HANDLE hSendPacketPoolHandle;
390 /** ndis buffer pool used for sends */
391 NDIS_HANDLE hSendBufferPoolHandle;
392 /** open/close adapter status.
393 * Since ndis adapter open and close requests may complete assynchronously,
394 * we are using event mechanism to wait for open/close completion
395 * the status field is being set by the completion call-back */
396 NDIS_STATUS Status;
397 /** open/close adaptor completion event */
398 NDIS_EVENT hEvent;
399 /** medium we are attached to */
400 NDIS_MEDIUM Medium;
401// /** physical medium we are attached to */
402// NDIS_PHYSICAL_MEDIUM PhMedium;
403 /** True - When the miniport or protocol is transitioning from a D0 to Standby (>D0) State
404 * False - At all other times, - Flag is cleared after a transition to D0 */
405 BOOLEAN bStandingBy;
406#endif
407} ADAPT, *PADAPT;
408
409typedef struct _PACKET_QUEUE_WORKER
410{
411 /** this event is used to initiate a packet queue worker thread kill */
412 KEVENT KillEvent;
413 /** this event is used to notify a worker thread that the packets are added to the queue */
414 KEVENT NotifyEvent;
415 /** pointer to the packet queue worker thread object */
416 PKTHREAD pThread;
417 /** pointer to the SG used by the packet queue for IntNet receive notifications */
418 PINTNETSG pSG;
419 /** Packet queue */
420 INTERLOCKED_PACKET_QUEUE PacketQueue;
421 /** Packet info pool, i.e. the pool for the packet queue elements */
422 PACKET_INFO_POOL PacketInfoPool;
423} PACKET_QUEUE_WORKER, *PPACKET_QUEUE_WORKER;
424
425/** Protocol reserved part of a sent packet that is allocated by us. */
426typedef struct _SEND_RSVD
427{
428 /** original packet receiver from the upperlying protocol
429 * can be null if the packet was originated by intnet */
430 PNDIS_PACKET pOriginalPkt;
431 /** pointer to the buffer to be freed on send completion
432 * can be null if no buffer is to be freed */
433 PVOID pBufToFree;
434#if !defined(VBOX_LOOPBACK_USEFLAGS) || defined(DEBUG_NETFLT_PACKETS)
435 SINGLE_LIST_ENTRY ListEntry;
436 /* true if the packet is from IntNet */
437 bool bFromIntNet;
438#endif
439} SEND_RSVD, *PSEND_RSVD;
440
441/** represents the data stored in the protocol recerved field of ndis packet on NdisTransferData processing*/
442typedef struct _TRANSFERDATA_RSVD
443{
444 /** next packet in a list */
445 SINGLE_LIST_ENTRY ListEntry;
446 /* packet buffer start */
447 PNDIS_BUFFER pOriginalBuffer;
448} TRANSFERDATA_RSVD, *PTRANSFERDATA_RSVD;
449
450/** Miniport reserved part of a received packet that is allocated by
451 * us. Note that this should fit into the MiniportReserved space
452 * in an NDIS_PACKET. */
453typedef struct _RECV_RSVD
454{
455 /** original packet receiver from the underling miniport
456 * can be null if the packet was originated by intnet */
457 PNDIS_PACKET pOriginalPkt;
458 /** pointer to the buffer to be freed on receive completion
459 * can be null if no buffer is to be freed */
460 PVOID pBufToFree;
461} RECV_RSVD, *PRECV_RSVD;
462
463#ifndef VBOX_NETFLT_ONDEMAND_BIND
464
465C_ASSERT(sizeof(RECV_RSVD) <= sizeof(((PNDIS_PACKET)0)->MiniportReserved));
466C_ASSERT(sizeof(TRANSFERDATA_RSVD) <= PROTOCOL_RESERVED_SIZE_IN_PACKET);
467#endif
468
469C_ASSERT(sizeof(NDIS_DEVICE_POWER_STATE) == sizeof(uint32_t));
470C_ASSERT(sizeof(UINT) == sizeof(uint32_t));
471
472#define NDIS_FLAGS_SKIP_LOOPBACK_W2K 0x400
473
474#include "../VBoxNetFltInternal.h"
475#include "VBoxNetFlt-win.h"
476#ifndef VBOXNETADP
477#include "VBoxNetFltPt-win.h"
478#endif
479#ifndef VBOX_NETFLT_ONDEMAND_BIND
480# include "VBoxNetFltMp-win.h"
481#endif
482
483#ifdef DEBUG_NETFLT_NOASSERT
484# ifdef Assert
485# undef Assert
486# endif
487
488# define Assert(_expr) do {} while (0)
489#endif /* #ifdef DEBUG_NETFLT_NOASSERT */
490
491#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette