2 * TAP-Win32/TAP-Win64 -- A kernel driver to provide virtual tap
3 * device functionality on Windows.
5 * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
7 * This source code is Copyright (C) 2002-2009 OpenVPN Technologies, Inc.,
8 * and is released under the GPL version 2 (see below), however due
9 * to the extra costs of supporting Windows Vista, OpenVPN Solutions
10 * LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
11 * license for versions 9.1 and higher prior to the official release of
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2
16 * as published by the Free Software Foundation.
18 * This program 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
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program (see the file COPYING included with this
25 * distribution); if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 //======================================================
30 // This driver is designed to work on Win 2000 or higher
31 // versions of Windows.
33 // It is SMP-safe and handles NDIS 5 power management.
35 // By default we operate as a "tap" virtual ethernet
36 // 802.3 interface, but we can emulate a "tun"
37 // interface (point-to-point IPv4) through the
38 // TAP_IOCTL_CONFIG_POINT_TO_POINT or
39 // TAP_IOCTL_CONFIG_TUN ioctl.
40 //======================================================
42 #include "../../autodefs/defs.h"
44 #error DDKVER_MAJOR must be defined as the major number of the DDK Version
47 #define NDIS_MINIPORT_DRIVER
48 #define BINARY_COMPATIBLE 0
49 #define NDIS50_MINIPORT 1
55 #define ALSO_DBGPRINT 1
56 #define DEBUGP_AT_DISPATCH 0
58 //========================================================
59 // Check for truncated IPv4 packets, log errors if found.
60 //========================================================
61 #define PACKET_TRUNCATION_CHECK 0
63 //========================================================
64 // EXPERIMENTAL -- Configure TAP device object to be
65 // accessible from non-administrative accounts, based
66 // on an advanced properties setting.
68 // Duplicates the functionality of OpenVPN's
69 // --allow-nonadmin directive.
70 //========================================================
71 #define ENABLE_NONADMIN 1
73 #if DDKVER_MAJOR < 5600
75 #include <ntstrsafe.h>
80 #include <ntstrsafe.h>
84 #include "constants.h"
91 #include "prototypes.h"
100 ((ta)->m_InterfaceIsRunning && (ta)->m_Extension.m_TapIsRunning)
102 #define INCREMENT_STAT(s) ++(s)
104 #define NAME_BUFFER_SIZE 80
106 //========================================================
108 //========================================================
110 NDIS_HANDLE g_NdisWrapperHandle
;
112 const UINT g_SupportedOIDList
[] = {
113 OID_GEN_HARDWARE_STATUS
,
114 OID_GEN_MEDIA_SUPPORTED
,
115 OID_GEN_MEDIA_IN_USE
,
116 OID_GEN_MAXIMUM_LOOKAHEAD
,
119 OID_GEN_TRANSMIT_BLOCK_SIZE
,
120 OID_GEN_RECEIVE_BLOCK_SIZE
,
121 OID_GEN_VENDOR_DESCRIPTION
,
122 OID_GEN_DRIVER_VERSION
,
127 OID_802_3_PERMANENT_ADDRESS
,
128 OID_802_3_CURRENT_ADDRESS
,
129 OID_GEN_RCV_NO_BUFFER
,
130 OID_802_3_RCV_ERROR_ALIGNMENT
,
131 OID_802_3_XMIT_ONE_COLLISION
,
132 OID_802_3_XMIT_MORE_COLLISIONS
,
133 OID_802_3_MULTICAST_LIST
,
134 OID_802_3_MAXIMUM_LIST_SIZE
,
136 OID_GEN_CURRENT_LOOKAHEAD
,
137 OID_GEN_CURRENT_PACKET_FILTER
,
138 OID_GEN_PROTOCOL_OPTIONS
,
139 OID_GEN_MAXIMUM_TOTAL_SIZE
,
140 OID_GEN_TRANSMIT_BUFFER_SPACE
,
141 OID_GEN_RECEIVE_BUFFER_SPACE
,
142 OID_GEN_MAXIMUM_FRAME_SIZE
,
143 OID_GEN_VENDOR_DRIVER_VERSION
,
144 OID_GEN_MAXIMUM_SEND_PACKETS
,
145 OID_GEN_MEDIA_CONNECT_STATUS
,
146 OID_GEN_SUPPORTED_LIST
149 //============================================================
151 //============================================================
152 #pragma NDIS_INIT_FUNCTION (DriverEntry)
155 DriverEntry (IN PDRIVER_OBJECT p_DriverObject
,
156 IN PUNICODE_STRING p_RegistryPath
)
158 NDIS_STATUS l_Status
= NDIS_STATUS_FAILURE
;
159 NDIS_MINIPORT_CHARACTERISTICS
*l_Properties
= NULL
;
161 //========================================================
162 // Notify NDIS that a new miniport driver is initializing.
163 //========================================================
165 NdisMInitializeWrapper (&g_NdisWrapperHandle
,
167 p_RegistryPath
, NULL
);
169 //======================
170 // Global initialization
171 //======================
174 MyDebugInit (10000); // Allocate debugging text space
177 if (!InitInstanceList ())
179 DEBUGP (("[TAP] Allocation failed for adapter instance list\n"));
183 //=======================================
184 // Set and register miniport entry points
185 //=======================================
187 l_Properties
= MemAlloc (sizeof (NDIS_MINIPORT_CHARACTERISTICS
), TRUE
);
189 if (l_Properties
== NULL
)
191 DEBUGP (("[TAP] Allocation failed for miniport entry points\n"));
195 l_Properties
->MajorNdisVersion
= TAP_NDIS_MAJOR_VERSION
;
196 l_Properties
->MinorNdisVersion
= TAP_NDIS_MINOR_VERSION
;
197 l_Properties
->InitializeHandler
= AdapterCreate
;
198 l_Properties
->HaltHandler
= AdapterHalt
;
199 l_Properties
->ResetHandler
= AdapterReset
; /* DISPATCH_LEVEL */
200 l_Properties
->TransferDataHandler
= AdapterReceive
; /* DISPATCH_LEVEL */
201 l_Properties
->SendHandler
= AdapterTransmit
; /* DISPATCH_LEVEL */
202 l_Properties
->QueryInformationHandler
= AdapterQuery
; /* DISPATCH_LEVEL */
203 l_Properties
->SetInformationHandler
= AdapterModify
; /* DISPATCH_LEVEL */
206 NdisMRegisterMiniport (g_NdisWrapperHandle
, l_Properties
,
207 sizeof (NDIS_MINIPORT_CHARACTERISTICS
)))
209 case NDIS_STATUS_SUCCESS
:
211 DEBUGP (("[TAP] version [%d.%d] %s %s registered miniport successfully\n",
212 TAP_DRIVER_MAJOR_VERSION
,
213 TAP_DRIVER_MINOR_VERSION
,
216 DEBUGP (("Registry Path: '%S'\n", p_RegistryPath
->Buffer
));
220 case NDIS_STATUS_BAD_CHARACTERISTICS
:
222 DEBUGP (("[TAP] Miniport characteristics were badly defined\n"));
223 NdisTerminateWrapper (g_NdisWrapperHandle
, NULL
);
227 case NDIS_STATUS_BAD_VERSION
:
230 (("[TAP] NDIS Version is wrong for the given characteristics\n"));
231 NdisTerminateWrapper (g_NdisWrapperHandle
, NULL
);
235 case NDIS_STATUS_RESOURCES
:
237 DEBUGP (("[TAP] Insufficient resources\n"));
238 NdisTerminateWrapper (g_NdisWrapperHandle
, NULL
);
243 case NDIS_STATUS_FAILURE
:
245 DEBUGP (("[TAP] Unknown fatal registration error\n"));
246 NdisTerminateWrapper (g_NdisWrapperHandle
, NULL
);
253 MemFree (l_Properties
, sizeof (NDIS_MINIPORT_CHARACTERISTICS
));
255 if (l_Status
== NDIS_STATUS_SUCCESS
)
256 NdisMRegisterUnloadHandler (g_NdisWrapperHandle
, TapDriverUnload
);
258 TapDriverUnload (p_DriverObject
);
263 //============================================================
265 //============================================================
267 TapDriverUnload (IN PDRIVER_OBJECT p_DriverObject
)
269 DEBUGP (("[TAP] version [%d.%d] %s %s unloaded, instances=%d, imbs=%d\n",
270 TAP_DRIVER_MAJOR_VERSION
,
271 TAP_DRIVER_MINOR_VERSION
,
275 InstanceMaxBucketSize()));
279 //==============================
280 // Free debugging text space
281 //==============================
287 //==========================================================
288 // Adapter Initialization
289 //==========================================================
290 NDIS_STATUS AdapterCreate
291 (OUT PNDIS_STATUS p_ErrorStatus
,
292 OUT PUINT p_MediaIndex
,
293 IN PNDIS_MEDIUM p_Media
,
294 IN UINT p_MediaCount
,
295 IN NDIS_HANDLE p_AdapterHandle
,
296 IN NDIS_HANDLE p_ConfigurationHandle
)
298 TapAdapterPointer l_Adapter
= NULL
;
300 NDIS_MEDIUM l_PreferredMedium
= NdisMedium802_3
; // Ethernet
301 BOOLEAN l_MacFromRegistry
= FALSE
;
306 BOOLEAN enable_non_admin
= FALSE
;
309 DEBUGP (("[TAP] AdapterCreate called\n"));
311 //====================================
312 // Make sure adapter type is supported
313 //====================================
316 l_Index
< p_MediaCount
&& p_Media
[l_Index
] != l_PreferredMedium
;
319 if (l_Index
== p_MediaCount
)
321 DEBUGP (("[TAP] Unsupported adapter type [wanted: %d]\n",
323 return NDIS_STATUS_UNSUPPORTED_MEDIA
;
326 *p_MediaIndex
= l_Index
;
328 //=========================================
329 // Allocate memory for TapAdapter structure
330 //=========================================
332 l_Adapter
= MemAlloc (sizeof (TapAdapter
), TRUE
);
334 if (l_Adapter
== NULL
)
336 DEBUGP (("[TAP] Couldn't allocate adapter memory\n"));
337 return NDIS_STATUS_RESOURCES
;
340 //==========================================
341 // Inform the NDIS library about significant
342 // features of our virtual NIC.
343 //==========================================
347 (NDIS_HANDLE
) l_Adapter
,
349 NDIS_ATTRIBUTE_DESERIALIZE
350 | NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT
351 | NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT
352 | NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND
,
353 NdisInterfaceInternal
);
355 //=====================================
356 // Initialize simple Adapter parameters
357 //=====================================
359 l_Adapter
->m_Lookahead
= DEFAULT_PACKET_LOOKAHEAD
;
360 l_Adapter
->m_Medium
= l_PreferredMedium
;
361 l_Adapter
->m_DeviceState
= '?';
362 l_Adapter
->m_MiniportAdapterHandle
= p_AdapterHandle
;
364 //==================================
365 // Allocate spinlock for controlling
366 // access to multicast address list.
367 //==================================
368 NdisAllocateSpinLock (&l_Adapter
->m_MCLock
);
369 l_Adapter
->m_MCLockAllocated
= TRUE
;
371 //====================================================
372 // Register a shutdown handler which will be called
373 // on system restart/shutdown to halt our virtual NIC.
374 //====================================================
376 NdisMRegisterAdapterShutdownHandler (p_AdapterHandle
, l_Adapter
,
378 l_Adapter
->m_RegisteredAdapterShutdownHandler
= TRUE
;
380 //============================================
381 // Get parameters from registry which were set
382 // in the adapter advanced properties dialog.
383 //============================================
386 NDIS_HANDLE configHandle
;
387 NDIS_CONFIGURATION_PARAMETER
*parm
;
389 // set defaults in case our registry query fails
390 l_Adapter
->m_MTU
= ETHERNET_MTU
;
391 l_Adapter
->m_MediaStateAlwaysConnected
= FALSE
;
392 l_Adapter
->m_MediaState
= FALSE
;
394 NdisOpenConfiguration (&status
, &configHandle
, p_ConfigurationHandle
);
395 if (status
!= NDIS_STATUS_SUCCESS
)
397 DEBUGP (("[TAP] Couldn't open adapter registry\n"));
398 AdapterFreeResources (l_Adapter
);
402 //====================================
403 // Allocate and construct adapter name
404 //====================================
407 NDIS_STRING mkey
= NDIS_STRING_CONST("MiniportName");
408 NDIS_STRING vkey
= NDIS_STRING_CONST("NdisVersion");
410 NDIS_CONFIGURATION_PARAMETER
*vparm
;
412 NdisReadConfiguration (&vstatus
, &vparm
, configHandle
, &vkey
, NdisParameterInteger
);
413 if (vstatus
== NDIS_STATUS_SUCCESS
)
414 DEBUGP (("[TAP] NdisReadConfiguration NdisVersion=%X\n", vparm
->ParameterData
.IntegerData
));
416 NdisReadConfiguration (&status
, &parm
, configHandle
, &mkey
, NdisParameterString
);
417 if (status
== NDIS_STATUS_SUCCESS
)
419 if (parm
->ParameterType
== NdisParameterString
)
421 DEBUGP (("[TAP] NdisReadConfiguration (MiniportName=%S)\n", parm
->ParameterData
.StringData
.Buffer
));
423 if (RtlUnicodeStringToAnsiString (
424 &l_Adapter
->m_NameAnsi
,
425 &parm
->ParameterData
.StringData
,
426 TRUE
) != STATUS_SUCCESS
)
428 DEBUGP (("[TAP] MiniportName failed\n"));
429 status
= NDIS_STATUS_RESOURCES
;
435 /* "MiniportName" is available only XP and above. Not on Windows 2000. */
436 if (vstatus
== NDIS_STATUS_SUCCESS
&& vparm
->ParameterData
.IntegerData
== 0x50000)
438 /* Fallback for Windows 2000 with NDIS version 5.00.00
439 Don't use this on Vista, 'NDIS_MINIPORT_BLOCK' was changed! */
440 if (RtlUnicodeStringToAnsiString (&l_Adapter
->m_NameAnsi
,
441 &((struct WIN2K_NDIS_MINIPORT_BLOCK
*) p_AdapterHandle
)->MiniportName
,
442 TRUE
) != STATUS_SUCCESS
)
444 DEBUGP (("[TAP] MiniportName (W2K) failed\n"));
445 status
= NDIS_STATUS_RESOURCES
;
449 DEBUGP (("[TAP] MiniportName (W2K) succeeded: %s\n", l_Adapter
->m_NameAnsi
.Buffer
));
450 status
= NDIS_STATUS_SUCCESS
;
456 /* Can't continue without name (see macro 'NAME') */
457 if (status
!= NDIS_STATUS_SUCCESS
|| !l_Adapter
->m_NameAnsi
.Buffer
)
459 NdisCloseConfiguration (configHandle
);
460 AdapterFreeResources (l_Adapter
);
461 DEBUGP (("[TAP] failed to get miniport name\n"));
462 return NDIS_STATUS_RESOURCES
;
465 /* Read MTU setting from registry */
467 NDIS_STRING key
= NDIS_STRING_CONST("MTU");
468 NdisReadConfiguration (&status
, &parm
, configHandle
,
469 &key
, NdisParameterInteger
);
470 if (status
== NDIS_STATUS_SUCCESS
)
472 if (parm
->ParameterType
== NdisParameterInteger
)
474 int mtu
= parm
->ParameterData
.IntegerData
;
475 if (mtu
< MINIMUM_MTU
)
477 if (mtu
> MAXIMUM_MTU
)
479 l_Adapter
->m_MTU
= mtu
;
484 /* Read Media Status setting from registry */
486 NDIS_STRING key
= NDIS_STRING_CONST("MediaStatus");
487 NdisReadConfiguration (&status
, &parm
, configHandle
,
488 &key
, NdisParameterInteger
);
489 if (status
== NDIS_STATUS_SUCCESS
)
491 if (parm
->ParameterType
== NdisParameterInteger
)
493 if (parm
->ParameterData
.IntegerData
)
495 l_Adapter
->m_MediaStateAlwaysConnected
= TRUE
;
496 l_Adapter
->m_MediaState
= TRUE
;
503 /* Read AllowNonAdmin setting from registry */
505 NDIS_STRING key
= NDIS_STRING_CONST("AllowNonAdmin");
506 NdisReadConfiguration (&status
, &parm
, configHandle
,
507 &key
, NdisParameterInteger
);
508 if (status
== NDIS_STATUS_SUCCESS
)
510 if (parm
->ParameterType
== NdisParameterInteger
)
512 if (parm
->ParameterData
.IntegerData
)
514 enable_non_admin
= TRUE
;
521 /* Read optional MAC setting from registry */
523 NDIS_STRING key
= NDIS_STRING_CONST("MAC");
524 ANSI_STRING mac_string
;
525 NdisReadConfiguration (&status
, &parm
, configHandle
,
526 &key
, NdisParameterString
);
527 if (status
== NDIS_STATUS_SUCCESS
)
529 if (parm
->ParameterType
== NdisParameterString
)
531 if (RtlUnicodeStringToAnsiString (&mac_string
, &parm
->ParameterData
.StringData
, TRUE
) == STATUS_SUCCESS
)
533 l_MacFromRegistry
= ParseMAC (l_Adapter
->m_MAC
, mac_string
.Buffer
);
534 RtlFreeAnsiString (&mac_string
);
540 NdisCloseConfiguration (configHandle
);
542 DEBUGP (("[%s] MTU=%d\n", NAME (l_Adapter
), l_Adapter
->m_MTU
));
545 //==================================
546 // Store and update MAC address info
547 //==================================
549 if (!l_MacFromRegistry
)
550 GenerateRandomMac (l_Adapter
->m_MAC
, NAME (l_Adapter
));
552 DEBUGP (("[%s] Using MAC %x:%x:%x:%x:%x:%x\n",
554 l_Adapter
->m_MAC
[0], l_Adapter
->m_MAC
[1], l_Adapter
->m_MAC
[2],
555 l_Adapter
->m_MAC
[3], l_Adapter
->m_MAC
[4], l_Adapter
->m_MAC
[5]));
562 for (i
= 0; i
< sizeof (MACADDR
); ++i
)
563 l_Adapter
->m_MAC_Broadcast
[i
] = 0xFF;
566 //====================================
567 // Initialize TAP device
568 //====================================
570 NDIS_STATUS tap_status
;
571 tap_status
= CreateTapDevice (&l_Adapter
->m_Extension
, NAME (l_Adapter
));
572 if (tap_status
!= NDIS_STATUS_SUCCESS
)
574 AdapterFreeResources (l_Adapter
);
575 DEBUGP (("[TAP] CreateTapDevice failed\n"));
580 if (!AddAdapterToInstanceList (l_Adapter
))
583 TapDeviceFreeResources (&l_Adapter
->m_Extension
);
584 AdapterFreeResources (l_Adapter
);
585 DEBUGP (("[TAP] AddAdapterToInstanceList failed\n"));
586 return NDIS_STATUS_RESOURCES
;
589 l_Adapter
->m_InterfaceIsRunning
= TRUE
;
592 if (enable_non_admin
)
593 AllowNonAdmin (&l_Adapter
->m_Extension
);
596 return NDIS_STATUS_SUCCESS
;
600 AdapterHalt (IN NDIS_HANDLE p_AdapterContext
)
604 TapAdapterPointer l_Adapter
= (TapAdapterPointer
) p_AdapterContext
;
608 l_Adapter
->m_InterfaceIsRunning
= FALSE
;
610 DEBUGP (("[%s] is being halted\n", NAME (l_Adapter
)));
612 DestroyTapDevice (&l_Adapter
->m_Extension
);
615 DEBUGP (("[%s] Freeing Resources\n", NAME (l_Adapter
)));
616 AdapterFreeResources (l_Adapter
);
618 status
= RemoveAdapterFromInstanceList (l_Adapter
);
619 DEBUGP (("[TAP] RemoveAdapterFromInstanceList returned %d\n", (int) status
));
621 DEBUGP (("[TAP] version [%d.%d] %s %s AdapterHalt returning\n",
622 TAP_DRIVER_MAJOR_VERSION
,
623 TAP_DRIVER_MINOR_VERSION
,
629 AdapterFreeResources (TapAdapterPointer p_Adapter
)
631 MYASSERT (!p_Adapter
->m_CalledAdapterFreeResources
);
632 p_Adapter
->m_CalledAdapterFreeResources
= TRUE
;
634 if (p_Adapter
->m_NameAnsi
.Buffer
)
635 RtlFreeAnsiString (&p_Adapter
->m_NameAnsi
);
637 if (p_Adapter
->m_RegisteredAdapterShutdownHandler
)
638 NdisMDeregisterAdapterShutdownHandler (p_Adapter
->m_MiniportAdapterHandle
);
640 if (p_Adapter
->m_MCLockAllocated
)
641 NdisFreeSpinLock (&p_Adapter
->m_MCLock
);
645 DestroyTapDevice (TapExtensionPointer p_Extension
)
647 DEBUGP (("[%s] Destroying tap device\n", p_Extension
->m_TapName
));
649 //======================================
650 // Let clients know we are shutting down
651 //======================================
652 p_Extension
->m_TapIsRunning
= FALSE
;
653 p_Extension
->m_TapOpens
= 0;
654 p_Extension
->m_Halt
= TRUE
;
656 //=====================================
657 // If we are concurrently executing in
658 // TapDeviceHook or AdapterTransmit,
659 // give those calls time to finish.
660 // Note that we must be running at IRQL
661 // < DISPATCH_LEVEL in order to call
663 //=====================================
666 //===========================================================
667 // Exhaust IRP and packet queues. Any pending IRPs will
668 // be cancelled, causing user-space to get this error
669 // on overlapped reads:
670 // The I/O operation has been aborted because of either a
671 // thread exit or an application request. (code=995)
672 // It's important that user-space close the device handle
673 // when this code is returned, so that when we finally
674 // do a NdisMDeregisterDevice, the device reference count
675 // is 0. Otherwise the driver will not unload even if the
676 // the last adapter has been halted.
677 //===========================================================
678 FlushQueues (p_Extension
);
679 NdisMSleep (500000); // give user space time to respond to IRP cancel
681 TapDeviceFreeResources (p_Extension
);
685 TapDeviceFreeResources (TapExtensionPointer p_Extension
)
687 MYASSERT (p_Extension
);
688 MYASSERT (!p_Extension
->m_CalledTapDeviceFreeResources
);
689 p_Extension
->m_CalledTapDeviceFreeResources
= TRUE
;
691 if (p_Extension
->m_PacketQueue
)
692 QueueFree (p_Extension
->m_PacketQueue
);
693 if (p_Extension
->m_IrpQueue
)
694 QueueFree (p_Extension
->m_IrpQueue
);
695 if (p_Extension
->m_InjectQueue
)
696 QueueFree (p_Extension
->m_InjectQueue
);
698 if (p_Extension
->m_CreatedUnicodeLinkName
)
699 RtlFreeUnicodeString (&p_Extension
->m_UnicodeLinkName
);
701 //==========================================================
702 // According to DDK docs, the device is not actually deleted
703 // until its reference count falls to zero. That means we
704 // still need to gracefully fail TapDeviceHook requests
705 // after this point, otherwise ugly things would happen if
706 // the device was disabled (e.g. in the network connections
707 // control panel) while a userspace app still held an open
708 // file handle to it.
709 //==========================================================
711 if (p_Extension
->m_TapDevice
)
714 status
= (NdisMDeregisterDevice (p_Extension
->m_TapDeviceHandle
)
715 == NDIS_STATUS_SUCCESS
);
716 DEBUGP (("[TAP] Deregistering TAP device, status=%d\n", (int)status
));
719 if (p_Extension
->m_TapName
)
720 MemFree (p_Extension
->m_TapName
, NAME_BUFFER_SIZE
);
722 if (p_Extension
->m_InjectDpcInitialized
)
723 KeRemoveQueueDpc (&p_Extension
->m_InjectDpc
);
725 if (p_Extension
->m_AllocatedSpinlocks
)
727 NdisFreeSpinLock (&p_Extension
->m_QueueLock
);
728 NdisFreeSpinLock (&p_Extension
->m_InjectLock
);
732 //========================================================================
733 // Tap Device Initialization
734 //========================================================================
737 CreateTapDevice (TapExtensionPointer p_Extension
, const char *p_Name
)
739 # define SIZEOF_DISPATCH (sizeof(PDRIVER_DISPATCH) * (IRP_MJ_MAXIMUM_FUNCTION + 1))
740 PDRIVER_DISPATCH
*l_Dispatch
= NULL
;
741 ANSI_STRING l_TapString
, l_LinkString
;
742 UNICODE_STRING l_TapUnicode
;
743 BOOLEAN l_FreeTapUnicode
= FALSE
;
744 NTSTATUS l_Status
, l_Return
= NDIS_STATUS_SUCCESS
;
745 const char *l_UsableName
;
747 DEBUGP (("[TAP] version [%d.%d] creating tap device: %s\n",
748 TAP_DRIVER_MAJOR_VERSION
,
749 TAP_DRIVER_MINOR_VERSION
,
752 NdisZeroMemory (p_Extension
, sizeof (TapExtension
));
754 INIT_MUTEX (&p_Extension
->m_OpenCloseMutex
);
756 l_LinkString
.Buffer
= NULL
;
757 l_TapString
.Buffer
= NULL
;
759 l_TapString
.MaximumLength
= l_LinkString
.MaximumLength
= NAME_BUFFER_SIZE
;
761 //=======================================
762 // Set TAP device entry points
763 //=======================================
765 if ((l_Dispatch
= MemAlloc (SIZEOF_DISPATCH
, TRUE
)) == NULL
)
767 DEBUGP (("[%s] couldn't alloc TAP dispatch table\n", p_Name
));
768 l_Return
= NDIS_STATUS_RESOURCES
;
772 l_Dispatch
[IRP_MJ_DEVICE_CONTROL
] = TapDeviceHook
;
773 l_Dispatch
[IRP_MJ_READ
] = TapDeviceHook
;
774 l_Dispatch
[IRP_MJ_WRITE
] = TapDeviceHook
;
775 l_Dispatch
[IRP_MJ_CREATE
] = TapDeviceHook
;
776 l_Dispatch
[IRP_MJ_CLOSE
] = TapDeviceHook
;
778 //==================================
779 // Find the beginning of the GUID
780 //==================================
781 l_UsableName
= p_Name
;
782 while (*l_UsableName
!= '{')
784 if (*l_UsableName
== '\0')
786 DEBUGP (("[%s] couldn't find leading '{' in name\n", p_Name
));
787 l_Return
= NDIS_STATUS_RESOURCES
;
793 //==================================
794 // Allocate pool for TAP device name
795 //==================================
797 if ((p_Extension
->m_TapName
= l_TapString
.Buffer
=
798 MemAlloc (NAME_BUFFER_SIZE
, TRUE
)) == NULL
)
800 DEBUGP (("[%s] couldn't alloc TAP name buffer\n", p_Name
));
801 l_Return
= NDIS_STATUS_RESOURCES
;
805 //================================================
806 // Allocate pool for TAP symbolic link name buffer
807 //================================================
809 if ((l_LinkString
.Buffer
=
810 MemAlloc (NAME_BUFFER_SIZE
, TRUE
)) == NULL
)
812 DEBUGP (("[%s] couldn't alloc TAP symbolic link name buffer\n",
814 l_Return
= NDIS_STATUS_RESOURCES
;
818 //=======================================================
819 // Set TAP device name
820 //=======================================================
822 l_Status
= RtlStringCchPrintfExA
824 l_TapString
.MaximumLength
,
827 STRSAFE_FILL_BEHIND_NULL
| STRSAFE_IGNORE_NULLS
,
833 if (l_Status
!= STATUS_SUCCESS
)
835 DEBUGP (("[%s] couldn't format TAP device name\n",
837 l_Return
= NDIS_STATUS_RESOURCES
;
840 l_TapString
.Length
= (USHORT
) strlen (l_TapString
.Buffer
);
842 DEBUGP (("TAP DEV NAME: '%s'\n", l_TapString
.Buffer
));
844 //=======================================================
846 //=======================================================
848 l_Status
= RtlStringCchPrintfExA
849 (l_LinkString
.Buffer
,
850 l_LinkString
.MaximumLength
,
853 STRSAFE_FILL_BEHIND_NULL
| STRSAFE_IGNORE_NULLS
,
859 if (l_Status
!= STATUS_SUCCESS
)
861 DEBUGP (("[%s] couldn't format TAP device symbolic link\n",
863 l_Return
= NDIS_STATUS_RESOURCES
;
866 l_LinkString
.Length
= (USHORT
) strlen (l_LinkString
.Buffer
);
868 DEBUGP (("TAP LINK NAME: '%s'\n", l_LinkString
.Buffer
));
870 //==================================================
871 // Convert strings to unicode
872 //==================================================
873 if (RtlAnsiStringToUnicodeString (&l_TapUnicode
, &l_TapString
, TRUE
) !=
876 DEBUGP (("[%s] couldn't alloc TAP unicode name buffer\n",
878 l_Return
= NDIS_STATUS_RESOURCES
;
881 l_FreeTapUnicode
= TRUE
;
883 if (RtlAnsiStringToUnicodeString
884 (&p_Extension
->m_UnicodeLinkName
, &l_LinkString
, TRUE
)
888 (("[%s] Couldn't allocate unicode string for symbolic link name\n",
890 l_Return
= NDIS_STATUS_RESOURCES
;
893 p_Extension
->m_CreatedUnicodeLinkName
= TRUE
;
895 //==================================================
896 // Create new TAP device with symbolic
897 // link and associate with adapter.
898 //==================================================
900 l_Status
= NdisMRegisterDevice
901 (g_NdisWrapperHandle
,
903 &p_Extension
->m_UnicodeLinkName
,
905 &p_Extension
->m_TapDevice
,
906 &p_Extension
->m_TapDeviceHandle
909 if (l_Status
!= STATUS_SUCCESS
)
911 DEBUGP (("[%s] couldn't be created\n", p_Name
));
912 l_Return
= NDIS_STATUS_RESOURCES
;
916 /* Set TAP device flags */
917 p_Extension
->m_TapDevice
->Flags
|= DO_DIRECT_IO
;
919 //========================================================
920 // Initialize Packet and IRP queues.
922 // The packet queue is used to buffer data which has been
923 // "transmitted" by the virtual NIC, before user space
924 // has had a chance to read it.
926 // The IRP queue is used to buffer pending I/O requests
927 // from userspace, i.e. read requests on the TAP device
928 // waiting for the system to "transmit" something through
931 // Basically, packets in the packet queue are used
932 // to satisfy IRP requests in the IRP queue.
934 // QueueLock is used to lock the packet queue used
935 // for the TAP-Win32 NIC -> User Space packet flow direction.
937 // All accesses to packet or IRP queues should be
938 // bracketed by the QueueLock spinlock,
939 // in order to be SMP-safe.
940 //========================================================
942 NdisAllocateSpinLock (&p_Extension
->m_QueueLock
);
943 NdisAllocateSpinLock (&p_Extension
->m_InjectLock
);
944 p_Extension
->m_AllocatedSpinlocks
= TRUE
;
946 p_Extension
->m_PacketQueue
= QueueInit (PACKET_QUEUE_SIZE
);
947 p_Extension
->m_IrpQueue
= QueueInit (IRP_QUEUE_SIZE
);
948 p_Extension
->m_InjectQueue
= QueueInit (INJECT_QUEUE_SIZE
);
949 if (!p_Extension
->m_PacketQueue
950 || !p_Extension
->m_IrpQueue
951 || !p_Extension
->m_InjectQueue
)
953 DEBUGP (("[%s] couldn't alloc TAP queues\n", p_Name
));
954 l_Return
= NDIS_STATUS_RESOURCES
;
958 //=================================================================
959 // Initialize deferred procedure call for DHCP/ARP packet injection
960 //=================================================================
962 KeInitializeDpc (&p_Extension
->m_InjectDpc
, InjectPacketDpc
, NULL
);
963 p_Extension
->m_InjectDpcInitialized
= TRUE
;
965 //========================
966 // Finalize initialization
967 //========================
969 p_Extension
->m_TapIsRunning
= TRUE
;
971 DEBUGP (("[%s] successfully created TAP device [%s]\n", p_Name
,
972 p_Extension
->m_TapName
));
975 if (l_FreeTapUnicode
)
976 RtlFreeUnicodeString (&l_TapUnicode
);
977 if (l_LinkString
.Buffer
)
978 MemFree (l_LinkString
.Buffer
, NAME_BUFFER_SIZE
);
980 MemFree (l_Dispatch
, SIZEOF_DISPATCH
);
982 if (l_Return
!= NDIS_STATUS_SUCCESS
)
983 TapDeviceFreeResources (p_Extension
);
987 #undef SIZEOF_DISPATCH
989 //========================================================
991 //========================================================
993 AdapterReset (OUT PBOOLEAN p_AddressingReset
, IN NDIS_HANDLE p_AdapterContext
)
995 TapAdapterPointer l_Adapter
= (TapAdapterPointer
) p_AdapterContext
;
996 DEBUGP (("[%s] is resetting\n", NAME (l_Adapter
)));
997 return NDIS_STATUS_SUCCESS
;
1000 NDIS_STATUS AdapterReceive
1001 (OUT PNDIS_PACKET p_Packet
,
1002 OUT PUINT p_Transferred
,
1003 IN NDIS_HANDLE p_AdapterContext
,
1004 IN NDIS_HANDLE p_ReceiveContext
,
1006 IN UINT p_ToTransfer
)
1008 return NDIS_STATUS_SUCCESS
;
1011 //==============================================================
1012 // Adapter Option Query/Modification
1013 //==============================================================
1014 NDIS_STATUS AdapterQuery
1015 (IN NDIS_HANDLE p_AdapterContext
,
1018 IN ULONG p_BufferLength
,
1019 OUT PULONG p_BytesWritten
, OUT PULONG p_BytesNeeded
)
1021 TapAdapterPointer l_Adapter
= (TapAdapterPointer
) p_AdapterContext
;
1022 TapAdapterQuery l_Query
, *l_QueryPtr
= &l_Query
;
1023 NDIS_STATUS l_Status
= NDIS_STATUS_SUCCESS
;
1024 UINT l_QueryLength
= 4;
1025 BOOLEAN lock_succeeded
;
1027 NdisZeroMemory (&l_Query
, sizeof (l_Query
));
1031 //===================================================================
1032 // Vendor & Driver version Info
1033 //===================================================================
1034 case OID_GEN_VENDOR_DESCRIPTION
:
1035 l_QueryPtr
= (TapAdapterQueryPointer
) PRODUCT_STRING
;
1036 l_QueryLength
= strlen (PRODUCT_STRING
) + 1;
1039 case OID_GEN_VENDOR_ID
:
1040 l_Query
.m_Long
= 0xffffff;
1043 case OID_GEN_DRIVER_VERSION
:
1045 (((USHORT
) TAP_NDIS_MAJOR_VERSION
) << 8 | (USHORT
)
1046 TAP_NDIS_MINOR_VERSION
);
1047 l_QueryLength
= sizeof (unsigned short);
1050 case OID_GEN_VENDOR_DRIVER_VERSION
:
1052 (((USHORT
) TAP_DRIVER_MAJOR_VERSION
) << 8 | (USHORT
)
1053 TAP_DRIVER_MINOR_VERSION
);
1056 //=================================================================
1058 //=================================================================
1059 case OID_GEN_RCV_NO_BUFFER
:
1063 case OID_802_3_RCV_ERROR_ALIGNMENT
:
1067 case OID_802_3_XMIT_ONE_COLLISION
:
1071 case OID_802_3_XMIT_MORE_COLLISIONS
:
1075 case OID_GEN_XMIT_OK
:
1076 l_Query
.m_Long
= l_Adapter
->m_Tx
;
1079 case OID_GEN_RCV_OK
:
1080 l_Query
.m_Long
= l_Adapter
->m_Rx
;
1083 case OID_GEN_XMIT_ERROR
:
1084 l_Query
.m_Long
= l_Adapter
->m_TxErr
;
1087 case OID_GEN_RCV_ERROR
:
1088 l_Query
.m_Long
= l_Adapter
->m_RxErr
;
1091 //===================================================================
1092 // Device & Protocol Options
1093 //===================================================================
1094 case OID_GEN_SUPPORTED_LIST
:
1095 l_QueryPtr
= (TapAdapterQueryPointer
) g_SupportedOIDList
;
1096 l_QueryLength
= sizeof (g_SupportedOIDList
);
1099 case OID_GEN_MAC_OPTIONS
:
1100 // This MUST be here !!!
1101 l_Query
.m_Long
= (NDIS_MAC_OPTION_RECEIVE_SERIALIZED
1102 | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA
1103 | NDIS_MAC_OPTION_NO_LOOPBACK
1104 | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND
);
1108 case OID_GEN_CURRENT_PACKET_FILTER
:
1110 (NDIS_PACKET_TYPE_ALL_LOCAL
|
1111 NDIS_PACKET_TYPE_BROADCAST
|
1112 NDIS_PACKET_TYPE_DIRECTED
| NDIS_PACKET_TYPE_ALL_FUNCTIONAL
);
1116 case OID_GEN_PROTOCOL_OPTIONS
:
1120 //==================================================================
1122 //==================================================================
1123 case OID_GEN_MEDIA_CONNECT_STATUS
:
1124 l_Query
.m_Long
= l_Adapter
->m_MediaState
1125 ? NdisMediaStateConnected
: NdisMediaStateDisconnected
;
1128 case OID_GEN_HARDWARE_STATUS
:
1129 l_Query
.m_HardwareStatus
= NdisHardwareStatusReady
;
1130 l_QueryLength
= sizeof (NDIS_HARDWARE_STATUS
);
1133 case OID_GEN_MEDIA_SUPPORTED
:
1134 case OID_GEN_MEDIA_IN_USE
:
1135 l_Query
.m_Medium
= l_Adapter
->m_Medium
;
1136 l_QueryLength
= sizeof (NDIS_MEDIUM
);
1139 case OID_GEN_PHYSICAL_MEDIUM
:
1140 l_Query
.m_PhysicalMedium
= NdisPhysicalMediumUnspecified
;
1141 l_QueryLength
= sizeof (NDIS_PHYSICAL_MEDIUM
);
1144 case OID_GEN_LINK_SPEED
:
1145 l_Query
.m_Long
= 100000; // rate / 100 bps
1148 case OID_802_3_PERMANENT_ADDRESS
:
1149 case OID_802_3_CURRENT_ADDRESS
:
1150 COPY_MAC (l_Query
.m_MacAddress
, l_Adapter
->m_MAC
);
1151 l_QueryLength
= sizeof (MACADDR
);
1154 //==================================================================
1156 //==================================================================
1158 case OID_GEN_MAXIMUM_SEND_PACKETS
:
1162 case OID_802_3_MAXIMUM_LIST_SIZE
:
1163 l_Query
.m_Long
= NIC_MAX_MCAST_LIST
;
1166 case OID_GEN_CURRENT_LOOKAHEAD
:
1167 l_Query
.m_Long
= l_Adapter
->m_Lookahead
;
1170 case OID_GEN_MAXIMUM_LOOKAHEAD
:
1171 case OID_GEN_MAXIMUM_TOTAL_SIZE
:
1172 case OID_GEN_RECEIVE_BUFFER_SPACE
:
1173 case OID_GEN_RECEIVE_BLOCK_SIZE
:
1174 l_Query
.m_Long
= DEFAULT_PACKET_LOOKAHEAD
;
1177 case OID_GEN_MAXIMUM_FRAME_SIZE
:
1178 case OID_GEN_TRANSMIT_BLOCK_SIZE
:
1179 case OID_GEN_TRANSMIT_BUFFER_SPACE
:
1180 l_Query
.m_Long
= l_Adapter
->m_MTU
;
1183 case OID_PNP_CAPABILITIES
:
1186 PNDIS_PNP_CAPABILITIES pPNPCapabilities
;
1187 PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct
;
1189 if (p_BufferLength
>= sizeof (NDIS_PNP_CAPABILITIES
))
1191 pPNPCapabilities
= (PNDIS_PNP_CAPABILITIES
) (p_Buffer
);
1194 // Setting up the buffer to be returned
1195 // to the Protocol above the Passthru miniport
1197 pPMstruct
= &pPNPCapabilities
->WakeUpCapabilities
;
1198 pPMstruct
->MinMagicPacketWakeUp
= NdisDeviceStateUnspecified
;
1199 pPMstruct
->MinPatternWakeUp
= NdisDeviceStateUnspecified
;
1200 pPMstruct
->MinLinkChangeWakeUp
= NdisDeviceStateUnspecified
;
1202 l_QueryLength
= sizeof (NDIS_PNP_CAPABILITIES
);
1206 case OID_PNP_QUERY_POWER
:
1209 // Required OIDs that we don't support
1211 case OID_GEN_SUPPORTED_GUIDS
:
1212 case OID_GEN_MEDIA_CAPABILITIES
:
1213 case OID_TCP_TASK_OFFLOAD
:
1214 case OID_FFP_SUPPORT
:
1215 l_Status
= NDIS_STATUS_INVALID_OID
;
1218 // Optional stats OIDs
1220 case OID_GEN_DIRECTED_BYTES_XMIT
:
1221 case OID_GEN_DIRECTED_FRAMES_XMIT
:
1222 case OID_GEN_MULTICAST_BYTES_XMIT
:
1223 case OID_GEN_MULTICAST_FRAMES_XMIT
:
1224 case OID_GEN_BROADCAST_BYTES_XMIT
:
1225 case OID_GEN_BROADCAST_FRAMES_XMIT
:
1226 case OID_GEN_DIRECTED_BYTES_RCV
:
1227 case OID_GEN_DIRECTED_FRAMES_RCV
:
1228 case OID_GEN_MULTICAST_BYTES_RCV
:
1229 case OID_GEN_MULTICAST_FRAMES_RCV
:
1230 case OID_GEN_BROADCAST_BYTES_RCV
:
1231 case OID_GEN_BROADCAST_FRAMES_RCV
:
1232 l_Status
= NDIS_STATUS_INVALID_OID
;
1235 //===================================================================
1237 //===================================================================
1239 DEBUGP (("[%s] Unhandled OID %lx\n", NAME (l_Adapter
), p_OID
));
1240 l_Status
= NDIS_STATUS_INVALID_OID
;
1244 if (l_Status
!= NDIS_STATUS_SUCCESS
)
1246 else if (l_QueryLength
> p_BufferLength
)
1248 l_Status
= NDIS_STATUS_INVALID_LENGTH
;
1249 *p_BytesNeeded
= l_QueryLength
;
1252 NdisMoveMemory (p_Buffer
, (PVOID
) l_QueryPtr
,
1253 (*p_BytesWritten
= l_QueryLength
));
1258 NDIS_STATUS AdapterModify
1259 (IN NDIS_HANDLE p_AdapterContext
,
1262 IN ULONG p_BufferLength
,
1263 OUT PULONG p_BytesRead
,
1264 OUT PULONG p_BytesNeeded
)
1266 TapAdapterQueryPointer l_Query
= (TapAdapterQueryPointer
) p_Buffer
;
1267 TapAdapterPointer l_Adapter
= (TapAdapterPointer
) p_AdapterContext
;
1268 NDIS_STATUS l_Status
= NDIS_STATUS_INVALID_OID
;
1273 //==================================================================
1275 //==================================================================
1276 case OID_802_3_MULTICAST_LIST
:
1277 DEBUGP (("[%s] Setting [OID_802_3_MULTICAST_LIST]\n",
1280 *p_BytesNeeded
= sizeof (ETH_ADDR
);
1281 *p_BytesRead
= p_BufferLength
;
1283 if (p_BufferLength
% sizeof (ETH_ADDR
))
1284 l_Status
= NDIS_STATUS_INVALID_LENGTH
;
1285 else if (p_BufferLength
> sizeof (MC_LIST
))
1287 l_Status
= NDIS_STATUS_MULTICAST_FULL
;
1288 *p_BytesNeeded
= sizeof (MC_LIST
);
1292 NdisAcquireSpinLock (&l_Adapter
->m_MCLock
);
1294 NdisZeroMemory(&l_Adapter
->m_MCList
, sizeof (MC_LIST
));
1296 NdisMoveMemory(&l_Adapter
->m_MCList
,
1300 l_Adapter
->m_MCListSize
= p_BufferLength
/ sizeof (ETH_ADDR
);
1302 NdisReleaseSpinLock (&l_Adapter
->m_MCLock
);
1304 l_Status
= NDIS_STATUS_SUCCESS
;
1308 case OID_GEN_CURRENT_PACKET_FILTER
:
1309 l_Status
= NDIS_STATUS_INVALID_LENGTH
;
1312 if (p_BufferLength
>= sizeof (ULONG
))
1315 (("[%s] Setting [OID_GEN_CURRENT_PACKET_FILTER] to [0x%02lx]\n",
1316 NAME (l_Adapter
), l_Query
->m_Long
));
1317 l_Status
= NDIS_STATUS_SUCCESS
;
1318 *p_BytesRead
= sizeof (ULONG
);
1322 case OID_GEN_CURRENT_LOOKAHEAD
:
1323 if (p_BufferLength
< sizeof (ULONG
))
1325 l_Status
= NDIS_STATUS_INVALID_LENGTH
;
1328 else if (l_Query
->m_Long
> DEFAULT_PACKET_LOOKAHEAD
1329 || l_Query
->m_Long
<= 0)
1331 l_Status
= NDIS_STATUS_INVALID_DATA
;
1335 DEBUGP (("[%s] Setting [OID_GEN_CURRENT_LOOKAHEAD] to [%d]\n",
1336 NAME (l_Adapter
), l_Query
->m_Long
));
1337 l_Adapter
->m_Lookahead
= l_Query
->m_Long
;
1338 l_Status
= NDIS_STATUS_SUCCESS
;
1339 *p_BytesRead
= sizeof (ULONG
);
1343 case OID_GEN_NETWORK_LAYER_ADDRESSES
:
1344 l_Status
= NDIS_STATUS_SUCCESS
;
1345 *p_BytesRead
= *p_BytesNeeded
= 0;
1348 case OID_GEN_TRANSPORT_HEADER_OFFSET
:
1349 l_Status
= NDIS_STATUS_SUCCESS
;
1350 *p_BytesRead
= *p_BytesNeeded
= 0;
1353 case OID_PNP_SET_POWER
:
1356 NDIS_DEVICE_POWER_STATE NewDeviceState
;
1358 NewDeviceState
= (*(PNDIS_DEVICE_POWER_STATE
) p_Buffer
);
1360 switch (NewDeviceState
)
1362 case NdisDeviceStateD0
:
1363 l_Adapter
->m_DeviceState
= '0';
1365 case NdisDeviceStateD1
:
1366 l_Adapter
->m_DeviceState
= '1';
1368 case NdisDeviceStateD2
:
1369 l_Adapter
->m_DeviceState
= '2';
1371 case NdisDeviceStateD3
:
1372 l_Adapter
->m_DeviceState
= '3';
1375 l_Adapter
->m_DeviceState
= '?';
1379 l_Status
= NDIS_STATUS_FAILURE
;
1382 // Check for invalid length
1384 if (p_BufferLength
< sizeof (NDIS_DEVICE_POWER_STATE
))
1386 l_Status
= NDIS_STATUS_INVALID_LENGTH
;
1390 if (NewDeviceState
> NdisDeviceStateD0
)
1392 l_Adapter
->m_InterfaceIsRunning
= FALSE
;
1393 DEBUGP (("[%s] Power management device state OFF\n",
1398 l_Adapter
->m_InterfaceIsRunning
= TRUE
;
1399 DEBUGP (("[%s] Power management device state ON\n",
1403 l_Status
= NDIS_STATUS_SUCCESS
;
1407 if (l_Status
== NDIS_STATUS_SUCCESS
)
1409 *p_BytesRead
= sizeof (NDIS_DEVICE_POWER_STATE
);
1415 *p_BytesNeeded
= sizeof (NDIS_DEVICE_POWER_STATE
);
1419 case OID_PNP_REMOVE_WAKE_UP_PATTERN
:
1420 case OID_PNP_ADD_WAKE_UP_PATTERN
:
1421 l_Status
= NDIS_STATUS_SUCCESS
;
1422 *p_BytesRead
= *p_BytesNeeded
= 0;
1426 DEBUGP (("[%s] Can't set value for OID %lx\n", NAME (l_Adapter
),
1428 l_Status
= NDIS_STATUS_INVALID_OID
;
1429 *p_BytesRead
= *p_BytesNeeded
= 0;
1436 //====================================================================
1437 // Adapter Transmission
1438 //====================================================================
1440 AdapterTransmit (IN NDIS_HANDLE p_AdapterContext
,
1441 IN PNDIS_PACKET p_Packet
,
1444 TapAdapterPointer l_Adapter
= (TapAdapterPointer
) p_AdapterContext
;
1445 ULONG l_Index
= 0, l_PacketLength
= 0;
1446 UINT l_BufferLength
= 0;
1448 TapPacketPointer l_PacketBuffer
;
1449 PNDIS_BUFFER l_NDIS_Buffer
;
1453 NdisQueryPacket (p_Packet
, NULL
, NULL
, &l_NDIS_Buffer
, &l_PacketLength
);
1455 //====================================================
1456 // Here we abandon the transmission attempt if any of
1457 // the parameters is wrong or memory allocation fails
1458 // but we do not indicate failure. The packet is
1459 // silently dropped.
1460 //====================================================
1462 if (l_PacketLength
< ETHERNET_HEADER_SIZE
|| l_PacketLength
> 65535)
1464 else if (!l_Adapter
->m_Extension
.m_TapOpens
|| !l_Adapter
->m_MediaState
)
1465 goto exit_success
; // Nothing is bound to the TAP device
1467 if (NdisAllocateMemoryWithTag (&l_PacketBuffer
,
1468 TAP_PACKET_SIZE (l_PacketLength
),
1469 '5PAT') != NDIS_STATUS_SUCCESS
)
1470 goto exit_no_resources
;
1472 if (l_PacketBuffer
== NULL
)
1473 goto exit_no_resources
;
1475 l_PacketBuffer
->m_SizeFlags
= (l_PacketLength
& TP_SIZE_MASK
);
1477 //===========================
1478 // Reassemble packet contents
1479 //===========================
1484 while (l_NDIS_Buffer
&& l_Index
< l_PacketLength
)
1487 NdisQueryBuffer (l_NDIS_Buffer
, (PVOID
*) & l_Buffer
,
1489 newlen
= l_Index
+ l_BufferLength
;
1490 if (newlen
> l_PacketLength
)
1493 goto no_queue
; /* overflow */
1495 NdisMoveMemory (l_PacketBuffer
->m_Data
+ l_Index
, l_Buffer
,
1498 NdisGetNextBuffer (l_NDIS_Buffer
, &l_NDIS_Buffer
);
1500 if (l_Index
!= l_PacketLength
)
1503 goto no_queue
; /* underflow */
1506 DUMP_PACKET ("AdapterTransmit", l_PacketBuffer
->m_Data
, l_PacketLength
);
1508 //=====================================================
1509 // If IPv4 packet, check whether or not packet
1511 //=====================================================
1512 #if PACKET_TRUNCATION_CHECK
1513 IPv4PacketSizeVerify (l_PacketBuffer
->m_Data
, l_PacketLength
, FALSE
, "TX", &l_Adapter
->m_TxTrunc
);
1516 //=====================================================
1517 // Are we running in DHCP server masquerade mode?
1519 // If so, catch both DHCP requests and ARP queries
1520 // to resolve the address of our virtual DHCP server.
1521 //=====================================================
1522 if (l_Adapter
->m_dhcp_enabled
)
1524 const ETH_HEADER
*eth
= (ETH_HEADER
*) l_PacketBuffer
->m_Data
;
1525 const IPHDR
*ip
= (IPHDR
*) (l_PacketBuffer
->m_Data
+ sizeof (ETH_HEADER
));
1526 const UDPHDR
*udp
= (UDPHDR
*) (l_PacketBuffer
->m_Data
+ sizeof (ETH_HEADER
) + sizeof (IPHDR
));
1529 if (l_PacketLength
== sizeof (ARP_PACKET
)
1530 && eth
->proto
== htons (ETH_P_ARP
)
1531 && l_Adapter
->m_dhcp_server_arp
)
1533 if (ProcessARP (l_Adapter
,
1534 (PARP_PACKET
) l_PacketBuffer
->m_Data
,
1535 l_Adapter
->m_dhcp_addr
,
1536 l_Adapter
->m_dhcp_server_ip
,
1538 l_Adapter
->m_dhcp_server_mac
))
1543 else if (l_PacketLength
>= sizeof (ETH_HEADER
) + sizeof (IPHDR
) + sizeof (UDPHDR
) + sizeof (DHCP
)
1544 && eth
->proto
== htons (ETH_P_IP
)
1545 && ip
->version_len
== 0x45 // IPv4, 20 byte header
1546 && ip
->protocol
== IPPROTO_UDP
1547 && udp
->dest
== htons (BOOTPS_PORT
))
1549 const DHCP
*dhcp
= (DHCP
*) (l_PacketBuffer
->m_Data
1550 + sizeof (ETH_HEADER
)
1554 const int optlen
= l_PacketLength
1555 - sizeof (ETH_HEADER
)
1560 if (optlen
> 0) // we must have at least one DHCP option
1562 if (ProcessDHCP (l_Adapter
, eth
, ip
, udp
, dhcp
, optlen
))
1570 //===============================================
1571 // In Point-To-Point mode, check to see whether
1572 // packet is ARP or IPv4 (if neither, then drop).
1573 //===============================================
1574 if (l_Adapter
->m_tun
)
1578 if (l_PacketLength
< ETHERNET_HEADER_SIZE
)
1581 e
= (ETH_HEADER
*) l_PacketBuffer
->m_Data
;
1583 switch (ntohs (e
->proto
))
1587 // Make sure that packet is the
1588 // right size for ARP.
1589 if (l_PacketLength
!= sizeof (ARP_PACKET
))
1592 ProcessARP (l_Adapter
,
1593 (PARP_PACKET
) l_PacketBuffer
->m_Data
,
1594 l_Adapter
->m_localIP
,
1595 l_Adapter
->m_remoteNetwork
,
1596 l_Adapter
->m_remoteNetmask
,
1597 l_Adapter
->m_TapToUser
.dest
);
1604 // Make sure that packet is large
1605 // enough to be IPv4.
1607 < ETHERNET_HEADER_SIZE
+ IP_HEADER_SIZE
)
1610 // Only accept directed packets,
1612 if (memcmp (e
, &l_Adapter
->m_TapToUser
, ETHERNET_HEADER_SIZE
))
1615 // Packet looks like IPv4, queue it.
1616 l_PacketBuffer
->m_SizeFlags
|= TP_TUN
;
1620 //===============================================
1621 // Push packet onto queue to wait for read from
1623 //===============================================
1625 NdisAcquireSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
1628 if (IS_UP (l_Adapter
))
1629 result
= QueuePush (l_Adapter
->m_Extension
.m_PacketQueue
, l_PacketBuffer
);
1631 NdisReleaseSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
1633 if ((TapPacketPointer
) result
!= l_PacketBuffer
)
1635 // adapter receive overrun
1636 INCREMENT_STAT (l_Adapter
->m_TxErr
);
1641 INCREMENT_STAT (l_Adapter
->m_Tx
);
1644 //============================================================
1645 // Cycle through IRPs and packets, try to satisfy each pending
1646 // IRP with a queued packet.
1647 //============================================================
1651 l_PacketBuffer
= NULL
;
1653 NdisAcquireSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
1655 if (IS_UP (l_Adapter
)
1656 && QueueCount (l_Adapter
->m_Extension
.m_PacketQueue
)
1657 && QueueCount (l_Adapter
->m_Extension
.m_IrpQueue
))
1659 l_IRP
= (PIRP
) QueuePop (l_Adapter
->m_Extension
.m_IrpQueue
);
1660 l_PacketBuffer
= (TapPacketPointer
)
1661 QueuePop (l_Adapter
->m_Extension
.m_PacketQueue
);
1664 NdisReleaseSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
1666 MYASSERT ((l_IRP
!= NULL
) + (l_PacketBuffer
!= NULL
) != 1);
1668 if (l_IRP
&& l_PacketBuffer
)
1672 IO_NETWORK_INCREMENT
);
1678 __except (EXCEPTION_EXECUTE_HANDLER
)
1682 return NDIS_STATUS_SUCCESS
;
1685 NdisFreeMemory (l_PacketBuffer
,
1686 TAP_PACKET_SIZE (l_PacketLength
),
1690 return NDIS_STATUS_SUCCESS
;
1693 return NDIS_STATUS_FAILURE
;
1696 return NDIS_STATUS_RESOURCES
;
1699 //======================================================================
1700 // Hooks for catching TAP device IRP's.
1701 //======================================================================
1704 TapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject
, IN PIRP p_IRP
)
1706 TapAdapterPointer l_Adapter
= LookupAdapterInInstanceList (p_DeviceObject
);
1707 PIO_STACK_LOCATION l_IrpSp
;
1708 NTSTATUS l_Status
= STATUS_SUCCESS
;
1711 l_IrpSp
= IoGetCurrentIrpStackLocation (p_IRP
);
1713 p_IRP
->IoStatus
.Status
= STATUS_SUCCESS
;
1714 p_IRP
->IoStatus
.Information
= 0;
1716 if (!l_Adapter
|| l_Adapter
->m_Extension
.m_Halt
)
1718 DEBUGP (("TapDeviceHook called when TAP device is halted, MajorFunction=%d\n",
1719 (int)l_IrpSp
->MajorFunction
));
1721 if (l_IrpSp
->MajorFunction
== IRP_MJ_CLOSE
)
1723 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
1724 return STATUS_SUCCESS
;
1728 p_IRP
->IoStatus
.Status
= STATUS_NO_SUCH_DEVICE
;
1729 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
1730 return STATUS_NO_SUCH_DEVICE
;
1734 switch (l_IrpSp
->MajorFunction
)
1736 //===========================================================
1737 // Ioctl call handlers
1738 //===========================================================
1739 case IRP_MJ_DEVICE_CONTROL
:
1741 switch (l_IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
1743 case TAP_IOCTL_GET_MAC
:
1745 if (l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
1746 >= sizeof (MACADDR
))
1748 COPY_MAC (p_IRP
->AssociatedIrp
.SystemBuffer
,
1750 p_IRP
->IoStatus
.Information
= sizeof (MACADDR
);
1755 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_BUFFER_TOO_SMALL
;
1759 case TAP_IOCTL_GET_VERSION
:
1761 const ULONG size
= sizeof (ULONG
) * 3;
1762 if (l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
1765 ((PULONG
) (p_IRP
->AssociatedIrp
.SystemBuffer
))[0]
1766 = TAP_DRIVER_MAJOR_VERSION
;
1767 ((PULONG
) (p_IRP
->AssociatedIrp
.SystemBuffer
))[1]
1768 = TAP_DRIVER_MINOR_VERSION
;
1769 ((PULONG
) (p_IRP
->AssociatedIrp
.SystemBuffer
))[2]
1775 p_IRP
->IoStatus
.Information
= size
;
1780 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_BUFFER_TOO_SMALL
;
1785 case TAP_IOCTL_GET_MTU
:
1787 const ULONG size
= sizeof (ULONG
) * 1;
1788 if (l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
1791 ((PULONG
) (p_IRP
->AssociatedIrp
.SystemBuffer
))[0]
1793 p_IRP
->IoStatus
.Information
= size
;
1798 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_BUFFER_TOO_SMALL
;
1803 case TAP_IOCTL_GET_INFO
:
1806 if (l_Adapter
->m_InterfaceIsRunning
)
1810 if (l_Adapter
->m_Extension
.m_TapIsRunning
)
1814 state
[2] = l_Adapter
->m_DeviceState
;
1815 if (l_Adapter
->m_MediaStateAlwaysConnected
)
1821 p_IRP
->IoStatus
.Status
= l_Status
= RtlStringCchPrintfExA (
1822 ((LPTSTR
) (p_IRP
->AssociatedIrp
.SystemBuffer
)),
1823 l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
1826 STRSAFE_FILL_BEHIND_NULL
| STRSAFE_IGNORE_NULLS
,
1827 #if PACKET_TRUNCATION_CHECK
1828 "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d,%d] Rx=[%d,%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d] InjQ=[%d,%d,%d]",
1830 "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d] Rx=[%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d] InjQ=[%d,%d,%d]",
1833 g_LastErrorFilename
,
1834 g_LastErrorLineNumber
,
1835 (int)l_Adapter
->m_Extension
.m_NumTapOpens
,
1836 (int)l_Adapter
->m_Tx
,
1837 (int)l_Adapter
->m_TxErr
,
1838 #if PACKET_TRUNCATION_CHECK
1839 (int)l_Adapter
->m_TxTrunc
,
1841 (int)l_Adapter
->m_Rx
,
1842 (int)l_Adapter
->m_RxErr
,
1843 #if PACKET_TRUNCATION_CHECK
1844 (int)l_Adapter
->m_RxTrunc
,
1846 (int)l_Adapter
->m_Extension
.m_IrpQueue
->size
,
1847 (int)l_Adapter
->m_Extension
.m_IrpQueue
->max_size
,
1848 (int)IRP_QUEUE_SIZE
,
1849 (int)l_Adapter
->m_Extension
.m_PacketQueue
->size
,
1850 (int)l_Adapter
->m_Extension
.m_PacketQueue
->max_size
,
1851 (int)PACKET_QUEUE_SIZE
,
1852 (int)l_Adapter
->m_Extension
.m_InjectQueue
->size
,
1853 (int)l_Adapter
->m_Extension
.m_InjectQueue
->max_size
,
1854 (int)INJECT_QUEUE_SIZE
1857 p_IRP
->IoStatus
.Information
1858 = l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
1864 case TAP_IOCTL_GET_LOG_LINE
:
1866 if (GetDebugLine ((LPTSTR
)p_IRP
->AssociatedIrp
.SystemBuffer
,
1867 l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
))
1868 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_SUCCESS
;
1870 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
1872 p_IRP
->IoStatus
.Information
1873 = l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
1879 case TAP_IOCTL_CONFIG_TUN
:
1881 if (l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
>=
1882 (sizeof (IPADDR
) * 3))
1886 l_Adapter
->m_tun
= FALSE
;
1888 GenerateRelatedMAC (dest
, l_Adapter
->m_MAC
, 1);
1890 l_Adapter
->m_localIP
= ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[0];
1891 l_Adapter
->m_remoteNetwork
= ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[1];
1892 l_Adapter
->m_remoteNetmask
= ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[2];
1894 // sanity check on network/netmask
1895 if ((l_Adapter
->m_remoteNetwork
& l_Adapter
->m_remoteNetmask
) != l_Adapter
->m_remoteNetwork
)
1898 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
1902 COPY_MAC (l_Adapter
->m_TapToUser
.src
, l_Adapter
->m_MAC
);
1903 COPY_MAC (l_Adapter
->m_TapToUser
.dest
, dest
);
1904 COPY_MAC (l_Adapter
->m_UserToTap
.src
, dest
);
1905 COPY_MAC (l_Adapter
->m_UserToTap
.dest
, l_Adapter
->m_MAC
);
1907 l_Adapter
->m_TapToUser
.proto
= l_Adapter
->m_UserToTap
.proto
= htons (ETH_P_IP
);
1909 l_Adapter
->m_tun
= TRUE
;
1911 CheckIfDhcpAndTunMode (l_Adapter
);
1913 p_IRP
->IoStatus
.Information
= 1; // Simple boolean value
1918 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
1924 case TAP_IOCTL_CONFIG_POINT_TO_POINT
: // Obsoleted by TAP_IOCTL_CONFIG_TUN
1926 if (l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
>=
1927 (sizeof (IPADDR
) * 2))
1931 l_Adapter
->m_tun
= FALSE
;
1933 GenerateRelatedMAC (dest
, l_Adapter
->m_MAC
, 1);
1935 l_Adapter
->m_localIP
= ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[0];
1936 l_Adapter
->m_remoteNetwork
= ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[1];
1937 l_Adapter
->m_remoteNetmask
= ~0;
1939 COPY_MAC (l_Adapter
->m_TapToUser
.src
, l_Adapter
->m_MAC
);
1940 COPY_MAC (l_Adapter
->m_TapToUser
.dest
, dest
);
1941 COPY_MAC (l_Adapter
->m_UserToTap
.src
, dest
);
1942 COPY_MAC (l_Adapter
->m_UserToTap
.dest
, l_Adapter
->m_MAC
);
1944 l_Adapter
->m_TapToUser
.proto
= l_Adapter
->m_UserToTap
.proto
= htons (ETH_P_IP
);
1946 l_Adapter
->m_tun
= TRUE
;
1948 CheckIfDhcpAndTunMode (l_Adapter
);
1950 p_IRP
->IoStatus
.Information
= 1; // Simple boolean value
1955 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
1961 case TAP_IOCTL_SET_MEDIA_STATUS
:
1963 if (l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
>=
1964 (sizeof (ULONG
) * 1))
1966 ULONG parm
= ((PULONG
) (p_IRP
->AssociatedIrp
.SystemBuffer
))[0];
1967 SetMediaStatus (l_Adapter
, (BOOLEAN
) parm
);
1968 p_IRP
->IoStatus
.Information
= 1;
1973 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
1978 case TAP_IOCTL_CONFIG_DHCP_MASQ
:
1980 if (l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
>=
1981 (sizeof (IPADDR
) * 4))
1983 l_Adapter
->m_dhcp_enabled
= FALSE
;
1984 l_Adapter
->m_dhcp_server_arp
= FALSE
;
1985 l_Adapter
->m_dhcp_user_supplied_options_buffer_len
= 0;
1987 // Adapter IP addr / netmask
1988 l_Adapter
->m_dhcp_addr
=
1989 ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[0];
1990 l_Adapter
->m_dhcp_netmask
=
1991 ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[1];
1993 // IP addr of DHCP masq server
1994 l_Adapter
->m_dhcp_server_ip
=
1995 ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[2];
1997 // Lease time in seconds
1998 l_Adapter
->m_dhcp_lease_time
=
1999 ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[3];
2001 GenerateRelatedMAC (l_Adapter
->m_dhcp_server_mac
, l_Adapter
->m_MAC
, 2);
2003 l_Adapter
->m_dhcp_enabled
= TRUE
;
2004 l_Adapter
->m_dhcp_server_arp
= TRUE
;
2006 CheckIfDhcpAndTunMode (l_Adapter
);
2008 p_IRP
->IoStatus
.Information
= 1; // Simple boolean value
2013 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
2019 case TAP_IOCTL_CONFIG_DHCP_SET_OPT
:
2021 if (l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
<=
2022 DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE
2023 && l_Adapter
->m_dhcp_enabled
)
2025 l_Adapter
->m_dhcp_user_supplied_options_buffer_len
= 0;
2027 NdisMoveMemory (l_Adapter
->m_dhcp_user_supplied_options_buffer
,
2028 p_IRP
->AssociatedIrp
.SystemBuffer
,
2029 l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
2031 l_Adapter
->m_dhcp_user_supplied_options_buffer_len
=
2032 l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
2034 p_IRP
->IoStatus
.Information
= 1; // Simple boolean value
2039 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
2048 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
2053 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2057 //===========================================================
2058 // User mode thread issued a read request on the tap device
2059 // If there are packets waiting to be read, then the request
2060 // will be satisfied here. If not, then the request will be
2061 // queued and satisfied by any packet that is not used to
2062 // satisfy requests ahead of it.
2063 //===========================================================
2066 TapPacketPointer l_PacketBuffer
;
2067 BOOLEAN pending
= FALSE
;
2069 // Save IRP-accessible copy of buffer length
2070 p_IRP
->IoStatus
.Information
= l_IrpSp
->Parameters
.Read
.Length
;
2072 if (p_IRP
->MdlAddress
== NULL
)
2074 DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_READ\n",
2077 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
2078 p_IRP
->IoStatus
.Information
= 0;
2079 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2082 else if ((p_IRP
->AssociatedIrp
.SystemBuffer
=
2083 MmGetSystemAddressForMdlSafe
2084 (p_IRP
->MdlAddress
, NormalPagePriority
)) == NULL
)
2086 DEBUGP (("[%s] Could not map address in IRP_MJ_READ\n",
2089 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INSUFFICIENT_RESOURCES
;
2090 p_IRP
->IoStatus
.Information
= 0;
2091 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2094 else if (!l_Adapter
->m_InterfaceIsRunning
)
2096 DEBUGP (("[%s] Interface is down in IRP_MJ_READ\n",
2099 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2100 p_IRP
->IoStatus
.Information
= 0;
2101 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2105 //==================================
2106 // Can we provide immediate service?
2107 //==================================
2109 l_PacketBuffer
= NULL
;
2111 NdisAcquireSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
2113 if (IS_UP (l_Adapter
)
2114 && QueueCount (l_Adapter
->m_Extension
.m_PacketQueue
)
2115 && QueueCount (l_Adapter
->m_Extension
.m_IrpQueue
) == 0)
2117 l_PacketBuffer
= (TapPacketPointer
)
2118 QueuePop (l_Adapter
->m_Extension
.m_PacketQueue
);
2121 NdisReleaseSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
2125 l_Status
= CompleteIRP (p_IRP
,
2131 //=============================
2132 // Attempt to pend read request
2133 //=============================
2135 NdisAcquireSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
2137 if (IS_UP (l_Adapter
)
2138 && QueuePush (l_Adapter
->m_Extension
.m_IrpQueue
, p_IRP
) == (PIRP
) p_IRP
)
2140 IoSetCancelRoutine (p_IRP
, CancelIRPCallback
);
2141 l_Status
= STATUS_PENDING
;
2142 IoMarkIrpPending (p_IRP
);
2146 NdisReleaseSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
2151 // Can't queue anymore IRP's
2152 DEBUGP (("[%s] TAP [%s] read IRP overrun\n",
2153 NAME (l_Adapter
), l_Adapter
->m_Extension
.m_TapName
));
2155 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2156 p_IRP
->IoStatus
.Information
= 0;
2157 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2161 //==============================================================
2162 // User mode issued a WriteFile request on the TAP file handle.
2163 // The request will always get satisfied here. The call may
2164 // fail if there are too many pending packets (queue full).
2165 //==============================================================
2168 if (p_IRP
->MdlAddress
== NULL
)
2170 DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n",
2173 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
2174 p_IRP
->IoStatus
.Information
= 0;
2176 else if ((p_IRP
->AssociatedIrp
.SystemBuffer
=
2177 MmGetSystemAddressForMdlSafe
2178 (p_IRP
->MdlAddress
, NormalPagePriority
)) == NULL
)
2180 DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n",
2183 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INSUFFICIENT_RESOURCES
;
2184 p_IRP
->IoStatus
.Information
= 0;
2186 else if (!l_Adapter
->m_InterfaceIsRunning
)
2188 DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n",
2191 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2192 p_IRP
->IoStatus
.Information
= 0;
2194 else if (!l_Adapter
->m_tun
&& ((l_IrpSp
->Parameters
.Write
.Length
) >= ETHERNET_HEADER_SIZE
))
2198 p_IRP
->IoStatus
.Information
= l_IrpSp
->Parameters
.Write
.Length
;
2200 DUMP_PACKET ("IRP_MJ_WRITE ETH",
2201 (unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
,
2202 l_IrpSp
->Parameters
.Write
.Length
);
2204 //=====================================================
2205 // If IPv4 packet, check whether or not packet
2207 //=====================================================
2208 #if PACKET_TRUNCATION_CHECK
2209 IPv4PacketSizeVerify ((unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
,
2210 l_IrpSp
->Parameters
.Write
.Length
,
2213 &l_Adapter
->m_RxTrunc
);
2216 NdisMEthIndicateReceive
2217 (l_Adapter
->m_MiniportAdapterHandle
,
2218 (NDIS_HANDLE
) l_Adapter
,
2219 (unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
,
2220 ETHERNET_HEADER_SIZE
,
2221 (unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
+ ETHERNET_HEADER_SIZE
,
2222 l_IrpSp
->Parameters
.Write
.Length
- ETHERNET_HEADER_SIZE
,
2223 l_IrpSp
->Parameters
.Write
.Length
- ETHERNET_HEADER_SIZE
);
2225 NdisMEthIndicateReceiveComplete (l_Adapter
->m_MiniportAdapterHandle
);
2227 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_SUCCESS
;
2229 __except (EXCEPTION_EXECUTE_HANDLER
)
2231 DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE\n",
2234 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2235 p_IRP
->IoStatus
.Information
= 0;
2238 else if (l_Adapter
->m_tun
&& ((l_IrpSp
->Parameters
.Write
.Length
) >= IP_HEADER_SIZE
))
2242 p_IRP
->IoStatus
.Information
= l_IrpSp
->Parameters
.Write
.Length
;
2244 DUMP_PACKET2 ("IRP_MJ_WRITE P2P",
2245 &l_Adapter
->m_UserToTap
,
2246 (unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
,
2247 l_IrpSp
->Parameters
.Write
.Length
);
2249 //=====================================================
2250 // If IPv4 packet, check whether or not packet
2252 //=====================================================
2253 #if PACKET_TRUNCATION_CHECK
2254 IPv4PacketSizeVerify ((unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
,
2255 l_IrpSp
->Parameters
.Write
.Length
,
2258 &l_Adapter
->m_RxTrunc
);
2261 NdisMEthIndicateReceive
2262 (l_Adapter
->m_MiniportAdapterHandle
,
2263 (NDIS_HANDLE
) l_Adapter
,
2264 (unsigned char *) &l_Adapter
->m_UserToTap
,
2265 sizeof (l_Adapter
->m_UserToTap
),
2266 (unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
,
2267 l_IrpSp
->Parameters
.Write
.Length
,
2268 l_IrpSp
->Parameters
.Write
.Length
);
2270 NdisMEthIndicateReceiveComplete (l_Adapter
->m_MiniportAdapterHandle
);
2272 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_SUCCESS
;
2274 __except (EXCEPTION_EXECUTE_HANDLER
)
2276 DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE (P2P)\n",
2279 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2280 p_IRP
->IoStatus
.Information
= 0;
2285 DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n",
2287 l_IrpSp
->Parameters
.Write
.Length
));
2289 p_IRP
->IoStatus
.Information
= 0; // ETHERNET_HEADER_SIZE;
2290 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_BUFFER_TOO_SMALL
;
2293 if (l_Status
== STATUS_SUCCESS
)
2294 INCREMENT_STAT (l_Adapter
->m_Rx
);
2296 INCREMENT_STAT (l_Adapter
->m_RxErr
);
2298 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2302 //--------------------------------------------------------------
2303 // User mode thread has called CreateFile() on the tap device
2304 //--------------------------------------------------------------
2307 BOOLEAN succeeded
= FALSE
;
2308 BOOLEAN mutex_succeeded
;
2311 (("[%s] [TAP] release [%d.%d] open request (m_TapOpens=%d)\n",
2312 NAME (l_Adapter
), TAP_DRIVER_MAJOR_VERSION
,
2313 TAP_DRIVER_MINOR_VERSION
, l_Adapter
->m_Extension
.m_TapOpens
));
2315 ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter
->m_Extension
.m_OpenCloseMutex
, mutex_succeeded
);
2316 if (mutex_succeeded
)
2318 if (l_Adapter
->m_Extension
.m_TapIsRunning
&& !l_Adapter
->m_Extension
.m_TapOpens
)
2320 ResetTapAdapterState (l_Adapter
);
2321 l_Adapter
->m_Extension
.m_TapOpens
= 1;
2327 INCREMENT_STAT (l_Adapter
->m_Extension
.m_NumTapOpens
);
2328 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_SUCCESS
;
2329 p_IRP
->IoStatus
.Information
= 0;
2333 DEBUGP (("[%s] TAP is presently unavailable (m_TapOpens=%d)\n",
2334 NAME (l_Adapter
), l_Adapter
->m_Extension
.m_TapOpens
));
2336 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2337 p_IRP
->IoStatus
.Information
= 0;
2340 RELEASE_MUTEX (&l_Adapter
->m_Extension
.m_OpenCloseMutex
);
2344 DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
2345 NAME (l_Adapter
), l_Adapter
->m_Extension
.m_TapOpens
));
2347 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2348 p_IRP
->IoStatus
.Information
= 0;
2351 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2355 //-----------------------------------------------------------
2356 // User mode thread called CloseHandle() on the tap device
2357 //-----------------------------------------------------------
2360 BOOLEAN mutex_succeeded
;
2362 DEBUGP (("[%s] [TAP] release [%d.%d] close/cleanup request\n",
2363 NAME (l_Adapter
), TAP_DRIVER_MAJOR_VERSION
,
2364 TAP_DRIVER_MINOR_VERSION
));
2366 ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter
->m_Extension
.m_OpenCloseMutex
, mutex_succeeded
);
2367 if (mutex_succeeded
)
2369 l_Adapter
->m_Extension
.m_TapOpens
= 0;
2370 ResetTapAdapterState (l_Adapter
);
2371 FlushQueues (&l_Adapter
->m_Extension
);
2372 SetMediaStatus (l_Adapter
, FALSE
);
2373 RELEASE_MUTEX (&l_Adapter
->m_Extension
.m_OpenCloseMutex
);
2377 DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
2378 NAME (l_Adapter
), l_Adapter
->m_Extension
.m_TapOpens
));
2380 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2381 p_IRP
->IoStatus
.Information
= 0;
2384 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2388 //------------------
2390 //------------------
2394 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2395 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2403 //=============================================================
2404 // CompleteIRP is normally called with an adapter -> userspace
2405 // network packet and an IRP (Pending I/O request) from userspace.
2407 // The IRP will normally represent a queued overlapped read
2408 // operation from userspace that is in a wait state.
2410 // Use the ethernet packet to satisfy the IRP.
2411 //=============================================================
2414 CompleteIRP (IN PIRP p_IRP
,
2415 IN TapPacketPointer p_PacketBuffer
,
2416 IN CCHAR PriorityBoost
)
2418 NTSTATUS l_Status
= STATUS_UNSUCCESSFUL
;
2424 MYASSERT (p_PacketBuffer
);
2426 IoSetCancelRoutine (p_IRP
, NULL
); // Disable cancel routine
2428 //-------------------------------------------
2429 // While p_PacketBuffer always contains a
2430 // full ethernet packet, including the
2431 // ethernet header, in point-to-point mode,
2432 // we only want to return the IPv4
2434 //-------------------------------------------
2436 if (p_PacketBuffer
->m_SizeFlags
& TP_TUN
)
2438 offset
= ETHERNET_HEADER_SIZE
;
2439 len
= (int) (p_PacketBuffer
->m_SizeFlags
& TP_SIZE_MASK
) - ETHERNET_HEADER_SIZE
;
2444 len
= (p_PacketBuffer
->m_SizeFlags
& TP_SIZE_MASK
);
2447 if (len
< 0 || (int) p_IRP
->IoStatus
.Information
< len
)
2449 p_IRP
->IoStatus
.Information
= 0;
2450 p_IRP
->IoStatus
.Status
= STATUS_BUFFER_OVERFLOW
;
2455 p_IRP
->IoStatus
.Information
= len
;
2456 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_SUCCESS
;
2460 NdisMoveMemory (p_IRP
->AssociatedIrp
.SystemBuffer
,
2461 p_PacketBuffer
->m_Data
+ offset
,
2464 __except (EXCEPTION_EXECUTE_HANDLER
)
2467 p_IRP
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
2468 p_IRP
->IoStatus
.Information
= 0;
2474 NdisFreeMemory (p_PacketBuffer
,
2475 TAP_PACKET_SIZE (p_PacketBuffer
->m_SizeFlags
& TP_SIZE_MASK
),
2478 __except (EXCEPTION_EXECUTE_HANDLER
)
2482 if (l_Status
== STATUS_SUCCESS
)
2484 IoCompleteRequest (p_IRP
, PriorityBoost
);
2487 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2492 //==============================================
2493 // IRPs get cancelled for a number of reasons.
2495 // The TAP device could be closed by userspace
2496 // when there are still pending read operations.
2498 // The user could disable the TAP adapter in the
2499 // network connections control panel, while the
2500 // device is still open by a process.
2501 //==============================================
2503 CancelIRPCallback (IN PDEVICE_OBJECT p_DeviceObject
,
2506 TapAdapterPointer l_Adapter
= LookupAdapterInInstanceList (p_DeviceObject
);
2507 CancelIRP (l_Adapter
? &l_Adapter
->m_Extension
: NULL
, p_IRP
, TRUE
);
2511 CancelIRP (TapExtensionPointer p_Extension
,
2515 BOOLEAN exists
= FALSE
;
2521 NdisAcquireSpinLock (&p_Extension
->m_QueueLock
);
2522 exists
= (QueueExtract (p_Extension
->m_IrpQueue
, p_IRP
) == p_IRP
);
2523 NdisReleaseSpinLock (&p_Extension
->m_QueueLock
);
2530 IoSetCancelRoutine (p_IRP
, NULL
);
2531 p_IRP
->IoStatus
.Status
= STATUS_CANCELLED
;
2532 p_IRP
->IoStatus
.Information
= 0;
2536 IoReleaseCancelSpinLock (p_IRP
->CancelIrql
);
2539 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2542 //===========================================
2543 // Exhaust packet, IRP, and injection queues.
2544 //===========================================
2546 FlushQueues (TapExtensionPointer p_Extension
)
2549 TapPacketPointer l_PacketBuffer
;
2550 InjectPacketPointer l_InjectBuffer
;
2551 int n_IRP
=0, n_Packet
=0, n_Inject
=0;
2553 MYASSERT (p_Extension
);
2554 MYASSERT (p_Extension
->m_TapDevice
);
2558 NdisAcquireSpinLock (&p_Extension
->m_QueueLock
);
2559 l_IRP
= QueuePop (p_Extension
->m_IrpQueue
);
2560 NdisReleaseSpinLock (&p_Extension
->m_QueueLock
);
2564 CancelIRP (NULL
, l_IRP
, FALSE
);
2572 NdisAcquireSpinLock (&p_Extension
->m_QueueLock
);
2573 l_PacketBuffer
= QueuePop (p_Extension
->m_PacketQueue
);
2574 NdisReleaseSpinLock (&p_Extension
->m_QueueLock
);
2578 MemFree (l_PacketBuffer
, TAP_PACKET_SIZE (l_PacketBuffer
->m_SizeFlags
& TP_SIZE_MASK
));
2586 NdisAcquireSpinLock (&p_Extension
->m_InjectLock
);
2587 l_InjectBuffer
= QueuePop (p_Extension
->m_InjectQueue
);
2588 NdisReleaseSpinLock (&p_Extension
->m_InjectLock
);
2592 INJECT_PACKET_FREE(l_InjectBuffer
);
2599 "[%s] [TAP] FlushQueues n_IRP=[%d,%d,%d] n_Packet=[%d,%d,%d] n_Inject=[%d,%d,%d]\n",
2600 p_Extension
->m_TapName
,
2602 p_Extension
->m_IrpQueue
->max_size
,
2605 p_Extension
->m_PacketQueue
->max_size
,
2608 p_Extension
->m_InjectQueue
->max_size
,
2613 //===================================================
2614 // Tell Windows whether the TAP device should be
2615 // considered "connected" or "disconnected".
2616 //===================================================
2618 SetMediaStatus (TapAdapterPointer p_Adapter
, BOOLEAN state
)
2620 if (p_Adapter
->m_MediaState
!= state
&& !p_Adapter
->m_MediaStateAlwaysConnected
)
2623 NdisMIndicateStatus (p_Adapter
->m_MiniportAdapterHandle
,
2624 NDIS_STATUS_MEDIA_CONNECT
, NULL
, 0);
2626 NdisMIndicateStatus (p_Adapter
->m_MiniportAdapterHandle
,
2627 NDIS_STATUS_MEDIA_DISCONNECT
, NULL
, 0);
2629 NdisMIndicateStatusComplete (p_Adapter
->m_MiniportAdapterHandle
);
2630 p_Adapter
->m_MediaState
= state
;
2635 //======================================================
2636 // If DHCP mode is used together with tun
2637 // mode, consider the fact that the P2P remote subnet
2638 // might enclose the DHCP masq server address.
2639 //======================================================
2641 CheckIfDhcpAndTunMode (TapAdapterPointer p_Adapter
)
2643 if (p_Adapter
->m_tun
&& p_Adapter
->m_dhcp_enabled
)
2645 if ((p_Adapter
->m_dhcp_server_ip
& p_Adapter
->m_remoteNetmask
) == p_Adapter
->m_remoteNetwork
)
2647 COPY_MAC (p_Adapter
->m_dhcp_server_mac
, p_Adapter
->m_TapToUser
.dest
);
2648 p_Adapter
->m_dhcp_server_arp
= FALSE
;
2653 //===================================================
2654 // Generate an ARP reply message for specific kinds
2656 //===================================================
2658 ProcessARP (TapAdapterPointer p_Adapter
,
2659 const PARP_PACKET src
,
2660 const IPADDR adapter_ip
,
2661 const IPADDR ip_network
,
2662 const IPADDR ip_netmask
,
2665 //-----------------------------------------------
2666 // Is this the kind of packet we are looking for?
2667 //-----------------------------------------------
2668 if (src
->m_Proto
== htons (ETH_P_ARP
)
2669 && MAC_EQUAL (src
->m_MAC_Source
, p_Adapter
->m_MAC
)
2670 && MAC_EQUAL (src
->m_ARP_MAC_Source
, p_Adapter
->m_MAC
)
2671 && MAC_EQUAL (src
->m_MAC_Destination
, p_Adapter
->m_MAC_Broadcast
)
2672 && src
->m_ARP_Operation
== htons (ARP_REQUEST
)
2673 && src
->m_MAC_AddressType
== htons (MAC_ADDR_TYPE
)
2674 && src
->m_MAC_AddressSize
== sizeof (MACADDR
)
2675 && src
->m_PROTO_AddressType
== htons (ETH_P_IP
)
2676 && src
->m_PROTO_AddressSize
== sizeof (IPADDR
)
2677 && src
->m_ARP_IP_Source
== adapter_ip
2678 && (src
->m_ARP_IP_Destination
& ip_netmask
) == ip_network
2679 && src
->m_ARP_IP_Destination
!= adapter_ip
)
2681 ARP_PACKET
*arp
= (ARP_PACKET
*) MemAlloc (sizeof (ARP_PACKET
), TRUE
);
2684 //----------------------------------------------
2685 // Initialize ARP reply fields
2686 //----------------------------------------------
2687 arp
->m_Proto
= htons (ETH_P_ARP
);
2688 arp
->m_MAC_AddressType
= htons (MAC_ADDR_TYPE
);
2689 arp
->m_PROTO_AddressType
= htons (ETH_P_IP
);
2690 arp
->m_MAC_AddressSize
= sizeof (MACADDR
);
2691 arp
->m_PROTO_AddressSize
= sizeof (IPADDR
);
2692 arp
->m_ARP_Operation
= htons (ARP_REPLY
);
2694 //----------------------------------------------
2696 //----------------------------------------------
2697 COPY_MAC (arp
->m_MAC_Source
, mac
);
2698 COPY_MAC (arp
->m_MAC_Destination
, p_Adapter
->m_MAC
);
2699 COPY_MAC (arp
->m_ARP_MAC_Source
, mac
);
2700 COPY_MAC (arp
->m_ARP_MAC_Destination
, p_Adapter
->m_MAC
);
2701 arp
->m_ARP_IP_Source
= src
->m_ARP_IP_Destination
;
2702 arp
->m_ARP_IP_Destination
= adapter_ip
;
2704 DUMP_PACKET ("ProcessARP",
2705 (unsigned char *) arp
,
2706 sizeof (ARP_PACKET
));
2708 InjectPacketDeferred (p_Adapter
, (UCHAR
*) arp
, sizeof (ARP_PACKET
));
2710 MemFree (arp
, sizeof (ARP_PACKET
));
2719 //===============================================================
2720 // Used in cases where internally generated packets such as
2721 // ARP or DHCP replies must be returned to the kernel, to be
2722 // seen as an incoming packet "arriving" on the interface.
2723 //===============================================================
2725 // Defer packet injection till IRQL < DISPATCH_LEVEL
2727 InjectPacketDeferred (TapAdapterPointer p_Adapter
,
2729 const unsigned int len
)
2731 InjectPacketPointer l_InjectBuffer
;
2734 if (NdisAllocateMemoryWithTag (&l_InjectBuffer
,
2735 INJECT_PACKET_SIZE (len
),
2736 'IPAT') == NDIS_STATUS_SUCCESS
)
2738 l_InjectBuffer
->m_Size
= len
;
2739 NdisMoveMemory (l_InjectBuffer
->m_Data
, packet
, len
);
2740 NdisAcquireSpinLock (&p_Adapter
->m_Extension
.m_InjectLock
);
2741 result
= QueuePush (p_Adapter
->m_Extension
.m_InjectQueue
, l_InjectBuffer
);
2742 NdisReleaseSpinLock (&p_Adapter
->m_Extension
.m_InjectLock
);
2744 KeInsertQueueDpc (&p_Adapter
->m_Extension
.m_InjectDpc
, p_Adapter
, NULL
);
2746 INJECT_PACKET_FREE(l_InjectBuffer
);
2750 // Handle the injection of previously deferred packets
2752 InjectPacketDpc(KDPC
*Dpc
,
2753 PVOID DeferredContext
,
2754 PVOID SystemArgument1
,
2755 PVOID SystemArgument2
)
2757 InjectPacketPointer l_InjectBuffer
;
2758 TapAdapterPointer l_Adapter
= (TapAdapterPointer
)SystemArgument1
;
2761 NdisAcquireSpinLock (&l_Adapter
->m_Extension
.m_InjectLock
);
2762 l_InjectBuffer
= QueuePop (l_Adapter
->m_Extension
.m_InjectQueue
);
2763 NdisReleaseSpinLock (&l_Adapter
->m_Extension
.m_InjectLock
);
2766 InjectPacketNow(l_Adapter
, l_InjectBuffer
->m_Data
, l_InjectBuffer
->m_Size
);
2767 INJECT_PACKET_FREE(l_InjectBuffer
);
2774 // Do packet injection now
2776 InjectPacketNow (TapAdapterPointer p_Adapter
,
2778 const unsigned int len
)
2780 MYASSERT (len
>= ETHERNET_HEADER_SIZE
);
2784 //------------------------------------------------------------
2785 // NdisMEthIndicateReceive and NdisMEthIndicateReceiveComplete
2786 // could potentially be called reentrantly both here and in
2787 // TapDeviceHook/IRP_MJ_WRITE.
2789 // The DDK docs imply that this is okay.
2791 // Note that reentrant behavior could only occur if the
2792 // non-deferred version of InjectPacket is used.
2793 //------------------------------------------------------------
2794 NdisMEthIndicateReceive
2795 (p_Adapter
->m_MiniportAdapterHandle
,
2796 (NDIS_HANDLE
) p_Adapter
,
2798 ETHERNET_HEADER_SIZE
,
2799 packet
+ ETHERNET_HEADER_SIZE
,
2800 len
- ETHERNET_HEADER_SIZE
,
2801 len
- ETHERNET_HEADER_SIZE
);
2803 NdisMEthIndicateReceiveComplete (p_Adapter
->m_MiniportAdapterHandle
);
2805 __except (EXCEPTION_EXECUTE_HANDLER
)
2807 DEBUGP (("[%s] NdisMEthIndicateReceive failed in InjectPacketNow\n",
2813 //===================================================================
2814 // Go back to default TAP mode from Point-To-Point mode.
2815 // Also reset (i.e. disable) DHCP Masq mode.
2816 //===================================================================
2817 VOID
ResetTapAdapterState (TapAdapterPointer p_Adapter
)
2820 p_Adapter
->m_tun
= FALSE
;
2821 p_Adapter
->m_localIP
= 0;
2822 p_Adapter
->m_remoteNetwork
= 0;
2823 p_Adapter
->m_remoteNetmask
= 0;
2824 NdisZeroMemory (&p_Adapter
->m_TapToUser
, sizeof (p_Adapter
->m_TapToUser
));
2825 NdisZeroMemory (&p_Adapter
->m_UserToTap
, sizeof (p_Adapter
->m_UserToTap
));
2828 p_Adapter
->m_dhcp_enabled
= FALSE
;
2829 p_Adapter
->m_dhcp_server_arp
= FALSE
;
2830 p_Adapter
->m_dhcp_user_supplied_options_buffer_len
= 0;
2831 p_Adapter
->m_dhcp_addr
= 0;
2832 p_Adapter
->m_dhcp_netmask
= 0;
2833 p_Adapter
->m_dhcp_server_ip
= 0;
2834 p_Adapter
->m_dhcp_lease_time
= 0;
2835 p_Adapter
->m_dhcp_received_discover
= FALSE
;
2836 p_Adapter
->m_dhcp_bad_requests
= 0;
2837 NdisZeroMemory (p_Adapter
->m_dhcp_server_mac
, sizeof (MACADDR
));
2842 //===================================================================
2843 // Set TAP device handle to be accessible without admin privileges.
2844 //===================================================================
2845 VOID
AllowNonAdmin (TapExtensionPointer p_Extension
)
2848 SECURITY_DESCRIPTOR sd
;
2849 OBJECT_ATTRIBUTES oa
;
2850 IO_STATUS_BLOCK isb
;
2853 NdisZeroMemory (&sd
, sizeof (sd
));
2854 NdisZeroMemory (&oa
, sizeof (oa
));
2855 NdisZeroMemory (&isb
, sizeof (isb
));
2857 if (!p_Extension
->m_CreatedUnicodeLinkName
)
2859 DEBUGP (("[TAP] AllowNonAdmin: UnicodeLinkName is uninitialized\n"));
2864 stat
= RtlCreateSecurityDescriptor (&sd
, SECURITY_DESCRIPTOR_REVISION
);
2865 if (stat
!= STATUS_SUCCESS
)
2867 DEBUGP (("[TAP] AllowNonAdmin: RtlCreateSecurityDescriptor failed\n"));
2872 InitializeObjectAttributes (
2874 &p_Extension
->m_UnicodeLinkName
,
2888 if (stat
!= STATUS_SUCCESS
)
2890 DEBUGP (("[TAP] AllowNonAdmin: ZwOpenFile failed, status=0x%08x\n", (unsigned int)stat
));
2895 stat
= ZwSetSecurityObject (hand
, DACL_SECURITY_INFORMATION
, &sd
);
2896 if (stat
!= STATUS_SUCCESS
)
2898 DEBUGP (("[TAP] AllowNonAdmin: ZwSetSecurityObject failed\n"));
2903 stat
= ZwClose (hand
);
2904 if (stat
!= STATUS_SUCCESS
)
2906 DEBUGP (("[TAP] AllowNonAdmin: ZwClose failed\n"));
2911 DEBUGP (("[TAP] AllowNonAdmin: SUCCEEDED\n"));
2916 #if PACKET_TRUNCATION_CHECK
2919 IPv4PacketSizeVerify (const UCHAR
*data
, ULONG length
, BOOLEAN tun
, const char *prefix
, LONG
*counter
)
2926 ip
= (IPHDR
*) data
;
2930 if (length
>= sizeof (ETH_HEADER
))
2932 const ETH_HEADER
*eth
= (ETH_HEADER
*) data
;
2934 if (eth
->proto
!= htons (ETH_P_IP
))
2937 ip
= (IPHDR
*) (data
+ sizeof (ETH_HEADER
));
2938 len
-= sizeof (ETH_HEADER
);
2944 if (len
>= sizeof (IPHDR
))
2946 const int totlen
= ntohs (ip
->tot_len
);
2948 DEBUGP (("[TAP] IPv4PacketSizeVerify %s len=%d totlen=%d\n", prefix
, len
, totlen
));
2957 //======================================================================
2959 //======================================================================