2
* TAP-Win32 -- A kernel driver to provide virtual tap device
3
* functionality on Windows. Originally derived
4
* from the CIPE-Win32 project by Damion K. Wilson,
5
* with extensive modifications by James Yonan.
7
* All source code which derives from the CIPE-Win32 project is
8
* Copyright (C) Damion K. Wilson, 2003, and is released under the
9
* GPL version 2 (see below).
11
* All other source code is Copyright (C) James Yonan, 2003-2004,
12
* and is released under the GPL version 2 (see below).
14
* This program is free software; you can redistribute it and/or modify
15
* it under the terms of the GNU General Public License as published by
16
* the Free Software Foundation; either version 2 of the License, or
17
* (at your option) any later version.
19
* This program is distributed in the hope that it will be useful,
20
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
* GNU General Public License for more details.
24
* You should have received a copy of the GNU General Public License
25
* along with this program (see the file COPYING included with this
26
* distribution); if not, write to the Free Software Foundation, Inc.,
27
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30
//======================================================
31
// This driver is designed to work on Win 2000 or higher
32
// versions of Windows.
34
// It is SMP-safe and handles NDIS 5 power management.
36
// By default we operate as a "tap" virtual ethernet
37
// 802.3 interface, but we can emulate a "tun"
38
// interface (point-to-point IPv4) through the
39
// TAP_IOCTL_CONFIG_POINT_TO_POINT ioctl.
40
//======================================================
42
#define NDIS_MINIPORT_DRIVER
43
#define BINARY_COMPATIBLE 0
44
#define NDIS50_MINIPORT 1
50
#include <ntstrsafe.h>
52
#include "constants.h"
59
#include "prototypes.h"
66
//========================================================
68
//========================================================
69
PDRIVER_DISPATCH g_DispatchHook[IRP_MJ_MAXIMUM_FUNCTION + 1];
70
NDIS_MINIPORT_CHARACTERISTICS g_Properties;
71
PDRIVER_OBJECT g_TapDriverObject = NULL;
72
char g_DispatchFunctionsHooked = 0;
73
NDIS_HANDLE g_NdisWrapperHandle;
74
MACADDR g_MAC = { 0, 0, 0, 0, 0, 0 };
77
((a)->m_TapIsRunning && (a)->m_InterfaceIsRunning)
79
#define INCREMENT_STAT(s) ++(s)
81
UINT g_SupportedOIDList[] = {
82
OID_GEN_HARDWARE_STATUS,
83
OID_GEN_MEDIA_SUPPORTED,
85
OID_GEN_MAXIMUM_LOOKAHEAD,
88
OID_GEN_TRANSMIT_BLOCK_SIZE,
89
OID_GEN_RECEIVE_BLOCK_SIZE,
90
OID_GEN_VENDOR_DESCRIPTION,
91
OID_GEN_DRIVER_VERSION,
96
OID_802_3_PERMANENT_ADDRESS,
97
OID_802_3_CURRENT_ADDRESS,
98
OID_GEN_RCV_NO_BUFFER,
99
OID_802_3_RCV_ERROR_ALIGNMENT,
100
OID_802_3_XMIT_ONE_COLLISION,
101
OID_802_3_XMIT_MORE_COLLISIONS,
102
OID_802_3_MULTICAST_LIST,
103
OID_802_3_MAXIMUM_LIST_SIZE,
105
OID_GEN_CURRENT_LOOKAHEAD,
106
OID_GEN_CURRENT_PACKET_FILTER,
107
OID_GEN_PROTOCOL_OPTIONS,
108
OID_GEN_MAXIMUM_TOTAL_SIZE,
109
OID_GEN_TRANSMIT_BUFFER_SPACE,
110
OID_GEN_RECEIVE_BUFFER_SPACE,
111
OID_GEN_MAXIMUM_FRAME_SIZE,
112
OID_GEN_VENDOR_DRIVER_VERSION,
113
OID_GEN_MAXIMUM_SEND_PACKETS,
114
OID_GEN_MEDIA_CONNECT_STATUS,
115
OID_GEN_SUPPORTED_LIST
118
//============================================================
120
//============================================================
121
#pragma NDIS_INIT_FUNCTION (DriverEntry)
124
DriverEntry (IN PDRIVER_OBJECT p_DriverObject,
125
IN PUNICODE_STRING p_RegistryPath)
127
NDIS_STATUS l_Status = NDIS_STATUS_FAILURE;
129
//==============================
130
// Allocate debugging text space
131
//==============================
136
//========================================================
137
// Notify NDIS that a new miniport driver is initializing.
138
//========================================================
140
NdisMInitializeWrapper (&g_NdisWrapperHandle,
141
g_TapDriverObject = p_DriverObject,
142
p_RegistryPath, NULL);
144
//=======================================
145
// Set and register miniport entry points
146
//=======================================
148
NdisZeroMemory (&g_Properties, sizeof (g_Properties));
150
g_Properties.MajorNdisVersion = TAP_NDIS_MAJOR_VERSION;
151
g_Properties.MinorNdisVersion = TAP_NDIS_MINOR_VERSION;
152
g_Properties.InitializeHandler = AdapterCreate;
153
g_Properties.HaltHandler = AdapterHalt;
154
g_Properties.ResetHandler = AdapterReset;
155
g_Properties.TransferDataHandler = AdapterReceive;
156
g_Properties.SendHandler = AdapterTransmit;
157
g_Properties.QueryInformationHandler = AdapterQuery;
158
g_Properties.SetInformationHandler = AdapterModify;
159
g_Properties.DisableInterruptHandler = NULL;
160
g_Properties.EnableInterruptHandler = NULL;
161
g_Properties.HandleInterruptHandler = NULL;
162
g_Properties.ISRHandler = NULL;
163
g_Properties.ReconfigureHandler = NULL;
164
g_Properties.CheckForHangHandler = NULL;
165
g_Properties.ReturnPacketHandler = NULL;
166
g_Properties.SendPacketsHandler = NULL;
167
g_Properties.AllocateCompleteHandler = NULL;
169
g_Properties.CoCreateVcHandler = NULL;
170
g_Properties.CoDeleteVcHandler = NULL;
171
g_Properties.CoActivateVcHandler = NULL;
172
g_Properties.CoDeactivateVcHandler = NULL;
173
g_Properties.CoSendPacketsHandler = NULL;
174
g_Properties.CoRequestHandler = NULL;
176
#ifndef ENABLE_RANDOM_MAC
177
ConvertMacInfo (g_MAC, TAP_MAC_ROOT_ADDRESS, strlen (TAP_MAC_ROOT_ADDRESS));
181
NdisMRegisterMiniport (g_NdisWrapperHandle, &g_Properties,
182
sizeof (g_Properties)))
184
case NDIS_STATUS_SUCCESS:
186
DEBUGP (("[TAP] version [%d.%d] registered miniport successfully\n",
187
TAP_DRIVER_MAJOR_VERSION, TAP_DRIVER_MINOR_VERSION));
191
case NDIS_STATUS_BAD_CHARACTERISTICS:
193
DEBUGP (("[TAP] Miniport characteristics were badly defined\n"));
194
NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
198
case NDIS_STATUS_BAD_VERSION:
201
(("[TAP] NDIS Version is wrong for the given characteristics\n"));
202
NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
206
case NDIS_STATUS_RESOURCES:
208
DEBUGP (("[TAP] Insufficient resources\n"));
209
NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
213
case NDIS_STATUS_FAILURE:
215
DEBUGP (("[TAP] Unknown fatal registration error\n"));
216
NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
221
//==============================================================
222
// Save original NDIS dispatch functions and override with ours
223
//==============================================================
224
HookDispatchFunctions ();
229
//==========================================================
230
// Adapter Initialization
231
//==========================================================
232
NDIS_STATUS AdapterCreate
233
(OUT PNDIS_STATUS p_ErrorStatus,
234
OUT PUINT p_MediaIndex,
235
IN PNDIS_MEDIUM p_Media,
236
IN UINT p_MediaCount,
237
IN NDIS_HANDLE p_AdapterHandle,
238
IN NDIS_HANDLE p_ConfigurationHandle)
240
NDIS_MEDIUM l_PreferredMedium = NdisMedium802_3; // Ethernet
241
TapAdapterPointer l_Adapter = NULL;
242
ANSI_STRING l_AdapterString;
243
#ifndef ENABLE_RANDOM_MAC
249
//====================================
250
// Make sure adapter type is supported
251
//====================================
254
l_Index < p_MediaCount && p_Media[l_Index] != l_PreferredMedium;
257
if (l_Index == p_MediaCount)
259
DEBUGP (("[TAP] Unsupported adapter type [wanted: %d]\n",
261
return NDIS_STATUS_UNSUPPORTED_MEDIA;
264
*p_MediaIndex = l_Index;
266
//=========================================
267
// Allocate memory for TapAdapter structure
268
//=========================================
270
status = NdisAllocateMemoryWithTag ((PVOID *) & l_Adapter,
271
sizeof (TapAdapter), '1PAT');
273
if (status != NDIS_STATUS_SUCCESS || l_Adapter == NULL)
275
DEBUGP (("[TAP] Couldn't allocate adapter memory\n"));
276
return NDIS_STATUS_RESOURCES;
279
//==========================================
280
// Inform the NDIS library about significant
281
// features of our virtual NIC.
282
//==========================================
286
(NDIS_HANDLE) l_Adapter,
288
NDIS_ATTRIBUTE_DESERIALIZE
289
| NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT
290
| NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT
291
| NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
292
NdisInterfaceInternal);
294
//=====================================
295
// Initialize simple Adapter parameters
296
//=====================================
298
NdisZeroMemory (l_Adapter, sizeof (TapAdapter));
300
l_Adapter->m_Lookahead = DEFAULT_PACKET_LOOKAHEAD;
301
l_Adapter->m_Medium = l_PreferredMedium;
302
l_Adapter->m_DeviceState = '?';
304
//====================================================
305
// Register a shutdown handler which will be called
306
// on system restart/shutdown to halt our virtual NIC.
307
//====================================================
309
NdisMRegisterAdapterShutdownHandler (p_AdapterHandle, l_Adapter,
311
l_Adapter->m_MiniportAdapterHandle = p_AdapterHandle;
312
l_Adapter->m_RegisteredAdapterShutdownHandler = TRUE;
314
//===========================================================
315
// Allocate spinlocks used to control access to
316
// shared data structures by concurrent threads of execution.
317
// QueueLock is used to lock the packet queue used
318
// for the TAP-Win32 NIC -> User Space packet flow direction.
319
// This code is designed to be fully SMP-safe.
320
//===========================================================
322
NdisAllocateSpinLock (&l_Adapter->m_Lock);
323
NdisAllocateSpinLock (&l_Adapter->m_QueueLock);
324
l_Adapter->m_AllocatedSpinlocks = TRUE;
326
//====================================
327
// Allocate and construct adapter name
328
//====================================
330
l_AdapterString.MaximumLength =
331
((PNDIS_MINIPORT_BLOCK) p_AdapterHandle)->MiniportName.Length + 5;
333
if ((l_Adapter->m_Name = l_AdapterString.Buffer =
334
ExAllocatePoolWithTag (NonPagedPool,
335
l_AdapterString.MaximumLength,
338
AdapterFreeResources (l_Adapter);
339
return NDIS_STATUS_RESOURCES;
342
RtlUnicodeStringToAnsiString (
344
&((PNDIS_MINIPORT_BLOCK) p_AdapterHandle)->MiniportName,
346
l_AdapterString.Buffer[l_AdapterString.Length] = 0;
348
//==================================
349
// Store and update MAC address info
350
//==================================
352
#ifdef ENABLE_RANDOM_MAC
353
GenerateRandomMac (g_MAC, l_Adapter->m_Name);
354
COPY_MAC (l_Adapter->m_MAC, g_MAC);
356
COPY_MAC (l_Adapter->m_MAC, g_MAC);
361
++(*((unsigned short *) l_MAC));
367
DEBUGP (("[%s] Using MAC %x:%x:%x:%x:%x:%x\n",
369
l_Adapter->m_MAC[0], l_Adapter->m_MAC[1], l_Adapter->m_MAC[2],
370
l_Adapter->m_MAC[3], l_Adapter->m_MAC[4], l_Adapter->m_MAC[5]));
377
for (i = 0; i < sizeof (MACADDR); ++i)
378
l_Adapter->m_MAC_Broadcast[i] = 0xFF;
381
//============================================
382
// Get parameters from registry which were set
383
// in the adapter advanced properties dialog.
384
//============================================
387
NDIS_HANDLE configHandle;
388
NDIS_CONFIGURATION_PARAMETER *parm;
390
// set defaults in case our registry query fails
391
l_Adapter->m_MTU = DEFAULT_PACKET_LOOKAHEAD;
392
l_Adapter->m_MediaStateAlwaysConnected = FALSE;
393
l_Adapter->m_MediaState = FALSE;
395
NdisOpenConfiguration (&status, &configHandle, p_ConfigurationHandle);
396
if (status == NDIS_STATUS_SUCCESS)
398
/* Read MTU setting from registry */
400
NDIS_STRING key = NDIS_STRING_CONST("MTU");
401
NdisReadConfiguration (&status, &parm, configHandle,
402
&key, NdisParameterInteger);
403
if (status == NDIS_STATUS_SUCCESS)
405
if (parm->ParameterType == NdisParameterInteger)
407
int mtu = parm->ParameterData.IntegerData;
408
if (mtu < MINIMUM_MTU)
410
if (mtu > MAXIMUM_MTU)
412
l_Adapter->m_MTU = mtu;
417
/* Read Media Status setting from registry */
419
NDIS_STRING key = NDIS_STRING_CONST("MediaStatus");
420
NdisReadConfiguration (&status, &parm, configHandle,
421
&key, NdisParameterInteger);
422
if (status == NDIS_STATUS_SUCCESS)
424
if (parm->ParameterType == NdisParameterInteger)
426
if (parm->ParameterData.IntegerData)
428
l_Adapter->m_MediaStateAlwaysConnected = TRUE;
429
l_Adapter->m_MediaState = TRUE;
435
NdisCloseConfiguration (configHandle);
438
DEBUGP (("[%s] MTU=%d\n", l_Adapter->m_Name, l_Adapter->m_MTU));
441
//====================================
442
// Initialize TAP device
443
//====================================
445
NDIS_STATUS tap_status;
446
tap_status = CreateTapDevice (l_Adapter);
447
if (tap_status != NDIS_STATUS_SUCCESS)
449
AdapterFreeResources (l_Adapter);
454
l_Adapter->m_InterfaceIsRunning = TRUE;
455
return NDIS_STATUS_SUCCESS;
459
AdapterHalt (IN NDIS_HANDLE p_AdapterContext)
461
TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
463
DEBUGP (("[%s] is being halted\n", l_Adapter->m_Name));
464
l_Adapter->m_InterfaceIsRunning = FALSE;
465
NOTE_ERROR (l_Adapter);
468
if (l_Adapter->m_TapDevice)
469
DestroyTapDevice (l_Adapter);
472
DEBUGP (("[%s] Freeing Resources\n", l_Adapter->m_Name));
473
AdapterFreeResources (l_Adapter);
477
AdapterFreeResources (TapAdapterPointer p_Adapter)
479
MYASSERT (!p_Adapter->m_CalledAdapterFreeResources);
480
p_Adapter->m_CalledAdapterFreeResources = TRUE;
482
if (p_Adapter->m_Name)
484
ExFreePool (p_Adapter->m_Name);
485
p_Adapter->m_Name = NULL;
488
if (p_Adapter->m_AllocatedSpinlocks)
490
NdisFreeSpinLock (&p_Adapter->m_Lock);
491
NdisFreeSpinLock (&p_Adapter->m_QueueLock);
492
p_Adapter->m_AllocatedSpinlocks = FALSE;
495
if (p_Adapter->m_RegisteredAdapterShutdownHandler)
497
NdisMDeregisterAdapterShutdownHandler
498
(p_Adapter->m_MiniportAdapterHandle);
499
p_Adapter->m_RegisteredAdapterShutdownHandler = FALSE;
502
NdisZeroMemory ((PVOID) p_Adapter, sizeof (TapAdapter));
503
NdisFreeMemory ((PVOID) p_Adapter, sizeof (TapAdapter), 0);
505
//==============================
506
// Free debugging text space
507
//==============================
513
//========================================================================
514
// Tap Device Initialization
515
//========================================================================
517
CreateTapDevice (TapAdapterPointer p_Adapter)
519
unsigned short l_AdapterLength =
520
(unsigned short) strlen (p_Adapter->m_Name);
521
ANSI_STRING l_TapString, l_LinkString;
522
TapExtensionPointer l_Extension;
523
UNICODE_STRING l_TapUnicode;
524
BOOLEAN l_FreeTapUnicode = FALSE;
525
NTSTATUS l_Status, l_Return = NDIS_STATUS_SUCCESS;
527
l_LinkString.Buffer = NULL;
529
l_TapString.MaximumLength = l_LinkString.MaximumLength =
530
l_AdapterLength + strlen (TAPSUFFIX);
532
DEBUGP (("[TAP] version [%d.%d] creating tap device: %s\n",
533
TAP_DRIVER_MAJOR_VERSION,
534
TAP_DRIVER_MINOR_VERSION,
537
//==================================
538
// Allocate pool for TAP device name
539
//==================================
541
if ((p_Adapter->m_TapName = l_TapString.Buffer =
542
ExAllocatePoolWithTag (NonPagedPool,
543
l_TapString.MaximumLength,
546
DEBUGP (("[%s] couldn't alloc TAP name buffer\n", p_Adapter->m_Name));
547
l_Return = NDIS_STATUS_RESOURCES;
551
//================================================
552
// Allocate pool for TAP symbolic link name buffer
553
//================================================
555
if ((l_LinkString.Buffer =
556
ExAllocatePoolWithTag (NonPagedPool,
557
l_LinkString.MaximumLength,
560
DEBUGP (("[%s] couldn't alloc TAP symbolic link name buffer\n",
562
l_Return = NDIS_STATUS_RESOURCES;
566
//=======================================================
567
// Modify for tap device name ("\Device\TAPn.tap")
568
//=======================================================
569
NdisMoveMemory (l_TapString.Buffer, p_Adapter->m_Name, l_AdapterLength);
570
NdisMoveMemory (l_TapString.Buffer + l_AdapterLength, TAPSUFFIX,
571
strlen (TAPSUFFIX) + 1);
572
NdisMoveMemory (l_TapString.Buffer, "\\Device", 7); // For Win2K problem
573
l_TapString.Length = l_AdapterLength + strlen (TAPSUFFIX);
575
DEBUGP (("TAP DEV NAME: '%s'\n", l_TapString.Buffer));
577
//=======================================================
578
// And modify for tap link name ("\??\TAPn.tap")
579
//=======================================================
580
NdisMoveMemory (l_LinkString.Buffer, l_TapString.Buffer,
582
NdisMoveMemory (l_LinkString.Buffer, USERDEVICEDIR, strlen (USERDEVICEDIR));
585
(l_LinkString.Buffer + strlen (USERDEVICEDIR),
586
l_LinkString.Buffer + strlen (SYSDEVICEDIR),
587
l_TapString.Length - strlen (SYSDEVICEDIR));
589
l_LinkString.Buffer[l_LinkString.Length =
590
l_TapString.Length - (strlen (SYSDEVICEDIR) -
591
strlen (USERDEVICEDIR))] = 0;
593
DEBUGP (("TAP LINK NAME: '%s'\n", l_LinkString.Buffer));
595
//==================================================
596
// Create new tap device and associate with adapter
597
//==================================================
598
if (RtlAnsiStringToUnicodeString (&l_TapUnicode, &l_TapString, TRUE) !=
601
DEBUGP (("[%s] couldn't alloc TAP unicode name buffer\n",
603
l_Return = NDIS_STATUS_RESOURCES;
606
l_FreeTapUnicode = TRUE;
608
l_Status = IoCreateDevice
610
sizeof (TapExtension),
612
FILE_DEVICE_PHYSICAL_NETCARD | 0x8000,
613
0, FALSE, &(p_Adapter->m_TapDevice));
615
if (l_Status != STATUS_SUCCESS)
617
DEBUGP (("[%s] couldn't be created\n", p_Adapter->m_TapName));
618
l_Return = NDIS_STATUS_RESOURCES;
622
if (RtlAnsiStringToUnicodeString
623
(&p_Adapter->m_UnicodeLinkName, &l_LinkString, TRUE)
627
(("[%s] Couldn't allocate unicode string for symbolic link name\n",
629
l_Return = NDIS_STATUS_RESOURCES;
632
p_Adapter->m_CreatedUnicodeLinkName = TRUE;
634
//==================================================
635
// Associate symbolic link with new device
636
//==================================================
638
(IoCreateSymbolicLink (&p_Adapter->m_UnicodeLinkName, &l_TapUnicode)))
640
DEBUGP (("[%s] symbolic link couldn't be created\n",
641
l_LinkString.Buffer));
642
l_Return = NDIS_STATUS_RESOURCES;
645
p_Adapter->m_CreatedSymbolLink = TRUE;
647
//==================================================
648
// Initialize device extension (basically a kind
649
// of private data area containing our state info).
650
//==================================================
653
((TapExtensionPointer) p_Adapter->m_TapDevice->DeviceExtension);
655
NdisZeroMemory (l_Extension, sizeof (TapExtension));
657
p_Adapter->m_DeviceExtensionIsAccessible = TRUE;
659
l_Extension->m_Adapter = p_Adapter;
660
l_Extension->m_halt = FALSE;
662
//========================================================
663
// Initialize Packet and IRP queues.
665
// The packet queue is used to buffer data which has been
666
// "transmitted" by the virtual NIC, before user space
667
// has had a chance to read it.
669
// The IRP queue is used to buffer pending I/O requests
670
// from userspace, i.e. read requests on the TAP device
671
// waiting for the system to "transmit" something through
674
// Basically, packets in the packet queue are used
675
// to satisfy IRP requests in the IRP queue.
677
// All accesses to packet or IRP queues should be
678
// bracketed by the QueueLock spinlock,
679
// in order to be SMP-safe.
680
//========================================================
682
l_Extension->m_PacketQueue = QueueInit (PACKET_QUEUE_SIZE);
683
l_Extension->m_IrpQueue = QueueInit (IRP_QUEUE_SIZE);
685
if (!l_Extension->m_PacketQueue
686
|| !l_Extension->m_IrpQueue)
688
DEBUGP (("[%s] couldn't alloc TAP queues\n", p_Adapter->m_Name));
689
l_Return = NDIS_STATUS_RESOURCES;
693
//========================
694
// Finalize initialization
695
//========================
697
p_Adapter->m_TapIsRunning = TRUE;
699
/* instead of DO_BUFFERED_IO */
700
p_Adapter->m_TapDevice->Flags |= DO_DIRECT_IO;
702
p_Adapter->m_TapDevice->Flags &= ~DO_DEVICE_INITIALIZING;
704
DEBUGP (("[%s] successfully created TAP device [%s]\n", p_Adapter->m_Name,
705
p_Adapter->m_TapName));
708
if (l_FreeTapUnicode)
709
RtlFreeUnicodeString (&l_TapUnicode);
710
if (l_LinkString.Buffer)
711
ExFreePool (l_LinkString.Buffer);
713
if (l_Return != NDIS_STATUS_SUCCESS)
714
TapDeviceFreeResources (p_Adapter);
720
DestroyTapDevice (TapAdapterPointer p_Adapter)
722
TapExtensionPointer l_Extension =
723
(TapExtensionPointer) p_Adapter->m_TapDevice->DeviceExtension;
725
DEBUGP (("[%s] Destroying tap device\n", p_Adapter->m_TapName));
727
//======================================
728
// Let clients know we are shutting down
729
//======================================
730
p_Adapter->m_TapIsRunning = FALSE;
731
p_Adapter->m_TapOpens = 0;
732
l_Extension->m_halt = TRUE;
734
//====================================
735
// Give clients time to finish up.
736
// Note that we must be running at IRQL
737
// < DISPATCH_LEVEL in order to call
739
//====================================
742
//================================
743
// Exhaust IRP and packet queues
744
//================================
745
FlushQueues (p_Adapter);
747
TapDeviceFreeResources (p_Adapter);
751
TapDeviceFreeResources (TapAdapterPointer p_Adapter)
753
MYASSERT (p_Adapter);
754
MYASSERT (!p_Adapter->m_CalledTapDeviceFreeResources);
755
p_Adapter->m_CalledTapDeviceFreeResources = TRUE;
757
if (p_Adapter->m_DeviceExtensionIsAccessible)
759
TapExtensionPointer l_Extension;
761
MYASSERT (p_Adapter->m_TapDevice);
762
l_Extension = (TapExtensionPointer)
763
p_Adapter->m_TapDevice->DeviceExtension;
764
MYASSERT (l_Extension);
766
if (l_Extension->m_PacketQueue)
767
QueueFree (l_Extension->m_PacketQueue);
768
if (l_Extension->m_IrpQueue)
769
QueueFree (l_Extension->m_IrpQueue);
771
p_Adapter->m_DeviceExtensionIsAccessible = FALSE;
774
if (p_Adapter->m_CreatedSymbolLink)
775
IoDeleteSymbolicLink (&p_Adapter->m_UnicodeLinkName);
777
if (p_Adapter->m_CreatedUnicodeLinkName)
778
RtlFreeUnicodeString (&p_Adapter->m_UnicodeLinkName);
780
//==========================================================
781
// According to DDK docs, the device is not actually deleted
782
// until its reference count falls to zero. That means we
783
// still need to gracefully fail TapDeviceHook requests
784
// after this point, otherwise ugly things would happen if
785
// the device was disabled (e.g. in the network connections
786
// control panel) while a userspace app still held an open
787
// file handle to it.
788
//==========================================================
790
if (p_Adapter->m_TapDevice)
792
IoDeleteDevice (p_Adapter->m_TapDevice);
793
p_Adapter->m_TapDevice = NULL;
796
if (p_Adapter->m_TapName)
798
ExFreePool (p_Adapter->m_TapName);
799
p_Adapter->m_TapName = NULL;
803
//========================================================
805
//========================================================
807
AdapterReset (OUT PBOOLEAN p_AddressingReset, IN NDIS_HANDLE p_AdapterContext)
809
TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
810
DEBUGP (("[%s] is resetting\n", l_Adapter->m_Name));
811
return NDIS_STATUS_SUCCESS;
814
NDIS_STATUS AdapterReceive
815
(OUT PNDIS_PACKET p_Packet,
816
OUT PUINT p_Transferred,
817
IN NDIS_HANDLE p_AdapterContext,
818
IN NDIS_HANDLE p_ReceiveContext, IN UINT p_Offset, IN UINT p_ToTransfer)
820
return NDIS_STATUS_SUCCESS;
823
//==============================================================
824
// Adapter Option Query/Modification
825
//==============================================================
826
NDIS_STATUS AdapterQuery
827
(IN NDIS_HANDLE p_AdapterContext,
830
IN ULONG p_BufferLength,
831
OUT PULONG p_BytesWritten, OUT PULONG p_BytesNeeded)
833
TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
834
TapAdapterQuery l_Query, *l_QueryPtr = &l_Query;
835
NDIS_STATUS l_Status = NDIS_STATUS_SUCCESS;
836
UINT l_QueryLength = 4;
838
NdisZeroMemory (&l_Query, sizeof (l_Query));
839
NdisAcquireSpinLock (&l_Adapter->m_Lock);
843
//===================================================================
844
// Vendor & Driver version Info
845
//===================================================================
846
case OID_GEN_VENDOR_DESCRIPTION:
847
l_QueryPtr = (TapAdapterQueryPointer) PRODUCT_STRING;
848
l_QueryLength = strlen (PRODUCT_STRING) + 1;
851
case OID_GEN_VENDOR_ID:
852
l_Query.m_Long = 0xffffff;
855
case OID_GEN_DRIVER_VERSION:
857
(((USHORT) TAP_NDIS_MAJOR_VERSION) << 8 | (USHORT)
858
TAP_NDIS_MINOR_VERSION);
859
l_QueryLength = sizeof (unsigned short);
862
case OID_GEN_VENDOR_DRIVER_VERSION:
864
(((USHORT) TAP_DRIVER_MAJOR_VERSION) << 8 | (USHORT)
865
TAP_DRIVER_MINOR_VERSION);
868
//=================================================================
870
//=================================================================
871
case OID_GEN_RCV_NO_BUFFER:
875
case OID_802_3_RCV_ERROR_ALIGNMENT:
879
case OID_802_3_XMIT_ONE_COLLISION:
883
case OID_802_3_XMIT_MORE_COLLISIONS:
887
case OID_GEN_XMIT_OK:
888
l_Query.m_Long = l_Adapter->m_Tx;
892
l_Query.m_Long = l_Adapter->m_Rx;
895
case OID_GEN_XMIT_ERROR:
896
l_Query.m_Long = l_Adapter->m_TxErr;
899
case OID_GEN_RCV_ERROR:
900
l_Query.m_Long = l_Adapter->m_RxErr;
903
//===================================================================
904
// Device & Protocol Options
905
//===================================================================
906
case OID_GEN_SUPPORTED_LIST:
907
l_QueryPtr = (TapAdapterQueryPointer) g_SupportedOIDList;
908
l_QueryLength = sizeof (g_SupportedOIDList);
911
case OID_GEN_MAC_OPTIONS:
912
// This MUST be here !!!
913
l_Query.m_Long = (NDIS_MAC_OPTION_RECEIVE_SERIALIZED
914
| NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA
915
| NDIS_MAC_OPTION_NO_LOOPBACK
916
| NDIS_MAC_OPTION_TRANSFERS_NOT_PEND);
920
case OID_GEN_CURRENT_PACKET_FILTER:
922
(NDIS_PACKET_TYPE_ALL_LOCAL |
923
NDIS_PACKET_TYPE_BROADCAST |
924
NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_FUNCTIONAL);
928
case OID_GEN_PROTOCOL_OPTIONS:
932
//==================================================================
934
//==================================================================
935
case OID_GEN_MEDIA_CONNECT_STATUS:
936
l_Query.m_Long = l_Adapter->m_MediaState
937
? NdisMediaStateConnected : NdisMediaStateDisconnected;
940
case OID_GEN_HARDWARE_STATUS:
941
l_Query.m_HardwareStatus = NdisHardwareStatusReady;
942
l_QueryLength = sizeof (NDIS_HARDWARE_STATUS);
945
case OID_GEN_MEDIA_SUPPORTED:
946
case OID_GEN_MEDIA_IN_USE:
947
l_Query.m_Medium = l_Adapter->m_Medium;
948
l_QueryLength = sizeof (NDIS_MEDIUM);
951
case OID_GEN_LINK_SPEED:
952
l_Query.m_Long = 100000;
955
case OID_802_3_MULTICAST_LIST:
959
case OID_802_3_PERMANENT_ADDRESS:
960
case OID_802_3_CURRENT_ADDRESS:
961
COPY_MAC (l_Query.m_MacAddress, l_Adapter->m_MAC);
962
l_QueryLength = sizeof (MACADDR);
965
//==================================================================
967
//==================================================================
969
case OID_GEN_MAXIMUM_SEND_PACKETS:
973
case OID_802_3_MAXIMUM_LIST_SIZE:
977
case OID_GEN_CURRENT_LOOKAHEAD:
978
l_Query.m_Long = l_Adapter->m_Lookahead;
981
case OID_GEN_MAXIMUM_LOOKAHEAD:
982
case OID_GEN_MAXIMUM_TOTAL_SIZE:
983
case OID_GEN_RECEIVE_BUFFER_SPACE:
984
case OID_GEN_RECEIVE_BLOCK_SIZE:
985
l_Query.m_Long = DEFAULT_PACKET_LOOKAHEAD;
988
case OID_GEN_MAXIMUM_FRAME_SIZE:
989
case OID_GEN_TRANSMIT_BLOCK_SIZE:
990
case OID_GEN_TRANSMIT_BUFFER_SPACE:
991
l_Query.m_Long = l_Adapter->m_MTU;
994
case OID_PNP_CAPABILITIES:
997
PNDIS_PNP_CAPABILITIES pPNPCapabilities;
998
PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct;
1000
if (p_BufferLength >= sizeof (NDIS_PNP_CAPABILITIES))
1002
pPNPCapabilities = (PNDIS_PNP_CAPABILITIES) (p_Buffer);
1005
// Setting up the buffer to be returned
1006
// to the Protocol above the Passthru miniport
1008
pPMstruct = &pPNPCapabilities->WakeUpCapabilities;
1009
pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
1010
pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;
1011
pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
1013
l_QueryLength = sizeof (NDIS_PNP_CAPABILITIES);
1017
case OID_PNP_QUERY_POWER:
1020
// Required OIDs that we don't support
1022
case OID_GEN_SUPPORTED_GUIDS:
1023
case OID_GEN_MEDIA_CAPABILITIES:
1024
case OID_GEN_PHYSICAL_MEDIUM:
1025
case OID_TCP_TASK_OFFLOAD:
1026
case OID_FFP_SUPPORT:
1027
l_Status = NDIS_STATUS_INVALID_OID;
1030
// Optional stats OIDs
1032
case OID_GEN_DIRECTED_BYTES_XMIT:
1033
case OID_GEN_DIRECTED_FRAMES_XMIT:
1034
case OID_GEN_MULTICAST_BYTES_XMIT:
1035
case OID_GEN_MULTICAST_FRAMES_XMIT:
1036
case OID_GEN_BROADCAST_BYTES_XMIT:
1037
case OID_GEN_BROADCAST_FRAMES_XMIT:
1038
case OID_GEN_DIRECTED_BYTES_RCV:
1039
case OID_GEN_DIRECTED_FRAMES_RCV:
1040
case OID_GEN_MULTICAST_BYTES_RCV:
1041
case OID_GEN_MULTICAST_FRAMES_RCV:
1042
case OID_GEN_BROADCAST_BYTES_RCV:
1043
case OID_GEN_BROADCAST_FRAMES_RCV:
1044
l_Status = NDIS_STATUS_INVALID_OID;
1047
//===================================================================
1049
//===================================================================
1051
DEBUGP (("[%s] Unhandled OID %lx\n", l_Adapter->m_Name, p_OID));
1052
l_Status = NDIS_STATUS_INVALID_OID;
1056
if (l_Status != NDIS_STATUS_SUCCESS)
1058
else if (l_QueryLength > p_BufferLength)
1060
l_Status = NDIS_STATUS_INVALID_LENGTH;
1061
*p_BytesNeeded = l_QueryLength;
1064
NdisMoveMemory (p_Buffer, (PVOID) l_QueryPtr,
1065
(*p_BytesWritten = l_QueryLength));
1067
NdisReleaseSpinLock (&l_Adapter->m_Lock);
1072
NDIS_STATUS AdapterModify
1073
(IN NDIS_HANDLE p_AdapterContext,
1076
IN ULONG p_BufferLength,
1077
OUT PULONG p_BytesRead,
1078
OUT PULONG p_BytesNeeded)
1080
TapAdapterQueryPointer l_Query = (TapAdapterQueryPointer) p_Buffer;
1081
TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
1082
NDIS_STATUS l_Status = NDIS_STATUS_INVALID_OID;
1085
NdisAcquireSpinLock (&l_Adapter->m_Lock);
1089
//==================================================================
1091
//==================================================================
1092
case OID_802_3_MULTICAST_LIST:
1093
DEBUGP (("[%s] Setting [OID_802_3_MAXIMUM_LIST_SIZE]\n",
1094
l_Adapter->m_Name));
1095
l_Status = NDIS_STATUS_SUCCESS;
1098
case OID_GEN_CURRENT_PACKET_FILTER:
1099
l_Status = NDIS_STATUS_INVALID_LENGTH;
1102
if (p_BufferLength >= sizeof (ULONG))
1105
(("[%s] Setting [OID_GEN_CURRENT_PACKET_FILTER] to [0x%02lx]\n",
1106
l_Adapter->m_Name, l_Query->m_Long));
1107
l_Status = NDIS_STATUS_SUCCESS;
1108
*p_BytesRead = sizeof (ULONG);
1113
case OID_GEN_CURRENT_LOOKAHEAD:
1114
if (p_BufferLength < sizeof (ULONG))
1116
l_Status = NDIS_STATUS_INVALID_LENGTH;
1119
else if (l_Query->m_Long > DEFAULT_PACKET_LOOKAHEAD
1120
|| l_Query->m_Long <= 0)
1121
l_Status = NDIS_STATUS_INVALID_DATA;
1124
DEBUGP (("[%s] Setting [OID_GEN_CURRENT_LOOKAHEAD] to [%d]\n",
1125
l_Adapter->m_Name, l_Query->m_Long));
1126
l_Adapter->m_Lookahead = l_Query->m_Long;
1127
l_Status = NDIS_STATUS_SUCCESS;
1128
*p_BytesRead = sizeof (ULONG);
1133
case OID_GEN_NETWORK_LAYER_ADDRESSES:
1134
l_Status = NDIS_STATUS_SUCCESS;
1135
*p_BytesRead = *p_BytesNeeded = 0;
1138
case OID_GEN_TRANSPORT_HEADER_OFFSET:
1139
l_Status = NDIS_STATUS_SUCCESS;
1140
*p_BytesRead = *p_BytesNeeded = 0;
1143
case OID_PNP_SET_POWER:
1146
NDIS_DEVICE_POWER_STATE NewDeviceState;
1148
NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE) p_Buffer);
1150
switch (NewDeviceState)
1152
case NdisDeviceStateD0:
1153
l_Adapter->m_DeviceState = '0';
1155
case NdisDeviceStateD1:
1156
l_Adapter->m_DeviceState = '1';
1158
case NdisDeviceStateD2:
1159
l_Adapter->m_DeviceState = '2';
1161
case NdisDeviceStateD3:
1162
l_Adapter->m_DeviceState = '3';
1165
l_Adapter->m_DeviceState = '?';
1169
l_Status = NDIS_STATUS_FAILURE;
1172
// Check for invalid length
1174
if (p_BufferLength < sizeof (NDIS_DEVICE_POWER_STATE))
1176
l_Status = NDIS_STATUS_INVALID_LENGTH;
1180
if (NewDeviceState > NdisDeviceStateD0)
1182
l_Adapter->m_InterfaceIsRunning = FALSE;
1183
DEBUGP (("[%s] Power management device state OFF\n",
1184
l_Adapter->m_Name));
1188
l_Adapter->m_InterfaceIsRunning = TRUE;
1189
DEBUGP (("[%s] Power management device state ON\n",
1190
l_Adapter->m_Name));
1193
l_Status = NDIS_STATUS_SUCCESS;
1197
if (l_Status == NDIS_STATUS_SUCCESS)
1199
*p_BytesRead = sizeof (NDIS_DEVICE_POWER_STATE);
1205
*p_BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE);
1209
case OID_PNP_REMOVE_WAKE_UP_PATTERN:
1210
case OID_PNP_ADD_WAKE_UP_PATTERN:
1211
l_Status = NDIS_STATUS_SUCCESS;
1212
*p_BytesRead = *p_BytesNeeded = 0;
1216
DEBUGP (("[%s] Can't set value for OID %lx\n", l_Adapter->m_Name,
1218
l_Status = NDIS_STATUS_INVALID_OID;
1219
*p_BytesRead = *p_BytesNeeded = 0;
1223
NdisReleaseSpinLock (&l_Adapter->m_Lock);
1228
//====================================================================
1229
// Adapter Transmission
1230
//====================================================================
1232
AdapterTransmit (IN NDIS_HANDLE p_AdapterContext, IN PNDIS_PACKET p_Packet,
1235
TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
1236
ULONG l_Index = 0, l_BufferLength = 0, l_PacketLength = 0;
1238
TapPacketPointer l_PacketBuffer;
1239
TapExtensionPointer l_Extension;
1240
PNDIS_BUFFER l_NDIS_Buffer;
1244
NdisQueryPacket (p_Packet, NULL, NULL, &l_NDIS_Buffer, &l_PacketLength);
1246
//====================================================
1247
// Here we abandon the transmission attempt if any of
1248
// the parameters is wrong or memory allocation fails
1249
// but we do not indicate failure. The packet is
1250
// silently dropped.
1251
//====================================================
1253
if (l_Adapter->m_TapDevice == NULL)
1254
return NDIS_STATUS_FAILURE;
1255
else if ((l_Extension =
1256
(TapExtensionPointer) l_Adapter->m_TapDevice->DeviceExtension) ==
1258
return NDIS_STATUS_FAILURE;
1259
else if (l_PacketLength < ETHERNET_HEADER_SIZE)
1260
return NDIS_STATUS_FAILURE;
1261
else if (l_PacketLength > 65535) // Cap packet size to TCP/IP maximum
1262
return NDIS_STATUS_FAILURE;
1263
else if (!l_Adapter->m_TapOpens || !l_Adapter->m_MediaState)
1264
return NDIS_STATUS_SUCCESS; // Nothing is bound to the TAP device
1266
if (NdisAllocateMemoryWithTag (&l_PacketBuffer,
1267
TAP_PACKET_SIZE (l_PacketLength),
1268
'5PAT') != NDIS_STATUS_SUCCESS)
1269
return NDIS_STATUS_RESOURCES;
1271
if (l_PacketBuffer == NULL)
1272
return NDIS_STATUS_RESOURCES;
1274
l_PacketBuffer->m_SizeFlags = (l_PacketLength & TP_SIZE_MASK);
1276
//===========================
1277
// Reassemble packet contents
1278
//===========================
1282
for (l_Index = 0; l_NDIS_Buffer && l_Index < l_PacketLength;
1283
l_Index += l_BufferLength)
1285
NdisQueryBuffer (l_NDIS_Buffer, (PVOID *) & l_Buffer,
1287
NdisMoveMemory (l_PacketBuffer->m_Data + l_Index, l_Buffer,
1289
NdisGetNextBuffer (l_NDIS_Buffer, &l_NDIS_Buffer);
1292
DUMP_PACKET ("AdapterTransmit", l_PacketBuffer->m_Data, l_PacketLength);
1294
//=====================================================
1295
// Are we running in DHCP server masquerade mode?
1297
// If so, catch both DHCP requests and ARP queries
1298
// to resolve the address of our virtual DHCP server.
1299
//=====================================================
1300
if (l_Adapter->m_dhcp_enabled)
1302
const ETH_HEADER *eth = (ETH_HEADER *) l_PacketBuffer->m_Data;
1303
const IPHDR *ip = (IPHDR *) (l_PacketBuffer->m_Data + sizeof (ETH_HEADER));
1304
const UDPHDR *udp = (UDPHDR *) (l_PacketBuffer->m_Data + sizeof (ETH_HEADER) + sizeof (IPHDR));
1307
if (l_PacketLength == sizeof (ARP_PACKET)
1308
&& eth->proto == htons (ETH_P_ARP)
1309
&& l_Adapter->m_dhcp_server_arp)
1311
if (ProcessARP (l_Adapter,
1312
(PARP_PACKET) l_PacketBuffer->m_Data,
1313
l_Adapter->m_dhcp_addr,
1314
l_Adapter->m_dhcp_server_ip,
1315
l_Adapter->m_dhcp_server_mac))
1320
else if (l_PacketLength >= sizeof (ETH_HEADER) + sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP)
1321
&& eth->proto == htons (ETH_P_IP)
1322
&& ip->version_len == 0x45 // IPv4, 20 byte header
1323
&& ip->protocol == IPPROTO_UDP
1324
&& udp->dest == htons (BOOTPS_PORT))
1326
const DHCP *dhcp = (DHCP *) (l_PacketBuffer->m_Data
1327
+ sizeof (ETH_HEADER)
1331
const int optlen = l_PacketLength
1332
- sizeof (ETH_HEADER)
1337
if (optlen > 0) // we must have at least one DHCP option
1339
if (ProcessDHCP (l_Adapter, eth, ip, udp, dhcp, optlen))
1347
//===============================================
1348
// In Point-To-Point mode, check to see whether
1349
// packet is ARP or IPv4 (if neither, then drop).
1350
//===============================================
1351
if (l_Adapter->m_PointToPoint)
1355
if (l_PacketLength < ETHERNET_HEADER_SIZE)
1358
e = (ETH_HEADER *) l_PacketBuffer->m_Data;
1360
switch (ntohs (e->proto))
1364
// Make sure that packet is the
1365
// right size for ARP.
1366
if (l_PacketLength != sizeof (ARP_PACKET))
1369
ProcessARP (l_Adapter,
1370
(PARP_PACKET) l_PacketBuffer->m_Data,
1371
l_Adapter->m_localIP,
1372
l_Adapter->m_remoteIP,
1373
l_Adapter->m_TapToUser.dest);
1380
// Make sure that packet is large
1381
// enough to be IPv4.
1383
< ETHERNET_HEADER_SIZE + IP_HEADER_SIZE)
1386
// Only accept directed packets,
1388
if (memcmp (e, &l_Adapter->m_TapToUser, ETHERNET_HEADER_SIZE))
1391
// Packet looks like IPv4, queue it.
1392
l_PacketBuffer->m_SizeFlags |= TP_POINT_TO_POINT;
1396
//===============================================
1397
// Push packet onto queue to wait for read from
1399
//===============================================
1401
NdisAcquireSpinLock (&l_Adapter->m_QueueLock);
1404
if (IS_UP (l_Adapter))
1405
result = QueuePush (l_Extension->m_PacketQueue, l_PacketBuffer);
1407
NdisReleaseSpinLock (&l_Adapter->m_QueueLock);
1409
if ((TapPacketPointer) result != l_PacketBuffer)
1411
// adapter receive overrun
1412
#ifndef NEED_TAP_IOCTL_SET_STATISTICS
1413
INCREMENT_STAT (l_Adapter->m_TxErr);
1417
#ifndef NEED_TAP_IOCTL_SET_STATISTICS
1420
INCREMENT_STAT (l_Adapter->m_Tx);
1424
//============================================================
1425
// Cycle through IRPs and packets, try to satisfy each pending
1426
// IRP with a queued packet.
1427
//============================================================
1431
l_PacketBuffer = NULL;
1433
NdisAcquireSpinLock (&l_Adapter->m_QueueLock);
1435
if (IS_UP (l_Adapter)
1436
&& QueueCount (l_Extension->m_PacketQueue)
1437
&& QueueCount (l_Extension->m_IrpQueue))
1439
l_IRP = (PIRP) QueuePop (l_Extension->m_IrpQueue);
1440
l_PacketBuffer = (TapPacketPointer)
1441
QueuePop (l_Extension->m_PacketQueue);
1444
NdisReleaseSpinLock (&l_Adapter->m_QueueLock);
1446
MYASSERT ((l_IRP != NULL) + (l_PacketBuffer != NULL) != 1);
1448
if (l_IRP && l_PacketBuffer)
1450
CompleteIRP (l_Adapter,
1453
IO_NETWORK_INCREMENT);
1459
__except (EXCEPTION_EXECUTE_HANDLER)
1463
return NDIS_STATUS_SUCCESS;
1466
NdisFreeMemory (l_PacketBuffer,
1467
TAP_PACKET_SIZE (l_PacketLength),
1469
return NDIS_STATUS_SUCCESS;
1472
//======================================================================
1473
// Hook for catching tap device IRP's.
1474
// Network adapter requests are forwarded on to NDIS
1475
//======================================================================
1477
TapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject, IN PIRP p_IRP)
1479
PIO_STACK_LOCATION l_IrpSp;
1480
TapExtensionPointer l_Extension;
1481
NTSTATUS l_Status = STATUS_SUCCESS;
1482
TapAdapterPointer l_Adapter;
1484
//=======================================================================
1485
// If it's not the private data device type, call the original handler
1486
//=======================================================================
1487
l_IrpSp = IoGetCurrentIrpStackLocation (p_IRP);
1488
if (p_DeviceObject->DeviceType != (FILE_DEVICE_PHYSICAL_NETCARD | 0x8000))
1490
return (*g_DispatchHook[l_IrpSp->MajorFunction]) (p_DeviceObject,
1494
//=============================================================
1495
// Only TAP device I/O requests get handled below here
1496
//=============================================================
1497
l_Extension = (TapExtensionPointer) p_DeviceObject->DeviceExtension;
1498
l_Adapter = l_Extension->m_Adapter;
1500
p_IRP->IoStatus.Status = STATUS_SUCCESS;
1501
p_IRP->IoStatus.Information = 0;
1503
if (l_Extension->m_halt)
1505
DEBUGP (("TapDeviceHook called when TAP device is halted\n"));
1506
p_IRP->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
1507
IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1508
return STATUS_NO_SUCH_DEVICE;
1511
switch (l_IrpSp->MajorFunction)
1513
//===========================================================
1514
// Ioctl call handlers
1515
//===========================================================
1516
case IRP_MJ_DEVICE_CONTROL:
1518
switch (l_IrpSp->Parameters.DeviceIoControl.IoControlCode)
1520
case TAP_IOCTL_GET_MAC:
1522
if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
1523
>= sizeof (MACADDR))
1525
COPY_MAC (p_IRP->AssociatedIrp.SystemBuffer,
1527
p_IRP->IoStatus.Information = sizeof (MACADDR);
1531
NOTE_ERROR (l_Adapter);
1532
p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
1536
case TAP_IOCTL_GET_VERSION:
1538
const ULONG size = sizeof (ULONG) * 3;
1539
if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
1542
((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0]
1543
= TAP_DRIVER_MAJOR_VERSION;
1544
((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[1]
1545
= TAP_DRIVER_MINOR_VERSION;
1546
((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[2]
1552
p_IRP->IoStatus.Information = size;
1556
NOTE_ERROR (l_Adapter);
1557
p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
1562
case TAP_IOCTL_GET_MTU:
1564
const ULONG size = sizeof (ULONG) * 1;
1565
if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
1568
((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0]
1570
p_IRP->IoStatus.Information = size;
1574
NOTE_ERROR (l_Adapter);
1575
p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
1580
case TAP_IOCTL_GET_INFO:
1583
if (l_Adapter->m_InterfaceIsRunning)
1587
if (l_Adapter->m_TapIsRunning)
1591
state[2] = l_Adapter->m_DeviceState;
1592
if (l_Adapter->m_MediaStateAlwaysConnected)
1598
p_IRP->IoStatus.Status = l_Status = RtlStringCchPrintfExA (
1599
((LPTSTR) (p_IRP->AssociatedIrp.SystemBuffer)),
1600
l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
1603
STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,
1604
"State=%s Err=[%s/%d] #O=%d Tx=[%d,%d] Rx=[%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d]",
1606
l_Adapter->m_LastErrorFilename,
1607
l_Adapter->m_LastErrorLineNumber,
1608
(int)l_Adapter->m_NumTapOpens,
1609
(int)l_Adapter->m_Tx,
1610
(int)l_Adapter->m_TxErr,
1611
(int)l_Adapter->m_Rx,
1612
(int)l_Adapter->m_RxErr,
1613
(int)l_Extension->m_IrpQueue->size,
1614
(int)l_Extension->m_IrpQueue->max_size,
1615
(int)IRP_QUEUE_SIZE,
1616
(int)l_Extension->m_PacketQueue->size,
1617
(int)l_Extension->m_PacketQueue->max_size,
1618
(int)PACKET_QUEUE_SIZE
1621
p_IRP->IoStatus.Information
1622
= l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1628
case TAP_IOCTL_GET_LOG_LINE:
1630
if (GetDebugLine ((LPTSTR)p_IRP->AssociatedIrp.SystemBuffer,
1631
l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength))
1632
p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
1634
p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
1636
p_IRP->IoStatus.Information
1637
= l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1643
#ifdef NEED_TAP_IOCTL_GET_LASTMAC
1644
case TAP_IOCTL_GET_LASTMAC:
1646
if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
1649
COPY_MAC (p_IRP->AssociatedIrp.SystemBuffer, g_MAC);
1650
p_IRP->IoStatus.Information = sizeof (MACADDR);
1654
NOTE_ERROR (l_Adapter);
1655
p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
1662
#ifdef NEED_TAP_IOCTL_SET_STATISTICS
1663
case TAP_IOCTL_SET_STATISTICS:
1665
if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
1666
(sizeof (ULONG) * 4))
1669
((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0];
1671
((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[1];
1672
l_Adapter->m_TxErr =
1673
((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[2];
1674
l_Adapter->m_RxErr =
1675
((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[3];
1676
p_IRP->IoStatus.Information = 1; // Simple boolean value
1680
NOTE_ERROR (l_Adapter);
1681
p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1687
case TAP_IOCTL_CONFIG_POINT_TO_POINT:
1689
if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
1690
(sizeof (IPADDR) * 2))
1694
NdisAcquireSpinLock (&l_Adapter->m_Lock);
1696
GenerateRelatedMAC (dest, l_Adapter->m_MAC, 1);
1698
l_Adapter->m_PointToPoint = TRUE;
1700
l_Adapter->m_localIP =
1701
((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0];
1702
l_Adapter->m_remoteIP =
1703
((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1];
1705
COPY_MAC (l_Adapter->m_TapToUser.src, l_Adapter->m_MAC);
1706
COPY_MAC (l_Adapter->m_TapToUser.dest, dest);
1707
COPY_MAC (l_Adapter->m_UserToTap.src, dest);
1708
COPY_MAC (l_Adapter->m_UserToTap.dest, l_Adapter->m_MAC);
1710
l_Adapter->m_TapToUser.proto = l_Adapter->m_UserToTap.proto = htons (ETH_P_IP);
1712
CheckIfDhcpAndPointToPointMode (l_Adapter);
1714
NdisReleaseSpinLock (&l_Adapter->m_Lock);
1716
p_IRP->IoStatus.Information = 1; // Simple boolean value
1720
NOTE_ERROR (l_Adapter);
1721
p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1727
case TAP_IOCTL_SET_MEDIA_STATUS:
1729
if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
1730
(sizeof (ULONG) * 1))
1732
ULONG parm = ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0];
1733
SetMediaStatus (l_Adapter, (BOOLEAN) parm);
1734
p_IRP->IoStatus.Information = 1;
1738
NOTE_ERROR (l_Adapter);
1739
p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1744
case TAP_IOCTL_CONFIG_DHCP_MASQ:
1746
if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
1747
(sizeof (IPADDR) * 4))
1749
NdisAcquireSpinLock (&l_Adapter->m_Lock);
1751
l_Adapter->m_dhcp_enabled = TRUE;
1752
l_Adapter->m_dhcp_server_arp = TRUE;
1753
l_Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
1755
// Adapter IP addr / netmask
1756
l_Adapter->m_dhcp_addr =
1757
((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0];
1758
l_Adapter->m_dhcp_netmask =
1759
((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1];
1761
// IP addr of DHCP masq server
1762
l_Adapter->m_dhcp_server_ip =
1763
((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[2];
1765
// Lease time in seconds
1766
l_Adapter->m_dhcp_lease_time =
1767
((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[3];
1769
GenerateRelatedMAC (l_Adapter->m_dhcp_server_mac, l_Adapter->m_MAC, 2);
1771
CheckIfDhcpAndPointToPointMode (l_Adapter);
1773
NdisReleaseSpinLock (&l_Adapter->m_Lock);
1775
p_IRP->IoStatus.Information = 1; // Simple boolean value
1779
NOTE_ERROR (l_Adapter);
1780
p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1786
case TAP_IOCTL_CONFIG_DHCP_SET_OPT:
1788
if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength <=
1789
DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE
1790
&& l_Adapter->m_dhcp_enabled)
1792
l_Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
1794
NdisMoveMemory (l_Adapter->m_dhcp_user_supplied_options_buffer,
1795
p_IRP->AssociatedIrp.SystemBuffer,
1796
l_IrpSp->Parameters.DeviceIoControl.InputBufferLength);
1798
l_Adapter->m_dhcp_user_supplied_options_buffer_len =
1799
l_IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1801
p_IRP->IoStatus.Information = 1; // Simple boolean value
1805
NOTE_ERROR (l_Adapter);
1806
p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1814
NOTE_ERROR (l_Adapter);
1815
p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1820
IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1824
//===========================================================
1825
// User mode thread issued a read request on the tap device
1826
// If there are packets waiting to be read, then the request
1827
// will be satisfied here. If not, then the request will be
1828
// queued and satisfied by any packet that is not used to
1829
// satisfy requests ahead of it.
1830
//===========================================================
1833
TapPacketPointer l_PacketBuffer;
1834
BOOLEAN pending = FALSE;
1836
// Save IRP-accessible copy of buffer length
1837
p_IRP->IoStatus.Information = l_IrpSp->Parameters.Read.Length;
1839
if (p_IRP->MdlAddress == NULL)
1841
DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_READ\n",
1842
l_Adapter->m_Name));
1843
NOTE_ERROR (l_Adapter);
1844
p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1845
p_IRP->IoStatus.Information = 0;
1846
IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1849
else if ((p_IRP->AssociatedIrp.SystemBuffer =
1850
MmGetSystemAddressForMdlSafe
1851
(p_IRP->MdlAddress, NormalPagePriority)) == NULL)
1853
DEBUGP (("[%s] Could not map address in IRP_MJ_READ\n",
1854
l_Adapter->m_Name));
1855
NOTE_ERROR (l_Adapter);
1856
p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES;
1857
p_IRP->IoStatus.Information = 0;
1858
IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1861
else if (!l_Adapter->m_InterfaceIsRunning)
1863
DEBUGP (("[%s] Interface is down in IRP_MJ_READ\n",
1864
l_Adapter->m_Name));
1865
NOTE_ERROR (l_Adapter);
1866
p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
1867
p_IRP->IoStatus.Information = 0;
1868
IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1872
//==================================
1873
// Can we provide immediate service?
1874
//==================================
1876
l_PacketBuffer = NULL;
1878
NdisAcquireSpinLock (&l_Adapter->m_QueueLock);
1880
if (IS_UP (l_Adapter)
1881
&& QueueCount (l_Extension->m_PacketQueue)
1882
&& QueueCount (l_Extension->m_IrpQueue) == 0)
1884
l_PacketBuffer = (TapPacketPointer)
1885
QueuePop (l_Extension->m_PacketQueue);
1888
NdisReleaseSpinLock (&l_Adapter->m_QueueLock);
1892
l_Status = CompleteIRP (l_Adapter,
1899
//=============================
1900
// Attempt to pend read request
1901
//=============================
1903
NdisAcquireSpinLock (&l_Adapter->m_QueueLock);
1905
if (IS_UP (l_Adapter)
1906
&& QueuePush (l_Extension->m_IrpQueue, p_IRP) == (PIRP) p_IRP)
1908
IoSetCancelRoutine (p_IRP, CancelIRPCallback);
1909
l_Status = STATUS_PENDING;
1910
IoMarkIrpPending (p_IRP);
1914
NdisReleaseSpinLock (&l_Adapter->m_QueueLock);
1919
// Can't queue anymore IRP's
1920
DEBUGP (("[%s] TAP [%s] read IRP overrun\n",
1921
l_Adapter->m_Name, l_Adapter->m_TapName));
1922
NOTE_ERROR (l_Adapter);
1923
p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
1924
p_IRP->IoStatus.Information = 0;
1925
IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1929
//==============================================================
1930
// User mode issued a WriteFile request on the TAP file handle.
1931
// The request will always get satisfied here. The call may
1932
// fail if there are too many pending packets (queue full).
1933
//==============================================================
1936
if (p_IRP->MdlAddress == NULL)
1938
DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n",
1939
l_Adapter->m_Name));
1940
NOTE_ERROR (l_Adapter);
1941
p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1942
p_IRP->IoStatus.Information = 0;
1944
else if ((p_IRP->AssociatedIrp.SystemBuffer =
1945
MmGetSystemAddressForMdlSafe
1946
(p_IRP->MdlAddress, NormalPagePriority)) == NULL)
1948
DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n",
1949
l_Adapter->m_Name));
1950
NOTE_ERROR (l_Adapter);
1951
p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES;
1952
p_IRP->IoStatus.Information = 0;
1954
else if (!l_Adapter->m_InterfaceIsRunning)
1956
DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n",
1957
l_Adapter->m_Name));
1958
NOTE_ERROR (l_Adapter);
1959
p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
1960
p_IRP->IoStatus.Information = 0;
1962
else if (!l_Adapter->m_PointToPoint && ((l_IrpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE))
1966
p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length;
1968
DUMP_PACKET ("IRP_MJ_WRITE ETH",
1969
(unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
1970
l_IrpSp->Parameters.Write.Length);
1972
NdisMEthIndicateReceive
1973
(l_Adapter->m_MiniportAdapterHandle,
1974
(NDIS_HANDLE) l_Adapter,
1975
(unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
1976
ETHERNET_HEADER_SIZE,
1977
(unsigned char *) p_IRP->AssociatedIrp.SystemBuffer + ETHERNET_HEADER_SIZE,
1978
l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE,
1979
l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE);
1981
NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle);
1983
p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
1985
__except (EXCEPTION_EXECUTE_HANDLER)
1987
DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE\n",
1988
l_Adapter->m_Name));
1989
NOTE_ERROR (l_Adapter);
1990
p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
1991
p_IRP->IoStatus.Information = 0;
1994
else if (l_Adapter->m_PointToPoint && ((l_IrpSp->Parameters.Write.Length) >= IP_HEADER_SIZE))
1998
p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length;
2000
DUMP_PACKET2 ("IRP_MJ_WRITE P2P",
2001
&l_Adapter->m_UserToTap,
2002
(unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2003
l_IrpSp->Parameters.Write.Length);
2005
NdisMEthIndicateReceive
2006
(l_Adapter->m_MiniportAdapterHandle,
2007
(NDIS_HANDLE) l_Adapter,
2008
(unsigned char *) &l_Adapter->m_UserToTap,
2009
sizeof (l_Adapter->m_UserToTap),
2010
(unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2011
l_IrpSp->Parameters.Write.Length,
2012
l_IrpSp->Parameters.Write.Length);
2014
NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle);
2016
p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2018
__except (EXCEPTION_EXECUTE_HANDLER)
2020
DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE (P2P)\n",
2021
l_Adapter->m_Name));
2022
NOTE_ERROR (l_Adapter);
2023
p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2024
p_IRP->IoStatus.Information = 0;
2029
DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n",
2031
l_IrpSp->Parameters.Write.Length));
2032
NOTE_ERROR (l_Adapter);
2033
p_IRP->IoStatus.Information = 0; // ETHERNET_HEADER_SIZE;
2034
p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
2037
#ifndef NEED_TAP_IOCTL_SET_STATISTICS
2038
if (l_Status == STATUS_SUCCESS)
2039
INCREMENT_STAT (l_Adapter->m_Rx);
2041
INCREMENT_STAT (l_Adapter->m_RxErr);
2043
IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2047
//--------------------------------------------------------------
2048
// User mode thread has called CreateFile() on the tap device
2049
//--------------------------------------------------------------
2052
if (l_Adapter->m_TapIsRunning
2053
#ifdef DISABLE_DEVICE_SHARING
2054
&& l_Adapter->m_TapOpens < 1
2061
(("[%s] [TAP] release [%d.%d] open request (m_TapOpens=%d)\n",
2062
l_Adapter->m_Name, TAP_DRIVER_MAJOR_VERSION,
2063
TAP_DRIVER_MINOR_VERSION, l_Adapter->m_TapOpens));
2065
NdisAcquireSpinLock (&l_Adapter->m_Lock);
2066
++l_Adapter->m_TapOpens;
2067
first_open = (l_Adapter->m_TapOpens == 1);
2069
ResetTapDevState (l_Adapter);
2070
NdisReleaseSpinLock (&l_Adapter->m_Lock);
2072
#ifdef SET_MEDIA_STATUS_ON_OPEN
2074
SetMediaStatus (l_Adapter, TRUE);
2077
INCREMENT_STAT (l_Adapter->m_NumTapOpens);
2078
p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2079
p_IRP->IoStatus.Information = 0;
2083
DEBUGP (("[%s] TAP is presently unavailable (m_TapOpens=%d)\n",
2084
l_Adapter->m_Name, l_Adapter->m_TapOpens));
2085
NOTE_ERROR (l_Adapter);
2086
p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2087
p_IRP->IoStatus.Information = 0;
2090
IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2094
//-----------------------------------------------------------
2095
// User mode thread called CloseHandle() on the tap device
2096
//-----------------------------------------------------------
2099
BOOLEAN fully_closed = FALSE;
2101
DEBUGP (("[%s] [TAP] release [%d.%d] close request\n",
2102
l_Adapter->m_Name, TAP_DRIVER_MAJOR_VERSION,
2103
TAP_DRIVER_MINOR_VERSION));
2105
NdisAcquireSpinLock (&l_Adapter->m_Lock);
2106
if (l_Adapter->m_TapOpens)
2108
--l_Adapter->m_TapOpens;
2109
if (l_Adapter->m_TapOpens == 0)
2111
fully_closed = TRUE;
2112
ResetTapDevState (l_Adapter);
2115
NdisReleaseSpinLock (&l_Adapter->m_Lock);
2119
FlushQueues (l_Adapter);
2120
SetMediaStatus (l_Adapter, FALSE);
2123
IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2127
//------------------
2129
//------------------
2132
//NOTE_ERROR (l_Adapter);
2133
p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2134
IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2142
//=============================================================
2143
// CompleteIRP is normally called with an adapter -> userspace
2144
// network packet and an IRP (Pending I/O request) from userspace.
2146
// The IRP will normally represent a queued overlapped read
2147
// operation from userspace that is in a wait state.
2149
// Use the ethernet packet to satisfy the IRP.
2150
//=============================================================
2153
CompleteIRP (TapAdapterPointer p_Adapter,
2155
IN TapPacketPointer p_PacketBuffer,
2156
IN CCHAR PriorityBoost)
2158
NTSTATUS l_Status = STATUS_UNSUCCESSFUL;
2164
MYASSERT (p_PacketBuffer);
2166
IoSetCancelRoutine (p_IRP, NULL); // Disable cancel routine
2168
//-------------------------------------------
2169
// While p_PacketBuffer always contains a
2170
// full ethernet packet, including the
2171
// ethernet header, in point-to-point mode,
2172
// we only want to return the IPv4
2174
//-------------------------------------------
2176
if (p_PacketBuffer->m_SizeFlags & TP_POINT_TO_POINT)
2178
offset = ETHERNET_HEADER_SIZE;
2179
len = (int) (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK) - ETHERNET_HEADER_SIZE;
2184
len = (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK);
2187
if (len < 0 || (int) p_IRP->IoStatus.Information < len)
2189
p_IRP->IoStatus.Information = 0;
2190
p_IRP->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
2191
NOTE_ERROR (p_Adapter);
2195
p_IRP->IoStatus.Information = len;
2196
p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2200
NdisMoveMemory (p_IRP->AssociatedIrp.SystemBuffer,
2201
p_PacketBuffer->m_Data + offset,
2204
__except (EXCEPTION_EXECUTE_HANDLER)
2206
NOTE_ERROR (p_Adapter);
2207
p_IRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
2208
p_IRP->IoStatus.Information = 0;
2214
NdisFreeMemory (p_PacketBuffer,
2215
TAP_PACKET_SIZE (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK),
2218
__except (EXCEPTION_EXECUTE_HANDLER)
2222
if (l_Status == STATUS_SUCCESS)
2224
IoCompleteRequest (p_IRP, PriorityBoost);
2227
IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2232
//==============================================
2233
// IRPs get cancelled for a number of reasons.
2235
// The TAP device could be closed by userspace
2236
// when there are still pending read operations.
2238
// The user could disable the TAP adapter in the
2239
// network connections control panel, while the
2240
// device is still open by a process.
2241
//==============================================
2243
CancelIRPCallback (IN PDEVICE_OBJECT p_DeviceObject,
2246
CancelIRP (p_DeviceObject, p_IRP, TRUE);
2250
CancelIRP (IN PDEVICE_OBJECT p_DeviceObject,
2254
TapExtensionPointer l_Extension =
2255
(TapExtensionPointer) p_DeviceObject->DeviceExtension;
2257
BOOLEAN exists = FALSE;
2261
if (!l_Extension->m_halt)
2263
NdisAcquireSpinLock (&l_Extension->m_Adapter->m_QueueLock);
2264
exists = (QueueExtract (l_Extension->m_IrpQueue, p_IRP) == p_IRP);
2265
NdisReleaseSpinLock (&l_Extension->m_Adapter->m_QueueLock);
2272
IoSetCancelRoutine (p_IRP, NULL);
2273
p_IRP->IoStatus.Status = STATUS_CANCELLED;
2274
p_IRP->IoStatus.Information = 0;
2278
IoReleaseCancelSpinLock (p_IRP->CancelIrql);
2281
IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2284
//====================================
2285
// Exhaust packet and IRP queues.
2286
//====================================
2288
FlushQueues (TapAdapterPointer p_Adapter)
2291
TapPacketPointer l_PacketBuffer;
2292
int n_IRP=0, n_Packet=0;
2293
TapExtensionPointer l_Extension;
2295
MYASSERT (p_Adapter);
2296
MYASSERT (p_Adapter->m_TapDevice);
2298
l_Extension = (TapExtensionPointer)
2299
p_Adapter->m_TapDevice->DeviceExtension;
2303
NdisAcquireSpinLock (&p_Adapter->m_QueueLock);
2304
l_IRP = QueuePop (l_Extension->m_IrpQueue);
2305
NdisReleaseSpinLock (&p_Adapter->m_QueueLock);
2309
CancelIRP (p_Adapter->m_TapDevice, l_IRP, FALSE);
2317
NdisAcquireSpinLock (&p_Adapter->m_QueueLock);
2318
l_PacketBuffer = QueuePop (l_Extension->m_PacketQueue);
2319
NdisReleaseSpinLock (&p_Adapter->m_QueueLock);
2323
MemFree (l_PacketBuffer, TAP_PACKET_SIZE (l_PacketBuffer->m_SizeFlags & TP_SIZE_MASK));
2330
"[%s] [TAP] FlushQueues n_IRP=[%d,%d,%d] n_Packet=[%d,%d,%d]\n",
2333
l_Extension->m_IrpQueue->max_size,
2336
l_Extension->m_PacketQueue->max_size,
2341
//===================================================
2342
// Tell Windows whether the TAP device should be
2343
// considered "connected" or "disconnected".
2344
//===================================================
2346
SetMediaStatus (TapAdapterPointer p_Adapter, BOOLEAN state)
2348
if (p_Adapter->m_MediaState != state && !p_Adapter->m_MediaStateAlwaysConnected)
2351
NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle,
2352
NDIS_STATUS_MEDIA_CONNECT, NULL, 0);
2354
NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle,
2355
NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0);
2357
NdisMIndicateStatusComplete (p_Adapter->m_MiniportAdapterHandle);
2358
p_Adapter->m_MediaState = state;
2363
//======================================================
2364
// If DHCP mode is used together with Point-to-point
2365
// mode, consider the fact that the P2P remote endpoint
2366
// might be equal to the DHCP masq server address.
2367
//======================================================
2369
CheckIfDhcpAndPointToPointMode (TapAdapterPointer p_Adapter)
2371
if (p_Adapter->m_PointToPoint && p_Adapter->m_dhcp_enabled)
2373
if (p_Adapter->m_dhcp_server_ip == p_Adapter->m_remoteIP)
2375
COPY_MAC (p_Adapter->m_dhcp_server_mac, p_Adapter->m_TapToUser.dest);
2376
p_Adapter->m_dhcp_server_arp = FALSE;
2381
//===================================================
2382
// Generate an ARP reply message for specific kinds
2384
//===================================================
2386
ProcessARP (TapAdapterPointer p_Adapter,
2387
const PARP_PACKET src,
2388
const IPADDR adapter_ip,
2392
//-----------------------------------------------
2393
// Is this the kind of packet we are looking for?
2394
//-----------------------------------------------
2395
if (src->m_Proto == htons (ETH_P_ARP)
2396
&& MAC_EQUAL (src->m_MAC_Source, p_Adapter->m_MAC)
2397
&& MAC_EQUAL (src->m_ARP_MAC_Source, p_Adapter->m_MAC)
2398
&& MAC_EQUAL (src->m_MAC_Destination, p_Adapter->m_MAC_Broadcast)
2399
&& src->m_ARP_Operation == htons (ARP_REQUEST)
2400
&& src->m_MAC_AddressType == htons (MAC_ADDR_TYPE)
2401
&& src->m_MAC_AddressSize == sizeof (MACADDR)
2402
&& src->m_PROTO_AddressType == htons (ETH_P_IP)
2403
&& src->m_PROTO_AddressSize == sizeof (IPADDR)
2404
&& src->m_ARP_IP_Source == adapter_ip
2405
&& src->m_ARP_IP_Destination == ip)
2407
ARP_PACKET *arp = (ARP_PACKET *) MemAlloc (sizeof (ARP_PACKET), TRUE);
2410
//----------------------------------------------
2411
// Initialize ARP reply fields
2412
//----------------------------------------------
2413
arp->m_Proto = htons (ETH_P_ARP);
2414
arp->m_MAC_AddressType = htons (MAC_ADDR_TYPE);
2415
arp->m_PROTO_AddressType = htons (ETH_P_IP);
2416
arp->m_MAC_AddressSize = sizeof (MACADDR);
2417
arp->m_PROTO_AddressSize = sizeof (IPADDR);
2418
arp->m_ARP_Operation = htons (ARP_REPLY);
2420
//----------------------------------------------
2422
//----------------------------------------------
2423
COPY_MAC (arp->m_MAC_Source, mac);
2424
COPY_MAC (arp->m_MAC_Destination, p_Adapter->m_MAC);
2425
COPY_MAC (arp->m_ARP_MAC_Source, mac);
2426
COPY_MAC (arp->m_ARP_MAC_Destination, p_Adapter->m_MAC);
2427
arp->m_ARP_IP_Source = ip;
2428
arp->m_ARP_IP_Destination = adapter_ip;
2430
DUMP_PACKET ("ProcessARP",
2431
(unsigned char *) arp,
2432
sizeof (ARP_PACKET));
2434
InjectPacket (p_Adapter, (UCHAR *) arp, sizeof (ARP_PACKET));
2436
MemFree (arp, sizeof (ARP_PACKET));
2445
//===============================================================
2446
// Used in cases where internally generated packets such as
2447
// ARP or DHCP replies must be returned to the kernel, to be
2448
// seen as an incoming packet "arriving" on the interface.
2449
//===============================================================
2452
InjectPacket (TapAdapterPointer p_Adapter, UCHAR *packet, const unsigned int len)
2454
MYASSERT (len >= ETHERNET_HEADER_SIZE);
2458
//------------------------------------------------------------
2459
// NdisMEthIndicateReceive and NdisMEthIndicateReceiveComplete
2460
// could potentially be called reentrantly both here and in
2461
// TapDeviceHook/IRP_MJ_WRITE.
2463
// The DDK docs imply that this is okay.
2464
//------------------------------------------------------------
2465
NdisMEthIndicateReceive
2466
(p_Adapter->m_MiniportAdapterHandle,
2467
(NDIS_HANDLE) p_Adapter,
2469
ETHERNET_HEADER_SIZE,
2470
packet + ETHERNET_HEADER_SIZE,
2471
len - ETHERNET_HEADER_SIZE,
2472
len - ETHERNET_HEADER_SIZE);
2474
NdisMEthIndicateReceiveComplete (p_Adapter->m_MiniportAdapterHandle);
2476
__except (EXCEPTION_EXECUTE_HANDLER)
2478
DEBUGP (("[%s] NdisMEthIndicateReceive failed in InjectPacket\n",
2479
p_Adapter->m_Name));
2480
NOTE_ERROR (p_Adapter);
2484
//===================================================================
2485
// Go back to default TAP mode from Point-To-Point mode.
2486
// Also reset (i.e. disable) DHCP Masq mode.
2487
//===================================================================
2488
VOID ResetTapDevState (TapAdapterPointer p_Adapter)
2491
p_Adapter->m_PointToPoint = FALSE;
2492
p_Adapter->m_localIP = 0;
2493
p_Adapter->m_remoteIP = 0;
2494
NdisZeroMemory (&p_Adapter->m_TapToUser, sizeof (p_Adapter->m_TapToUser));
2495
NdisZeroMemory (&p_Adapter->m_UserToTap, sizeof (p_Adapter->m_UserToTap));
2498
p_Adapter->m_dhcp_enabled = FALSE;
2499
p_Adapter->m_dhcp_server_arp = FALSE;
2500
p_Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
2501
p_Adapter->m_dhcp_addr = 0;
2502
p_Adapter->m_dhcp_netmask = 0;
2503
p_Adapter->m_dhcp_server_ip = 0;
2504
p_Adapter->m_dhcp_lease_time = 0;
2505
p_Adapter->m_dhcp_received_discover = FALSE;
2506
p_Adapter->m_dhcp_bad_requests = 0;
2507
NdisZeroMemory (p_Adapter->m_dhcp_server_mac, sizeof (MACADDR));
2510
//===================================================================
2511
// Dispatch Table Managemement
2512
//===================================================================
2514
HookDispatchFunctions ()
2516
unsigned long l_Index;
2518
//==============================================================
2519
// Save original NDIS dispatch functions and override with ours
2520
//==============================================================
2521
if (!g_DispatchFunctionsHooked)
2522
for (l_Index = 0, g_DispatchFunctionsHooked = 1;
2523
l_Index <= IRP_MJ_MAXIMUM_FUNCTION; ++l_Index)
2525
g_DispatchHook[l_Index] = g_TapDriverObject->MajorFunction[l_Index];
2526
g_TapDriverObject->MajorFunction[l_Index] = TapDeviceHook;
2530
//======================================================================
2532
//======================================================================