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).
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 //======================================================
26 // This driver is designed to work on Win 2000 or higher
27 // versions of Windows.
29 // It is SMP-safe and handles NDIS 5 power management.
31 // By default we operate as a "tap" virtual ethernet
32 // 802.3 interface, but we can emulate a "tun"
33 // interface (point-to-point IPv4) through the
34 // TAP_IOCTL_CONFIG_POINT_TO_POINT or
35 // TAP_IOCTL_CONFIG_TUN ioctl.
36 //======================================================
38 #include "../../autodefs/defs.h"
40 #error DDKVER_MAJOR must be defined as the major number of the DDK Version
43 #define NDIS_MINIPORT_DRIVER
44 #define BINARY_COMPATIBLE 0
45 #define NDIS50_MINIPORT 1
51 #define ALSO_DBGPRINT 1
52 #define DEBUGP_AT_DISPATCH 0
54 //========================================================
55 // Check for truncated IPv4 packets, log errors if found.
56 //========================================================
57 #define PACKET_TRUNCATION_CHECK 0
59 //========================================================
60 // EXPERIMENTAL -- Configure TAP device object to be
61 // accessible from non-administrative accounts, based
62 // on an advanced properties setting.
64 // Duplicates the functionality of OpenVPN's
65 // --allow-nonadmin directive.
66 //========================================================
67 #define ENABLE_NONADMIN 1
69 #if DDKVER_MAJOR < 5600
71 #include <ntstrsafe.h>
76 #include <ntstrsafe.h>
80 #include "constants.h"
87 #include "prototypes.h"
96 ((ta)->m_InterfaceIsRunning && (ta)->m_Extension.m_TapIsRunning)
98 #define INCREMENT_STAT(s) ++(s)
100 #define NAME_BUFFER_SIZE 80
102 //========================================================
104 //========================================================
106 NDIS_HANDLE g_NdisWrapperHandle
;
108 const UINT g_SupportedOIDList
[] = {
109 OID_GEN_HARDWARE_STATUS
,
110 OID_GEN_MEDIA_SUPPORTED
,
111 OID_GEN_MEDIA_IN_USE
,
112 OID_GEN_MAXIMUM_LOOKAHEAD
,
115 OID_GEN_TRANSMIT_BLOCK_SIZE
,
116 OID_GEN_RECEIVE_BLOCK_SIZE
,
117 OID_GEN_VENDOR_DESCRIPTION
,
118 OID_GEN_DRIVER_VERSION
,
123 OID_802_3_PERMANENT_ADDRESS
,
124 OID_802_3_CURRENT_ADDRESS
,
125 OID_GEN_RCV_NO_BUFFER
,
126 OID_802_3_RCV_ERROR_ALIGNMENT
,
127 OID_802_3_XMIT_ONE_COLLISION
,
128 OID_802_3_XMIT_MORE_COLLISIONS
,
129 OID_802_3_MULTICAST_LIST
,
130 OID_802_3_MAXIMUM_LIST_SIZE
,
132 OID_GEN_CURRENT_LOOKAHEAD
,
133 OID_GEN_CURRENT_PACKET_FILTER
,
134 OID_GEN_PROTOCOL_OPTIONS
,
135 OID_GEN_MAXIMUM_TOTAL_SIZE
,
136 OID_GEN_TRANSMIT_BUFFER_SPACE
,
137 OID_GEN_RECEIVE_BUFFER_SPACE
,
138 OID_GEN_MAXIMUM_FRAME_SIZE
,
139 OID_GEN_VENDOR_DRIVER_VERSION
,
140 OID_GEN_MAXIMUM_SEND_PACKETS
,
141 OID_GEN_MEDIA_CONNECT_STATUS
,
142 OID_GEN_SUPPORTED_LIST
145 //============================================================
147 //============================================================
148 #pragma NDIS_INIT_FUNCTION (DriverEntry)
151 DriverEntry (IN PDRIVER_OBJECT p_DriverObject
,
152 IN PUNICODE_STRING p_RegistryPath
)
154 NDIS_STATUS l_Status
= NDIS_STATUS_FAILURE
;
155 NDIS_MINIPORT_CHARACTERISTICS
*l_Properties
= NULL
;
157 //========================================================
158 // Notify NDIS that a new miniport driver is initializing.
159 //========================================================
161 NdisMInitializeWrapper (&g_NdisWrapperHandle
,
163 p_RegistryPath
, NULL
);
165 //======================
166 // Global initialization
167 //======================
170 MyDebugInit (10000); // Allocate debugging text space
173 if (!InitInstanceList ())
175 DEBUGP (("[TAP] Allocation failed for adapter instance list\n"));
179 //=======================================
180 // Set and register miniport entry points
181 //=======================================
183 l_Properties
= MemAlloc (sizeof (NDIS_MINIPORT_CHARACTERISTICS
), TRUE
);
185 if (l_Properties
== NULL
)
187 DEBUGP (("[TAP] Allocation failed for miniport entry points\n"));
191 l_Properties
->MajorNdisVersion
= TAP_NDIS_MAJOR_VERSION
;
192 l_Properties
->MinorNdisVersion
= TAP_NDIS_MINOR_VERSION
;
193 l_Properties
->InitializeHandler
= AdapterCreate
;
194 l_Properties
->HaltHandler
= AdapterHalt
;
195 l_Properties
->ResetHandler
= AdapterReset
; /* DISPATCH_LEVEL */
196 l_Properties
->TransferDataHandler
= AdapterReceive
; /* DISPATCH_LEVEL */
197 l_Properties
->SendHandler
= AdapterTransmit
; /* DISPATCH_LEVEL */
198 l_Properties
->QueryInformationHandler
= AdapterQuery
; /* DISPATCH_LEVEL */
199 l_Properties
->SetInformationHandler
= AdapterModify
; /* DISPATCH_LEVEL */
202 NdisMRegisterMiniport (g_NdisWrapperHandle
, l_Properties
,
203 sizeof (NDIS_MINIPORT_CHARACTERISTICS
)))
205 case NDIS_STATUS_SUCCESS
:
207 DEBUGP (("[TAP] version [%d.%d] %s %s registered miniport successfully\n",
208 TAP_DRIVER_MAJOR_VERSION
,
209 TAP_DRIVER_MINOR_VERSION
,
212 DEBUGP (("Registry Path: '%S'\n", p_RegistryPath
->Buffer
));
216 case NDIS_STATUS_BAD_CHARACTERISTICS
:
218 DEBUGP (("[TAP] Miniport characteristics were badly defined\n"));
219 NdisTerminateWrapper (g_NdisWrapperHandle
, NULL
);
223 case NDIS_STATUS_BAD_VERSION
:
226 (("[TAP] NDIS Version is wrong for the given characteristics\n"));
227 NdisTerminateWrapper (g_NdisWrapperHandle
, NULL
);
231 case NDIS_STATUS_RESOURCES
:
233 DEBUGP (("[TAP] Insufficient resources\n"));
234 NdisTerminateWrapper (g_NdisWrapperHandle
, NULL
);
239 case NDIS_STATUS_FAILURE
:
241 DEBUGP (("[TAP] Unknown fatal registration error\n"));
242 NdisTerminateWrapper (g_NdisWrapperHandle
, NULL
);
249 MemFree (l_Properties
, sizeof (NDIS_MINIPORT_CHARACTERISTICS
));
251 if (l_Status
== NDIS_STATUS_SUCCESS
)
252 NdisMRegisterUnloadHandler (g_NdisWrapperHandle
, TapDriverUnload
);
254 TapDriverUnload (p_DriverObject
);
259 //============================================================
261 //============================================================
263 TapDriverUnload (IN PDRIVER_OBJECT p_DriverObject
)
265 DEBUGP (("[TAP] version [%d.%d] %s %s unloaded, instances=%d, imbs=%d\n",
266 TAP_DRIVER_MAJOR_VERSION
,
267 TAP_DRIVER_MINOR_VERSION
,
271 InstanceMaxBucketSize()));
275 //==============================
276 // Free debugging text space
277 //==============================
283 //==========================================================
284 // Adapter Initialization
285 //==========================================================
286 NDIS_STATUS AdapterCreate
287 (OUT PNDIS_STATUS p_ErrorStatus
,
288 OUT PUINT p_MediaIndex
,
289 IN PNDIS_MEDIUM p_Media
,
290 IN UINT p_MediaCount
,
291 IN NDIS_HANDLE p_AdapterHandle
,
292 IN NDIS_HANDLE p_ConfigurationHandle
)
294 TapAdapterPointer l_Adapter
= NULL
;
296 NDIS_MEDIUM l_PreferredMedium
= NdisMedium802_3
; // Ethernet
297 BOOLEAN l_MacFromRegistry
= FALSE
;
302 BOOLEAN enable_non_admin
= FALSE
;
305 DEBUGP (("[TAP] AdapterCreate called\n"));
307 //====================================
308 // Make sure adapter type is supported
309 //====================================
312 l_Index
< p_MediaCount
&& p_Media
[l_Index
] != l_PreferredMedium
;
315 if (l_Index
== p_MediaCount
)
317 DEBUGP (("[TAP] Unsupported adapter type [wanted: %d]\n",
319 return NDIS_STATUS_UNSUPPORTED_MEDIA
;
322 *p_MediaIndex
= l_Index
;
324 //=========================================
325 // Allocate memory for TapAdapter structure
326 //=========================================
328 l_Adapter
= MemAlloc (sizeof (TapAdapter
), TRUE
);
330 if (l_Adapter
== NULL
)
332 DEBUGP (("[TAP] Couldn't allocate adapter memory\n"));
333 return NDIS_STATUS_RESOURCES
;
336 //==========================================
337 // Inform the NDIS library about significant
338 // features of our virtual NIC.
339 //==========================================
343 (NDIS_HANDLE
) l_Adapter
,
345 NDIS_ATTRIBUTE_DESERIALIZE
346 | NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT
347 | NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT
348 | NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND
,
349 NdisInterfaceInternal
);
351 //=====================================
352 // Initialize simple Adapter parameters
353 //=====================================
355 l_Adapter
->m_Lookahead
= DEFAULT_PACKET_LOOKAHEAD
;
356 l_Adapter
->m_Medium
= l_PreferredMedium
;
357 l_Adapter
->m_DeviceState
= '?';
358 l_Adapter
->m_MiniportAdapterHandle
= p_AdapterHandle
;
360 //==================================
361 // Allocate spinlock for controlling
362 // access to multicast address list.
363 //==================================
364 NdisAllocateSpinLock (&l_Adapter
->m_MCLock
);
365 l_Adapter
->m_MCLockAllocated
= TRUE
;
367 //====================================================
368 // Register a shutdown handler which will be called
369 // on system restart/shutdown to halt our virtual NIC.
370 //====================================================
372 NdisMRegisterAdapterShutdownHandler (p_AdapterHandle
, l_Adapter
,
374 l_Adapter
->m_RegisteredAdapterShutdownHandler
= TRUE
;
376 //============================================
377 // Get parameters from registry which were set
378 // in the adapter advanced properties dialog.
379 //============================================
382 NDIS_HANDLE configHandle
;
383 NDIS_CONFIGURATION_PARAMETER
*parm
;
385 // set defaults in case our registry query fails
386 l_Adapter
->m_MTU
= ETHERNET_MTU
;
387 l_Adapter
->m_MediaStateAlwaysConnected
= FALSE
;
388 l_Adapter
->m_MediaState
= FALSE
;
390 NdisOpenConfiguration (&status
, &configHandle
, p_ConfigurationHandle
);
391 if (status
!= NDIS_STATUS_SUCCESS
)
393 DEBUGP (("[TAP] Couldn't open adapter registry\n"));
394 AdapterFreeResources (l_Adapter
);
398 //====================================
399 // Allocate and construct adapter name
400 //====================================
403 NDIS_STRING mkey
= NDIS_STRING_CONST("MiniportName");
404 NDIS_STRING vkey
= NDIS_STRING_CONST("NdisVersion");
406 NDIS_CONFIGURATION_PARAMETER
*vparm
;
408 NdisReadConfiguration (&vstatus
, &vparm
, configHandle
, &vkey
, NdisParameterInteger
);
409 if (vstatus
== NDIS_STATUS_SUCCESS
)
410 DEBUGP (("[TAP] NdisReadConfiguration NdisVersion=%X\n", vparm
->ParameterData
.IntegerData
));
412 NdisReadConfiguration (&status
, &parm
, configHandle
, &mkey
, NdisParameterString
);
413 if (status
== NDIS_STATUS_SUCCESS
)
415 if (parm
->ParameterType
== NdisParameterString
)
417 DEBUGP (("[TAP] NdisReadConfiguration (MiniportName=%S)\n", parm
->ParameterData
.StringData
.Buffer
));
419 if (RtlUnicodeStringToAnsiString (
420 &l_Adapter
->m_NameAnsi
,
421 &parm
->ParameterData
.StringData
,
422 TRUE
) != STATUS_SUCCESS
)
424 DEBUGP (("[TAP] MiniportName failed\n"));
425 status
= NDIS_STATUS_RESOURCES
;
431 /* "MiniportName" is available only XP and above. Not on Windows 2000. */
432 if (vstatus
== NDIS_STATUS_SUCCESS
&& vparm
->ParameterData
.IntegerData
== 0x50000)
434 /* Fallback for Windows 2000 with NDIS version 5.00.00
435 Don't use this on Vista, 'NDIS_MINIPORT_BLOCK' was changed! */
436 if (RtlUnicodeStringToAnsiString (&l_Adapter
->m_NameAnsi
,
437 &((struct WIN2K_NDIS_MINIPORT_BLOCK
*) p_AdapterHandle
)->MiniportName
,
438 TRUE
) != STATUS_SUCCESS
)
440 DEBUGP (("[TAP] MiniportName (W2K) failed\n"));
441 status
= NDIS_STATUS_RESOURCES
;
445 DEBUGP (("[TAP] MiniportName (W2K) succeeded: %s\n", l_Adapter
->m_NameAnsi
.Buffer
));
446 status
= NDIS_STATUS_SUCCESS
;
452 /* Can't continue without name (see macro 'NAME') */
453 if (status
!= NDIS_STATUS_SUCCESS
|| !l_Adapter
->m_NameAnsi
.Buffer
)
455 NdisCloseConfiguration (configHandle
);
456 AdapterFreeResources (l_Adapter
);
457 DEBUGP (("[TAP] failed to get miniport name\n"));
458 return NDIS_STATUS_RESOURCES
;
461 /* Read MTU setting from registry */
463 NDIS_STRING key
= NDIS_STRING_CONST("MTU");
464 NdisReadConfiguration (&status
, &parm
, configHandle
,
465 &key
, NdisParameterInteger
);
466 if (status
== NDIS_STATUS_SUCCESS
)
468 if (parm
->ParameterType
== NdisParameterInteger
)
470 int mtu
= parm
->ParameterData
.IntegerData
;
471 if (mtu
< MINIMUM_MTU
)
473 if (mtu
> MAXIMUM_MTU
)
475 l_Adapter
->m_MTU
= mtu
;
480 /* Read Media Status setting from registry */
482 NDIS_STRING key
= NDIS_STRING_CONST("MediaStatus");
483 NdisReadConfiguration (&status
, &parm
, configHandle
,
484 &key
, NdisParameterInteger
);
485 if (status
== NDIS_STATUS_SUCCESS
)
487 if (parm
->ParameterType
== NdisParameterInteger
)
489 if (parm
->ParameterData
.IntegerData
)
491 l_Adapter
->m_MediaStateAlwaysConnected
= TRUE
;
492 l_Adapter
->m_MediaState
= TRUE
;
499 /* Read AllowNonAdmin setting from registry */
501 NDIS_STRING key
= NDIS_STRING_CONST("AllowNonAdmin");
502 NdisReadConfiguration (&status
, &parm
, configHandle
,
503 &key
, NdisParameterInteger
);
504 if (status
== NDIS_STATUS_SUCCESS
)
506 if (parm
->ParameterType
== NdisParameterInteger
)
508 if (parm
->ParameterData
.IntegerData
)
510 enable_non_admin
= TRUE
;
517 /* Read optional MAC setting from registry */
519 NDIS_STRING key
= NDIS_STRING_CONST("MAC");
520 ANSI_STRING mac_string
;
521 NdisReadConfiguration (&status
, &parm
, configHandle
,
522 &key
, NdisParameterString
);
523 if (status
== NDIS_STATUS_SUCCESS
)
525 if (parm
->ParameterType
== NdisParameterString
)
527 if (RtlUnicodeStringToAnsiString (&mac_string
, &parm
->ParameterData
.StringData
, TRUE
) == STATUS_SUCCESS
)
529 l_MacFromRegistry
= ParseMAC (l_Adapter
->m_MAC
, mac_string
.Buffer
);
530 RtlFreeAnsiString (&mac_string
);
536 NdisCloseConfiguration (configHandle
);
538 DEBUGP (("[%s] MTU=%d\n", NAME (l_Adapter
), l_Adapter
->m_MTU
));
541 //==================================
542 // Store and update MAC address info
543 //==================================
545 if (!l_MacFromRegistry
)
546 GenerateRandomMac (l_Adapter
->m_MAC
, NAME (l_Adapter
));
548 DEBUGP (("[%s] Using MAC %x:%x:%x:%x:%x:%x\n",
550 l_Adapter
->m_MAC
[0], l_Adapter
->m_MAC
[1], l_Adapter
->m_MAC
[2],
551 l_Adapter
->m_MAC
[3], l_Adapter
->m_MAC
[4], l_Adapter
->m_MAC
[5]));
558 for (i
= 0; i
< sizeof (MACADDR
); ++i
)
559 l_Adapter
->m_MAC_Broadcast
[i
] = 0xFF;
562 //====================================
563 // Initialize TAP device
564 //====================================
566 NDIS_STATUS tap_status
;
567 tap_status
= CreateTapDevice (&l_Adapter
->m_Extension
, NAME (l_Adapter
));
568 if (tap_status
!= NDIS_STATUS_SUCCESS
)
570 AdapterFreeResources (l_Adapter
);
571 DEBUGP (("[TAP] CreateTapDevice failed\n"));
576 if (!AddAdapterToInstanceList (l_Adapter
))
579 TapDeviceFreeResources (&l_Adapter
->m_Extension
);
580 AdapterFreeResources (l_Adapter
);
581 DEBUGP (("[TAP] AddAdapterToInstanceList failed\n"));
582 return NDIS_STATUS_RESOURCES
;
585 l_Adapter
->m_InterfaceIsRunning
= TRUE
;
588 if (enable_non_admin
)
589 AllowNonAdmin (&l_Adapter
->m_Extension
);
592 return NDIS_STATUS_SUCCESS
;
596 AdapterHalt (IN NDIS_HANDLE p_AdapterContext
)
600 TapAdapterPointer l_Adapter
= (TapAdapterPointer
) p_AdapterContext
;
604 l_Adapter
->m_InterfaceIsRunning
= FALSE
;
606 DEBUGP (("[%s] is being halted\n", NAME (l_Adapter
)));
608 DestroyTapDevice (&l_Adapter
->m_Extension
);
611 DEBUGP (("[%s] Freeing Resources\n", NAME (l_Adapter
)));
612 AdapterFreeResources (l_Adapter
);
614 status
= RemoveAdapterFromInstanceList (l_Adapter
);
615 DEBUGP (("[TAP] RemoveAdapterFromInstanceList returned %d\n", (int) status
));
617 DEBUGP (("[TAP] version [%d.%d] %s %s AdapterHalt returning\n",
618 TAP_DRIVER_MAJOR_VERSION
,
619 TAP_DRIVER_MINOR_VERSION
,
625 AdapterFreeResources (TapAdapterPointer p_Adapter
)
627 MYASSERT (!p_Adapter
->m_CalledAdapterFreeResources
);
628 p_Adapter
->m_CalledAdapterFreeResources
= TRUE
;
630 if (p_Adapter
->m_NameAnsi
.Buffer
)
631 RtlFreeAnsiString (&p_Adapter
->m_NameAnsi
);
633 if (p_Adapter
->m_RegisteredAdapterShutdownHandler
)
634 NdisMDeregisterAdapterShutdownHandler (p_Adapter
->m_MiniportAdapterHandle
);
636 if (p_Adapter
->m_MCLockAllocated
)
637 NdisFreeSpinLock (&p_Adapter
->m_MCLock
);
641 DestroyTapDevice (TapExtensionPointer p_Extension
)
643 DEBUGP (("[%s] Destroying tap device\n", p_Extension
->m_TapName
));
645 //======================================
646 // Let clients know we are shutting down
647 //======================================
648 p_Extension
->m_TapIsRunning
= FALSE
;
649 p_Extension
->m_TapOpens
= 0;
650 p_Extension
->m_Halt
= TRUE
;
652 //=====================================
653 // If we are concurrently executing in
654 // TapDeviceHook or AdapterTransmit,
655 // give those calls time to finish.
656 // Note that we must be running at IRQL
657 // < DISPATCH_LEVEL in order to call
659 //=====================================
662 //===========================================================
663 // Exhaust IRP and packet queues. Any pending IRPs will
664 // be cancelled, causing user-space to get this error
665 // on overlapped reads:
666 // The I/O operation has been aborted because of either a
667 // thread exit or an application request. (code=995)
668 // It's important that user-space close the device handle
669 // when this code is returned, so that when we finally
670 // do a NdisMDeregisterDevice, the device reference count
671 // is 0. Otherwise the driver will not unload even if the
672 // the last adapter has been halted.
673 //===========================================================
674 FlushQueues (p_Extension
);
675 NdisMSleep (500000); // give user space time to respond to IRP cancel
677 TapDeviceFreeResources (p_Extension
);
681 TapDeviceFreeResources (TapExtensionPointer p_Extension
)
683 MYASSERT (p_Extension
);
684 MYASSERT (!p_Extension
->m_CalledTapDeviceFreeResources
);
685 p_Extension
->m_CalledTapDeviceFreeResources
= TRUE
;
687 if (p_Extension
->m_PacketQueue
)
688 QueueFree (p_Extension
->m_PacketQueue
);
689 if (p_Extension
->m_IrpQueue
)
690 QueueFree (p_Extension
->m_IrpQueue
);
691 if (p_Extension
->m_InjectQueue
)
692 QueueFree (p_Extension
->m_InjectQueue
);
694 if (p_Extension
->m_CreatedUnicodeLinkName
)
695 RtlFreeUnicodeString (&p_Extension
->m_UnicodeLinkName
);
697 //==========================================================
698 // According to DDK docs, the device is not actually deleted
699 // until its reference count falls to zero. That means we
700 // still need to gracefully fail TapDeviceHook requests
701 // after this point, otherwise ugly things would happen if
702 // the device was disabled (e.g. in the network connections
703 // control panel) while a userspace app still held an open
704 // file handle to it.
705 //==========================================================
707 if (p_Extension
->m_TapDevice
)
710 status
= (NdisMDeregisterDevice (p_Extension
->m_TapDeviceHandle
)
711 == NDIS_STATUS_SUCCESS
);
712 DEBUGP (("[TAP] Deregistering TAP device, status=%d\n", (int)status
));
715 if (p_Extension
->m_TapName
)
716 MemFree (p_Extension
->m_TapName
, NAME_BUFFER_SIZE
);
718 if (p_Extension
->m_InjectDpcInitialized
)
719 KeRemoveQueueDpc (&p_Extension
->m_InjectDpc
);
721 if (p_Extension
->m_AllocatedSpinlocks
)
723 NdisFreeSpinLock (&p_Extension
->m_QueueLock
);
724 NdisFreeSpinLock (&p_Extension
->m_InjectLock
);
728 //========================================================================
729 // Tap Device Initialization
730 //========================================================================
733 CreateTapDevice (TapExtensionPointer p_Extension
, const char *p_Name
)
735 # define SIZEOF_DISPATCH (sizeof(PDRIVER_DISPATCH) * (IRP_MJ_MAXIMUM_FUNCTION + 1))
736 PDRIVER_DISPATCH
*l_Dispatch
= NULL
;
737 ANSI_STRING l_TapString
, l_LinkString
;
738 UNICODE_STRING l_TapUnicode
;
739 BOOLEAN l_FreeTapUnicode
= FALSE
;
740 NTSTATUS l_Status
, l_Return
= NDIS_STATUS_SUCCESS
;
741 const char *l_UsableName
;
743 DEBUGP (("[TAP] version [%d.%d] creating tap device: %s\n",
744 TAP_DRIVER_MAJOR_VERSION
,
745 TAP_DRIVER_MINOR_VERSION
,
748 NdisZeroMemory (p_Extension
, sizeof (TapExtension
));
750 INIT_MUTEX (&p_Extension
->m_OpenCloseMutex
);
752 l_LinkString
.Buffer
= NULL
;
753 l_TapString
.Buffer
= NULL
;
755 l_TapString
.MaximumLength
= l_LinkString
.MaximumLength
= NAME_BUFFER_SIZE
;
757 //=======================================
758 // Set TAP device entry points
759 //=======================================
761 if ((l_Dispatch
= MemAlloc (SIZEOF_DISPATCH
, TRUE
)) == NULL
)
763 DEBUGP (("[%s] couldn't alloc TAP dispatch table\n", p_Name
));
764 l_Return
= NDIS_STATUS_RESOURCES
;
768 l_Dispatch
[IRP_MJ_DEVICE_CONTROL
] = TapDeviceHook
;
769 l_Dispatch
[IRP_MJ_READ
] = TapDeviceHook
;
770 l_Dispatch
[IRP_MJ_WRITE
] = TapDeviceHook
;
771 l_Dispatch
[IRP_MJ_CREATE
] = TapDeviceHook
;
772 l_Dispatch
[IRP_MJ_CLOSE
] = TapDeviceHook
;
774 //==================================
775 // Find the beginning of the GUID
776 //==================================
777 l_UsableName
= p_Name
;
778 while (*l_UsableName
!= '{')
780 if (*l_UsableName
== '\0')
782 DEBUGP (("[%s] couldn't find leading '{' in name\n", p_Name
));
783 l_Return
= NDIS_STATUS_RESOURCES
;
789 //==================================
790 // Allocate pool for TAP device name
791 //==================================
793 if ((p_Extension
->m_TapName
= l_TapString
.Buffer
=
794 MemAlloc (NAME_BUFFER_SIZE
, TRUE
)) == NULL
)
796 DEBUGP (("[%s] couldn't alloc TAP name buffer\n", p_Name
));
797 l_Return
= NDIS_STATUS_RESOURCES
;
801 //================================================
802 // Allocate pool for TAP symbolic link name buffer
803 //================================================
805 if ((l_LinkString
.Buffer
=
806 MemAlloc (NAME_BUFFER_SIZE
, TRUE
)) == NULL
)
808 DEBUGP (("[%s] couldn't alloc TAP symbolic link name buffer\n",
810 l_Return
= NDIS_STATUS_RESOURCES
;
814 //=======================================================
815 // Set TAP device name
816 //=======================================================
818 l_Status
= RtlStringCchPrintfExA
820 l_TapString
.MaximumLength
,
823 STRSAFE_FILL_BEHIND_NULL
| STRSAFE_IGNORE_NULLS
,
829 if (l_Status
!= STATUS_SUCCESS
)
831 DEBUGP (("[%s] couldn't format TAP device name\n",
833 l_Return
= NDIS_STATUS_RESOURCES
;
836 l_TapString
.Length
= (USHORT
) strlen (l_TapString
.Buffer
);
838 DEBUGP (("TAP DEV NAME: '%s'\n", l_TapString
.Buffer
));
840 //=======================================================
842 //=======================================================
844 l_Status
= RtlStringCchPrintfExA
845 (l_LinkString
.Buffer
,
846 l_LinkString
.MaximumLength
,
849 STRSAFE_FILL_BEHIND_NULL
| STRSAFE_IGNORE_NULLS
,
855 if (l_Status
!= STATUS_SUCCESS
)
857 DEBUGP (("[%s] couldn't format TAP device symbolic link\n",
859 l_Return
= NDIS_STATUS_RESOURCES
;
862 l_LinkString
.Length
= (USHORT
) strlen (l_LinkString
.Buffer
);
864 DEBUGP (("TAP LINK NAME: '%s'\n", l_LinkString
.Buffer
));
866 //==================================================
867 // Convert strings to unicode
868 //==================================================
869 if (RtlAnsiStringToUnicodeString (&l_TapUnicode
, &l_TapString
, TRUE
) !=
872 DEBUGP (("[%s] couldn't alloc TAP unicode name buffer\n",
874 l_Return
= NDIS_STATUS_RESOURCES
;
877 l_FreeTapUnicode
= TRUE
;
879 if (RtlAnsiStringToUnicodeString
880 (&p_Extension
->m_UnicodeLinkName
, &l_LinkString
, TRUE
)
884 (("[%s] Couldn't allocate unicode string for symbolic link name\n",
886 l_Return
= NDIS_STATUS_RESOURCES
;
889 p_Extension
->m_CreatedUnicodeLinkName
= TRUE
;
891 //==================================================
892 // Create new TAP device with symbolic
893 // link and associate with adapter.
894 //==================================================
896 l_Status
= NdisMRegisterDevice
897 (g_NdisWrapperHandle
,
899 &p_Extension
->m_UnicodeLinkName
,
901 &p_Extension
->m_TapDevice
,
902 &p_Extension
->m_TapDeviceHandle
905 if (l_Status
!= STATUS_SUCCESS
)
907 DEBUGP (("[%s] couldn't be created\n", p_Name
));
908 l_Return
= NDIS_STATUS_RESOURCES
;
912 /* Set TAP device flags */
913 p_Extension
->m_TapDevice
->Flags
|= DO_DIRECT_IO
;
915 //========================================================
916 // Initialize Packet and IRP queues.
918 // The packet queue is used to buffer data which has been
919 // "transmitted" by the virtual NIC, before user space
920 // has had a chance to read it.
922 // The IRP queue is used to buffer pending I/O requests
923 // from userspace, i.e. read requests on the TAP device
924 // waiting for the system to "transmit" something through
927 // Basically, packets in the packet queue are used
928 // to satisfy IRP requests in the IRP queue.
930 // QueueLock is used to lock the packet queue used
931 // for the TAP-Win32 NIC -> User Space packet flow direction.
933 // All accesses to packet or IRP queues should be
934 // bracketed by the QueueLock spinlock,
935 // in order to be SMP-safe.
936 //========================================================
938 NdisAllocateSpinLock (&p_Extension
->m_QueueLock
);
939 NdisAllocateSpinLock (&p_Extension
->m_InjectLock
);
940 p_Extension
->m_AllocatedSpinlocks
= TRUE
;
942 p_Extension
->m_PacketQueue
= QueueInit (PACKET_QUEUE_SIZE
);
943 p_Extension
->m_IrpQueue
= QueueInit (IRP_QUEUE_SIZE
);
944 p_Extension
->m_InjectQueue
= QueueInit (INJECT_QUEUE_SIZE
);
945 if (!p_Extension
->m_PacketQueue
946 || !p_Extension
->m_IrpQueue
947 || !p_Extension
->m_InjectQueue
)
949 DEBUGP (("[%s] couldn't alloc TAP queues\n", p_Name
));
950 l_Return
= NDIS_STATUS_RESOURCES
;
954 //=================================================================
955 // Initialize deferred procedure call for DHCP/ARP packet injection
956 //=================================================================
958 KeInitializeDpc (&p_Extension
->m_InjectDpc
, InjectPacketDpc
, NULL
);
959 p_Extension
->m_InjectDpcInitialized
= TRUE
;
961 //========================
962 // Finalize initialization
963 //========================
965 p_Extension
->m_TapIsRunning
= TRUE
;
967 DEBUGP (("[%s] successfully created TAP device [%s]\n", p_Name
,
968 p_Extension
->m_TapName
));
971 if (l_FreeTapUnicode
)
972 RtlFreeUnicodeString (&l_TapUnicode
);
973 if (l_LinkString
.Buffer
)
974 MemFree (l_LinkString
.Buffer
, NAME_BUFFER_SIZE
);
976 MemFree (l_Dispatch
, SIZEOF_DISPATCH
);
978 if (l_Return
!= NDIS_STATUS_SUCCESS
)
979 TapDeviceFreeResources (p_Extension
);
983 #undef SIZEOF_DISPATCH
985 //========================================================
987 //========================================================
989 AdapterReset (OUT PBOOLEAN p_AddressingReset
, IN NDIS_HANDLE p_AdapterContext
)
991 TapAdapterPointer l_Adapter
= (TapAdapterPointer
) p_AdapterContext
;
992 DEBUGP (("[%s] is resetting\n", NAME (l_Adapter
)));
993 return NDIS_STATUS_SUCCESS
;
996 NDIS_STATUS AdapterReceive
997 (OUT PNDIS_PACKET p_Packet
,
998 OUT PUINT p_Transferred
,
999 IN NDIS_HANDLE p_AdapterContext
,
1000 IN NDIS_HANDLE p_ReceiveContext
,
1002 IN UINT p_ToTransfer
)
1004 return NDIS_STATUS_SUCCESS
;
1007 //==============================================================
1008 // Adapter Option Query/Modification
1009 //==============================================================
1010 NDIS_STATUS AdapterQuery
1011 (IN NDIS_HANDLE p_AdapterContext
,
1014 IN ULONG p_BufferLength
,
1015 OUT PULONG p_BytesWritten
, OUT PULONG p_BytesNeeded
)
1017 TapAdapterPointer l_Adapter
= (TapAdapterPointer
) p_AdapterContext
;
1018 TapAdapterQuery l_Query
, *l_QueryPtr
= &l_Query
;
1019 NDIS_STATUS l_Status
= NDIS_STATUS_SUCCESS
;
1020 UINT l_QueryLength
= 4;
1021 BOOLEAN lock_succeeded
;
1023 NdisZeroMemory (&l_Query
, sizeof (l_Query
));
1027 //===================================================================
1028 // Vendor & Driver version Info
1029 //===================================================================
1030 case OID_GEN_VENDOR_DESCRIPTION
:
1031 l_QueryPtr
= (TapAdapterQueryPointer
) PRODUCT_STRING
;
1032 l_QueryLength
= strlen (PRODUCT_STRING
) + 1;
1035 case OID_GEN_VENDOR_ID
:
1036 l_Query
.m_Long
= 0xffffff;
1039 case OID_GEN_DRIVER_VERSION
:
1041 (((USHORT
) TAP_NDIS_MAJOR_VERSION
) << 8 | (USHORT
)
1042 TAP_NDIS_MINOR_VERSION
);
1043 l_QueryLength
= sizeof (unsigned short);
1046 case OID_GEN_VENDOR_DRIVER_VERSION
:
1048 (((USHORT
) TAP_DRIVER_MAJOR_VERSION
) << 8 | (USHORT
)
1049 TAP_DRIVER_MINOR_VERSION
);
1052 //=================================================================
1054 //=================================================================
1055 case OID_GEN_RCV_NO_BUFFER
:
1059 case OID_802_3_RCV_ERROR_ALIGNMENT
:
1063 case OID_802_3_XMIT_ONE_COLLISION
:
1067 case OID_802_3_XMIT_MORE_COLLISIONS
:
1071 case OID_GEN_XMIT_OK
:
1072 l_Query
.m_Long
= l_Adapter
->m_Tx
;
1075 case OID_GEN_RCV_OK
:
1076 l_Query
.m_Long
= l_Adapter
->m_Rx
;
1079 case OID_GEN_XMIT_ERROR
:
1080 l_Query
.m_Long
= l_Adapter
->m_TxErr
;
1083 case OID_GEN_RCV_ERROR
:
1084 l_Query
.m_Long
= l_Adapter
->m_RxErr
;
1087 //===================================================================
1088 // Device & Protocol Options
1089 //===================================================================
1090 case OID_GEN_SUPPORTED_LIST
:
1091 l_QueryPtr
= (TapAdapterQueryPointer
) g_SupportedOIDList
;
1092 l_QueryLength
= sizeof (g_SupportedOIDList
);
1095 case OID_GEN_MAC_OPTIONS
:
1096 // This MUST be here !!!
1097 l_Query
.m_Long
= (NDIS_MAC_OPTION_RECEIVE_SERIALIZED
1098 | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA
1099 | NDIS_MAC_OPTION_NO_LOOPBACK
1100 | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND
);
1104 case OID_GEN_CURRENT_PACKET_FILTER
:
1106 (NDIS_PACKET_TYPE_ALL_LOCAL
|
1107 NDIS_PACKET_TYPE_BROADCAST
|
1108 NDIS_PACKET_TYPE_DIRECTED
| NDIS_PACKET_TYPE_ALL_FUNCTIONAL
);
1112 case OID_GEN_PROTOCOL_OPTIONS
:
1116 //==================================================================
1118 //==================================================================
1119 case OID_GEN_MEDIA_CONNECT_STATUS
:
1120 l_Query
.m_Long
= l_Adapter
->m_MediaState
1121 ? NdisMediaStateConnected
: NdisMediaStateDisconnected
;
1124 case OID_GEN_HARDWARE_STATUS
:
1125 l_Query
.m_HardwareStatus
= NdisHardwareStatusReady
;
1126 l_QueryLength
= sizeof (NDIS_HARDWARE_STATUS
);
1129 case OID_GEN_MEDIA_SUPPORTED
:
1130 case OID_GEN_MEDIA_IN_USE
:
1131 l_Query
.m_Medium
= l_Adapter
->m_Medium
;
1132 l_QueryLength
= sizeof (NDIS_MEDIUM
);
1135 case OID_GEN_PHYSICAL_MEDIUM
:
1136 l_Query
.m_PhysicalMedium
= NdisPhysicalMediumUnspecified
;
1137 l_QueryLength
= sizeof (NDIS_PHYSICAL_MEDIUM
);
1140 case OID_GEN_LINK_SPEED
:
1141 l_Query
.m_Long
= 100000; // rate / 100 bps
1144 case OID_802_3_PERMANENT_ADDRESS
:
1145 case OID_802_3_CURRENT_ADDRESS
:
1146 COPY_MAC (l_Query
.m_MacAddress
, l_Adapter
->m_MAC
);
1147 l_QueryLength
= sizeof (MACADDR
);
1150 //==================================================================
1152 //==================================================================
1154 case OID_GEN_MAXIMUM_SEND_PACKETS
:
1158 case OID_802_3_MAXIMUM_LIST_SIZE
:
1159 l_Query
.m_Long
= NIC_MAX_MCAST_LIST
;
1162 case OID_GEN_CURRENT_LOOKAHEAD
:
1163 l_Query
.m_Long
= l_Adapter
->m_Lookahead
;
1166 case OID_GEN_MAXIMUM_LOOKAHEAD
:
1167 case OID_GEN_MAXIMUM_TOTAL_SIZE
:
1168 case OID_GEN_RECEIVE_BUFFER_SPACE
:
1169 case OID_GEN_RECEIVE_BLOCK_SIZE
:
1170 l_Query
.m_Long
= DEFAULT_PACKET_LOOKAHEAD
;
1173 case OID_GEN_MAXIMUM_FRAME_SIZE
:
1174 case OID_GEN_TRANSMIT_BLOCK_SIZE
:
1175 case OID_GEN_TRANSMIT_BUFFER_SPACE
:
1176 l_Query
.m_Long
= l_Adapter
->m_MTU
;
1179 case OID_PNP_CAPABILITIES
:
1182 PNDIS_PNP_CAPABILITIES pPNPCapabilities
;
1183 PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct
;
1185 if (p_BufferLength
>= sizeof (NDIS_PNP_CAPABILITIES
))
1187 pPNPCapabilities
= (PNDIS_PNP_CAPABILITIES
) (p_Buffer
);
1190 // Setting up the buffer to be returned
1191 // to the Protocol above the Passthru miniport
1193 pPMstruct
= &pPNPCapabilities
->WakeUpCapabilities
;
1194 pPMstruct
->MinMagicPacketWakeUp
= NdisDeviceStateUnspecified
;
1195 pPMstruct
->MinPatternWakeUp
= NdisDeviceStateUnspecified
;
1196 pPMstruct
->MinLinkChangeWakeUp
= NdisDeviceStateUnspecified
;
1198 l_QueryLength
= sizeof (NDIS_PNP_CAPABILITIES
);
1202 case OID_PNP_QUERY_POWER
:
1205 // Required OIDs that we don't support
1207 case OID_GEN_SUPPORTED_GUIDS
:
1208 case OID_GEN_MEDIA_CAPABILITIES
:
1209 case OID_TCP_TASK_OFFLOAD
:
1210 case OID_FFP_SUPPORT
:
1211 l_Status
= NDIS_STATUS_INVALID_OID
;
1214 // Optional stats OIDs
1216 case OID_GEN_DIRECTED_BYTES_XMIT
:
1217 case OID_GEN_DIRECTED_FRAMES_XMIT
:
1218 case OID_GEN_MULTICAST_BYTES_XMIT
:
1219 case OID_GEN_MULTICAST_FRAMES_XMIT
:
1220 case OID_GEN_BROADCAST_BYTES_XMIT
:
1221 case OID_GEN_BROADCAST_FRAMES_XMIT
:
1222 case OID_GEN_DIRECTED_BYTES_RCV
:
1223 case OID_GEN_DIRECTED_FRAMES_RCV
:
1224 case OID_GEN_MULTICAST_BYTES_RCV
:
1225 case OID_GEN_MULTICAST_FRAMES_RCV
:
1226 case OID_GEN_BROADCAST_BYTES_RCV
:
1227 case OID_GEN_BROADCAST_FRAMES_RCV
:
1228 l_Status
= NDIS_STATUS_INVALID_OID
;
1231 //===================================================================
1233 //===================================================================
1235 DEBUGP (("[%s] Unhandled OID %lx\n", NAME (l_Adapter
), p_OID
));
1236 l_Status
= NDIS_STATUS_INVALID_OID
;
1240 if (l_Status
!= NDIS_STATUS_SUCCESS
)
1242 else if (l_QueryLength
> p_BufferLength
)
1244 l_Status
= NDIS_STATUS_INVALID_LENGTH
;
1245 *p_BytesNeeded
= l_QueryLength
;
1248 NdisMoveMemory (p_Buffer
, (PVOID
) l_QueryPtr
,
1249 (*p_BytesWritten
= l_QueryLength
));
1254 NDIS_STATUS AdapterModify
1255 (IN NDIS_HANDLE p_AdapterContext
,
1258 IN ULONG p_BufferLength
,
1259 OUT PULONG p_BytesRead
,
1260 OUT PULONG p_BytesNeeded
)
1262 TapAdapterQueryPointer l_Query
= (TapAdapterQueryPointer
) p_Buffer
;
1263 TapAdapterPointer l_Adapter
= (TapAdapterPointer
) p_AdapterContext
;
1264 NDIS_STATUS l_Status
= NDIS_STATUS_INVALID_OID
;
1269 //==================================================================
1271 //==================================================================
1272 case OID_802_3_MULTICAST_LIST
:
1273 DEBUGP (("[%s] Setting [OID_802_3_MULTICAST_LIST]\n",
1276 *p_BytesNeeded
= sizeof (ETH_ADDR
);
1277 *p_BytesRead
= p_BufferLength
;
1279 if (p_BufferLength
% sizeof (ETH_ADDR
))
1280 l_Status
= NDIS_STATUS_INVALID_LENGTH
;
1281 else if (p_BufferLength
> sizeof (MC_LIST
))
1283 l_Status
= NDIS_STATUS_MULTICAST_FULL
;
1284 *p_BytesNeeded
= sizeof (MC_LIST
);
1288 NdisAcquireSpinLock (&l_Adapter
->m_MCLock
);
1290 NdisZeroMemory(&l_Adapter
->m_MCList
, sizeof (MC_LIST
));
1292 NdisMoveMemory(&l_Adapter
->m_MCList
,
1296 l_Adapter
->m_MCListSize
= p_BufferLength
/ sizeof (ETH_ADDR
);
1298 NdisReleaseSpinLock (&l_Adapter
->m_MCLock
);
1300 l_Status
= NDIS_STATUS_SUCCESS
;
1304 case OID_GEN_CURRENT_PACKET_FILTER
:
1305 l_Status
= NDIS_STATUS_INVALID_LENGTH
;
1308 if (p_BufferLength
>= sizeof (ULONG
))
1311 (("[%s] Setting [OID_GEN_CURRENT_PACKET_FILTER] to [0x%02lx]\n",
1312 NAME (l_Adapter
), l_Query
->m_Long
));
1313 l_Status
= NDIS_STATUS_SUCCESS
;
1314 *p_BytesRead
= sizeof (ULONG
);
1318 case OID_GEN_CURRENT_LOOKAHEAD
:
1319 if (p_BufferLength
< sizeof (ULONG
))
1321 l_Status
= NDIS_STATUS_INVALID_LENGTH
;
1324 else if (l_Query
->m_Long
> DEFAULT_PACKET_LOOKAHEAD
1325 || l_Query
->m_Long
<= 0)
1327 l_Status
= NDIS_STATUS_INVALID_DATA
;
1331 DEBUGP (("[%s] Setting [OID_GEN_CURRENT_LOOKAHEAD] to [%d]\n",
1332 NAME (l_Adapter
), l_Query
->m_Long
));
1333 l_Adapter
->m_Lookahead
= l_Query
->m_Long
;
1334 l_Status
= NDIS_STATUS_SUCCESS
;
1335 *p_BytesRead
= sizeof (ULONG
);
1339 case OID_GEN_NETWORK_LAYER_ADDRESSES
:
1340 l_Status
= NDIS_STATUS_SUCCESS
;
1341 *p_BytesRead
= *p_BytesNeeded
= 0;
1344 case OID_GEN_TRANSPORT_HEADER_OFFSET
:
1345 l_Status
= NDIS_STATUS_SUCCESS
;
1346 *p_BytesRead
= *p_BytesNeeded
= 0;
1349 case OID_PNP_SET_POWER
:
1352 NDIS_DEVICE_POWER_STATE NewDeviceState
;
1354 NewDeviceState
= (*(PNDIS_DEVICE_POWER_STATE
) p_Buffer
);
1356 switch (NewDeviceState
)
1358 case NdisDeviceStateD0
:
1359 l_Adapter
->m_DeviceState
= '0';
1361 case NdisDeviceStateD1
:
1362 l_Adapter
->m_DeviceState
= '1';
1364 case NdisDeviceStateD2
:
1365 l_Adapter
->m_DeviceState
= '2';
1367 case NdisDeviceStateD3
:
1368 l_Adapter
->m_DeviceState
= '3';
1371 l_Adapter
->m_DeviceState
= '?';
1375 l_Status
= NDIS_STATUS_FAILURE
;
1378 // Check for invalid length
1380 if (p_BufferLength
< sizeof (NDIS_DEVICE_POWER_STATE
))
1382 l_Status
= NDIS_STATUS_INVALID_LENGTH
;
1386 if (NewDeviceState
> NdisDeviceStateD0
)
1388 l_Adapter
->m_InterfaceIsRunning
= FALSE
;
1389 DEBUGP (("[%s] Power management device state OFF\n",
1394 l_Adapter
->m_InterfaceIsRunning
= TRUE
;
1395 DEBUGP (("[%s] Power management device state ON\n",
1399 l_Status
= NDIS_STATUS_SUCCESS
;
1403 if (l_Status
== NDIS_STATUS_SUCCESS
)
1405 *p_BytesRead
= sizeof (NDIS_DEVICE_POWER_STATE
);
1411 *p_BytesNeeded
= sizeof (NDIS_DEVICE_POWER_STATE
);
1415 case OID_PNP_REMOVE_WAKE_UP_PATTERN
:
1416 case OID_PNP_ADD_WAKE_UP_PATTERN
:
1417 l_Status
= NDIS_STATUS_SUCCESS
;
1418 *p_BytesRead
= *p_BytesNeeded
= 0;
1422 DEBUGP (("[%s] Can't set value for OID %lx\n", NAME (l_Adapter
),
1424 l_Status
= NDIS_STATUS_INVALID_OID
;
1425 *p_BytesRead
= *p_BytesNeeded
= 0;
1432 //====================================================================
1433 // Adapter Transmission
1434 //====================================================================
1436 AdapterTransmit (IN NDIS_HANDLE p_AdapterContext
,
1437 IN PNDIS_PACKET p_Packet
,
1440 TapAdapterPointer l_Adapter
= (TapAdapterPointer
) p_AdapterContext
;
1441 ULONG l_Index
= 0, l_PacketLength
= 0;
1442 UINT l_BufferLength
= 0;
1444 TapPacketPointer l_PacketBuffer
;
1445 PNDIS_BUFFER l_NDIS_Buffer
;
1449 NdisQueryPacket (p_Packet
, NULL
, NULL
, &l_NDIS_Buffer
, &l_PacketLength
);
1451 //====================================================
1452 // Here we abandon the transmission attempt if any of
1453 // the parameters is wrong or memory allocation fails
1454 // but we do not indicate failure. The packet is
1455 // silently dropped.
1456 //====================================================
1458 if (l_PacketLength
< ETHERNET_HEADER_SIZE
|| l_PacketLength
> 65535)
1460 else if (!l_Adapter
->m_Extension
.m_TapOpens
|| !l_Adapter
->m_MediaState
)
1461 goto exit_success
; // Nothing is bound to the TAP device
1463 if (NdisAllocateMemoryWithTag (&l_PacketBuffer
,
1464 TAP_PACKET_SIZE (l_PacketLength
),
1465 '5PAT') != NDIS_STATUS_SUCCESS
)
1466 goto exit_no_resources
;
1468 if (l_PacketBuffer
== NULL
)
1469 goto exit_no_resources
;
1471 l_PacketBuffer
->m_SizeFlags
= (l_PacketLength
& TP_SIZE_MASK
);
1473 //===========================
1474 // Reassemble packet contents
1475 //===========================
1480 while (l_NDIS_Buffer
&& l_Index
< l_PacketLength
)
1483 NdisQueryBuffer (l_NDIS_Buffer
, (PVOID
*) & l_Buffer
,
1485 newlen
= l_Index
+ l_BufferLength
;
1486 if (newlen
> l_PacketLength
)
1489 goto no_queue
; /* overflow */
1491 NdisMoveMemory (l_PacketBuffer
->m_Data
+ l_Index
, l_Buffer
,
1494 NdisGetNextBuffer (l_NDIS_Buffer
, &l_NDIS_Buffer
);
1496 if (l_Index
!= l_PacketLength
)
1499 goto no_queue
; /* underflow */
1502 DUMP_PACKET ("AdapterTransmit", l_PacketBuffer
->m_Data
, l_PacketLength
);
1504 //=====================================================
1505 // If IPv4 packet, check whether or not packet
1507 //=====================================================
1508 #if PACKET_TRUNCATION_CHECK
1509 IPv4PacketSizeVerify (l_PacketBuffer
->m_Data
, l_PacketLength
, FALSE
, "TX", &l_Adapter
->m_TxTrunc
);
1512 //=====================================================
1513 // Are we running in DHCP server masquerade mode?
1515 // If so, catch both DHCP requests and ARP queries
1516 // to resolve the address of our virtual DHCP server.
1517 //=====================================================
1518 if (l_Adapter
->m_dhcp_enabled
)
1520 const ETH_HEADER
*eth
= (ETH_HEADER
*) l_PacketBuffer
->m_Data
;
1521 const IPHDR
*ip
= (IPHDR
*) (l_PacketBuffer
->m_Data
+ sizeof (ETH_HEADER
));
1522 const UDPHDR
*udp
= (UDPHDR
*) (l_PacketBuffer
->m_Data
+ sizeof (ETH_HEADER
) + sizeof (IPHDR
));
1525 if (l_PacketLength
== sizeof (ARP_PACKET
)
1526 && eth
->proto
== htons (ETH_P_ARP
)
1527 && l_Adapter
->m_dhcp_server_arp
)
1529 if (ProcessARP (l_Adapter
,
1530 (PARP_PACKET
) l_PacketBuffer
->m_Data
,
1531 l_Adapter
->m_dhcp_addr
,
1532 l_Adapter
->m_dhcp_server_ip
,
1534 l_Adapter
->m_dhcp_server_mac
))
1539 else if (l_PacketLength
>= sizeof (ETH_HEADER
) + sizeof (IPHDR
) + sizeof (UDPHDR
) + sizeof (DHCP
)
1540 && eth
->proto
== htons (ETH_P_IP
)
1541 && ip
->version_len
== 0x45 // IPv4, 20 byte header
1542 && ip
->protocol
== IPPROTO_UDP
1543 && udp
->dest
== htons (BOOTPS_PORT
))
1545 const DHCP
*dhcp
= (DHCP
*) (l_PacketBuffer
->m_Data
1546 + sizeof (ETH_HEADER
)
1550 const int optlen
= l_PacketLength
1551 - sizeof (ETH_HEADER
)
1556 if (optlen
> 0) // we must have at least one DHCP option
1558 if (ProcessDHCP (l_Adapter
, eth
, ip
, udp
, dhcp
, optlen
))
1566 //===============================================
1567 // In Point-To-Point mode, check to see whether
1568 // packet is ARP or IPv4 (if neither, then drop).
1569 //===============================================
1570 if (l_Adapter
->m_tun
)
1574 if (l_PacketLength
< ETHERNET_HEADER_SIZE
)
1577 e
= (ETH_HEADER
*) l_PacketBuffer
->m_Data
;
1579 switch (ntohs (e
->proto
))
1583 // Make sure that packet is the
1584 // right size for ARP.
1585 if (l_PacketLength
!= sizeof (ARP_PACKET
))
1588 ProcessARP (l_Adapter
,
1589 (PARP_PACKET
) l_PacketBuffer
->m_Data
,
1590 l_Adapter
->m_localIP
,
1591 l_Adapter
->m_remoteNetwork
,
1592 l_Adapter
->m_remoteNetmask
,
1593 l_Adapter
->m_TapToUser
.dest
);
1600 // Make sure that packet is large
1601 // enough to be IPv4.
1603 < ETHERNET_HEADER_SIZE
+ IP_HEADER_SIZE
)
1606 // Only accept directed packets,
1608 if (memcmp (e
, &l_Adapter
->m_TapToUser
, ETHERNET_HEADER_SIZE
))
1611 // Packet looks like IPv4, queue it.
1612 l_PacketBuffer
->m_SizeFlags
|= TP_TUN
;
1616 //===============================================
1617 // Push packet onto queue to wait for read from
1619 //===============================================
1621 NdisAcquireSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
1624 if (IS_UP (l_Adapter
))
1625 result
= QueuePush (l_Adapter
->m_Extension
.m_PacketQueue
, l_PacketBuffer
);
1627 NdisReleaseSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
1629 if ((TapPacketPointer
) result
!= l_PacketBuffer
)
1631 // adapter receive overrun
1632 INCREMENT_STAT (l_Adapter
->m_TxErr
);
1637 INCREMENT_STAT (l_Adapter
->m_Tx
);
1640 //============================================================
1641 // Cycle through IRPs and packets, try to satisfy each pending
1642 // IRP with a queued packet.
1643 //============================================================
1647 l_PacketBuffer
= NULL
;
1649 NdisAcquireSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
1651 if (IS_UP (l_Adapter
)
1652 && QueueCount (l_Adapter
->m_Extension
.m_PacketQueue
)
1653 && QueueCount (l_Adapter
->m_Extension
.m_IrpQueue
))
1655 l_IRP
= (PIRP
) QueuePop (l_Adapter
->m_Extension
.m_IrpQueue
);
1656 l_PacketBuffer
= (TapPacketPointer
)
1657 QueuePop (l_Adapter
->m_Extension
.m_PacketQueue
);
1660 NdisReleaseSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
1662 MYASSERT ((l_IRP
!= NULL
) + (l_PacketBuffer
!= NULL
) != 1);
1664 if (l_IRP
&& l_PacketBuffer
)
1668 IO_NETWORK_INCREMENT
);
1674 __except (EXCEPTION_EXECUTE_HANDLER
)
1678 return NDIS_STATUS_SUCCESS
;
1681 NdisFreeMemory (l_PacketBuffer
,
1682 TAP_PACKET_SIZE (l_PacketLength
),
1686 return NDIS_STATUS_SUCCESS
;
1689 return NDIS_STATUS_FAILURE
;
1692 return NDIS_STATUS_RESOURCES
;
1695 //======================================================================
1696 // Hooks for catching TAP device IRP's.
1697 //======================================================================
1700 TapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject
, IN PIRP p_IRP
)
1702 TapAdapterPointer l_Adapter
= LookupAdapterInInstanceList (p_DeviceObject
);
1703 PIO_STACK_LOCATION l_IrpSp
;
1704 NTSTATUS l_Status
= STATUS_SUCCESS
;
1707 l_IrpSp
= IoGetCurrentIrpStackLocation (p_IRP
);
1709 p_IRP
->IoStatus
.Status
= STATUS_SUCCESS
;
1710 p_IRP
->IoStatus
.Information
= 0;
1712 if (!l_Adapter
|| l_Adapter
->m_Extension
.m_Halt
)
1714 DEBUGP (("TapDeviceHook called when TAP device is halted, MajorFunction=%d\n",
1715 (int)l_IrpSp
->MajorFunction
));
1717 if (l_IrpSp
->MajorFunction
== IRP_MJ_CLOSE
)
1719 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
1720 return STATUS_SUCCESS
;
1724 p_IRP
->IoStatus
.Status
= STATUS_NO_SUCH_DEVICE
;
1725 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
1726 return STATUS_NO_SUCH_DEVICE
;
1730 switch (l_IrpSp
->MajorFunction
)
1732 //===========================================================
1733 // Ioctl call handlers
1734 //===========================================================
1735 case IRP_MJ_DEVICE_CONTROL
:
1737 switch (l_IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
1739 case TAP_IOCTL_GET_MAC
:
1741 if (l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
1742 >= sizeof (MACADDR
))
1744 COPY_MAC (p_IRP
->AssociatedIrp
.SystemBuffer
,
1746 p_IRP
->IoStatus
.Information
= sizeof (MACADDR
);
1751 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_BUFFER_TOO_SMALL
;
1755 case TAP_IOCTL_GET_VERSION
:
1757 const ULONG size
= sizeof (ULONG
) * 3;
1758 if (l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
1761 ((PULONG
) (p_IRP
->AssociatedIrp
.SystemBuffer
))[0]
1762 = TAP_DRIVER_MAJOR_VERSION
;
1763 ((PULONG
) (p_IRP
->AssociatedIrp
.SystemBuffer
))[1]
1764 = TAP_DRIVER_MINOR_VERSION
;
1765 ((PULONG
) (p_IRP
->AssociatedIrp
.SystemBuffer
))[2]
1771 p_IRP
->IoStatus
.Information
= size
;
1776 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_BUFFER_TOO_SMALL
;
1781 case TAP_IOCTL_GET_MTU
:
1783 const ULONG size
= sizeof (ULONG
) * 1;
1784 if (l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
1787 ((PULONG
) (p_IRP
->AssociatedIrp
.SystemBuffer
))[0]
1789 p_IRP
->IoStatus
.Information
= size
;
1794 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_BUFFER_TOO_SMALL
;
1799 case TAP_IOCTL_GET_INFO
:
1802 if (l_Adapter
->m_InterfaceIsRunning
)
1806 if (l_Adapter
->m_Extension
.m_TapIsRunning
)
1810 state
[2] = l_Adapter
->m_DeviceState
;
1811 if (l_Adapter
->m_MediaStateAlwaysConnected
)
1817 p_IRP
->IoStatus
.Status
= l_Status
= RtlStringCchPrintfExA (
1818 ((LPTSTR
) (p_IRP
->AssociatedIrp
.SystemBuffer
)),
1819 l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
,
1822 STRSAFE_FILL_BEHIND_NULL
| STRSAFE_IGNORE_NULLS
,
1823 #if PACKET_TRUNCATION_CHECK
1824 "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]",
1826 "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]",
1829 g_LastErrorFilename
,
1830 g_LastErrorLineNumber
,
1831 (int)l_Adapter
->m_Extension
.m_NumTapOpens
,
1832 (int)l_Adapter
->m_Tx
,
1833 (int)l_Adapter
->m_TxErr
,
1834 #if PACKET_TRUNCATION_CHECK
1835 (int)l_Adapter
->m_TxTrunc
,
1837 (int)l_Adapter
->m_Rx
,
1838 (int)l_Adapter
->m_RxErr
,
1839 #if PACKET_TRUNCATION_CHECK
1840 (int)l_Adapter
->m_RxTrunc
,
1842 (int)l_Adapter
->m_Extension
.m_IrpQueue
->size
,
1843 (int)l_Adapter
->m_Extension
.m_IrpQueue
->max_size
,
1844 (int)IRP_QUEUE_SIZE
,
1845 (int)l_Adapter
->m_Extension
.m_PacketQueue
->size
,
1846 (int)l_Adapter
->m_Extension
.m_PacketQueue
->max_size
,
1847 (int)PACKET_QUEUE_SIZE
,
1848 (int)l_Adapter
->m_Extension
.m_InjectQueue
->size
,
1849 (int)l_Adapter
->m_Extension
.m_InjectQueue
->max_size
,
1850 (int)INJECT_QUEUE_SIZE
1853 p_IRP
->IoStatus
.Information
1854 = l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
1860 case TAP_IOCTL_GET_LOG_LINE
:
1862 if (GetDebugLine ((LPTSTR
)p_IRP
->AssociatedIrp
.SystemBuffer
,
1863 l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
))
1864 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_SUCCESS
;
1866 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
1868 p_IRP
->IoStatus
.Information
1869 = l_IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
1875 case TAP_IOCTL_CONFIG_TUN
:
1877 if (l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
>=
1878 (sizeof (IPADDR
) * 3))
1882 l_Adapter
->m_tun
= FALSE
;
1884 GenerateRelatedMAC (dest
, l_Adapter
->m_MAC
, 1);
1886 l_Adapter
->m_localIP
= ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[0];
1887 l_Adapter
->m_remoteNetwork
= ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[1];
1888 l_Adapter
->m_remoteNetmask
= ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[2];
1890 // sanity check on network/netmask
1891 if ((l_Adapter
->m_remoteNetwork
& l_Adapter
->m_remoteNetmask
) != l_Adapter
->m_remoteNetwork
)
1894 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
1898 COPY_MAC (l_Adapter
->m_TapToUser
.src
, l_Adapter
->m_MAC
);
1899 COPY_MAC (l_Adapter
->m_TapToUser
.dest
, dest
);
1900 COPY_MAC (l_Adapter
->m_UserToTap
.src
, dest
);
1901 COPY_MAC (l_Adapter
->m_UserToTap
.dest
, l_Adapter
->m_MAC
);
1903 l_Adapter
->m_TapToUser
.proto
= l_Adapter
->m_UserToTap
.proto
= htons (ETH_P_IP
);
1905 l_Adapter
->m_tun
= TRUE
;
1907 CheckIfDhcpAndTunMode (l_Adapter
);
1909 p_IRP
->IoStatus
.Information
= 1; // Simple boolean value
1914 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
1920 case TAP_IOCTL_CONFIG_POINT_TO_POINT
: // Obsoleted by TAP_IOCTL_CONFIG_TUN
1922 if (l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
>=
1923 (sizeof (IPADDR
) * 2))
1927 l_Adapter
->m_tun
= FALSE
;
1929 GenerateRelatedMAC (dest
, l_Adapter
->m_MAC
, 1);
1931 l_Adapter
->m_localIP
= ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[0];
1932 l_Adapter
->m_remoteNetwork
= ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[1];
1933 l_Adapter
->m_remoteNetmask
= ~0;
1935 COPY_MAC (l_Adapter
->m_TapToUser
.src
, l_Adapter
->m_MAC
);
1936 COPY_MAC (l_Adapter
->m_TapToUser
.dest
, dest
);
1937 COPY_MAC (l_Adapter
->m_UserToTap
.src
, dest
);
1938 COPY_MAC (l_Adapter
->m_UserToTap
.dest
, l_Adapter
->m_MAC
);
1940 l_Adapter
->m_TapToUser
.proto
= l_Adapter
->m_UserToTap
.proto
= htons (ETH_P_IP
);
1942 l_Adapter
->m_tun
= TRUE
;
1944 CheckIfDhcpAndTunMode (l_Adapter
);
1946 p_IRP
->IoStatus
.Information
= 1; // Simple boolean value
1951 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
1957 case TAP_IOCTL_SET_MEDIA_STATUS
:
1959 if (l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
>=
1960 (sizeof (ULONG
) * 1))
1962 ULONG parm
= ((PULONG
) (p_IRP
->AssociatedIrp
.SystemBuffer
))[0];
1963 SetMediaStatus (l_Adapter
, (BOOLEAN
) parm
);
1964 p_IRP
->IoStatus
.Information
= 1;
1969 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
1974 case TAP_IOCTL_CONFIG_DHCP_MASQ
:
1976 if (l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
>=
1977 (sizeof (IPADDR
) * 4))
1979 l_Adapter
->m_dhcp_enabled
= FALSE
;
1980 l_Adapter
->m_dhcp_server_arp
= FALSE
;
1981 l_Adapter
->m_dhcp_user_supplied_options_buffer_len
= 0;
1983 // Adapter IP addr / netmask
1984 l_Adapter
->m_dhcp_addr
=
1985 ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[0];
1986 l_Adapter
->m_dhcp_netmask
=
1987 ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[1];
1989 // IP addr of DHCP masq server
1990 l_Adapter
->m_dhcp_server_ip
=
1991 ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[2];
1993 // Lease time in seconds
1994 l_Adapter
->m_dhcp_lease_time
=
1995 ((IPADDR
*) (p_IRP
->AssociatedIrp
.SystemBuffer
))[3];
1997 GenerateRelatedMAC (l_Adapter
->m_dhcp_server_mac
, l_Adapter
->m_MAC
, 2);
1999 l_Adapter
->m_dhcp_enabled
= TRUE
;
2000 l_Adapter
->m_dhcp_server_arp
= TRUE
;
2002 CheckIfDhcpAndTunMode (l_Adapter
);
2004 p_IRP
->IoStatus
.Information
= 1; // Simple boolean value
2009 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
2015 case TAP_IOCTL_CONFIG_DHCP_SET_OPT
:
2017 if (l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
<=
2018 DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE
2019 && l_Adapter
->m_dhcp_enabled
)
2021 l_Adapter
->m_dhcp_user_supplied_options_buffer_len
= 0;
2023 NdisMoveMemory (l_Adapter
->m_dhcp_user_supplied_options_buffer
,
2024 p_IRP
->AssociatedIrp
.SystemBuffer
,
2025 l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
2027 l_Adapter
->m_dhcp_user_supplied_options_buffer_len
=
2028 l_IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
2030 p_IRP
->IoStatus
.Information
= 1; // Simple boolean value
2035 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
2044 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
2049 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2053 //===========================================================
2054 // User mode thread issued a read request on the tap device
2055 // If there are packets waiting to be read, then the request
2056 // will be satisfied here. If not, then the request will be
2057 // queued and satisfied by any packet that is not used to
2058 // satisfy requests ahead of it.
2059 //===========================================================
2062 TapPacketPointer l_PacketBuffer
;
2063 BOOLEAN pending
= FALSE
;
2065 // Save IRP-accessible copy of buffer length
2066 p_IRP
->IoStatus
.Information
= l_IrpSp
->Parameters
.Read
.Length
;
2068 if (p_IRP
->MdlAddress
== NULL
)
2070 DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_READ\n",
2073 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
2074 p_IRP
->IoStatus
.Information
= 0;
2075 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2078 else if ((p_IRP
->AssociatedIrp
.SystemBuffer
=
2079 MmGetSystemAddressForMdlSafe
2080 (p_IRP
->MdlAddress
, NormalPagePriority
)) == NULL
)
2082 DEBUGP (("[%s] Could not map address in IRP_MJ_READ\n",
2085 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INSUFFICIENT_RESOURCES
;
2086 p_IRP
->IoStatus
.Information
= 0;
2087 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2090 else if (!l_Adapter
->m_InterfaceIsRunning
)
2092 DEBUGP (("[%s] Interface is down in IRP_MJ_READ\n",
2095 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2096 p_IRP
->IoStatus
.Information
= 0;
2097 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2101 //==================================
2102 // Can we provide immediate service?
2103 //==================================
2105 l_PacketBuffer
= NULL
;
2107 NdisAcquireSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
2109 if (IS_UP (l_Adapter
)
2110 && QueueCount (l_Adapter
->m_Extension
.m_PacketQueue
)
2111 && QueueCount (l_Adapter
->m_Extension
.m_IrpQueue
) == 0)
2113 l_PacketBuffer
= (TapPacketPointer
)
2114 QueuePop (l_Adapter
->m_Extension
.m_PacketQueue
);
2117 NdisReleaseSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
2121 l_Status
= CompleteIRP (p_IRP
,
2127 //=============================
2128 // Attempt to pend read request
2129 //=============================
2131 NdisAcquireSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
2133 if (IS_UP (l_Adapter
)
2134 && QueuePush (l_Adapter
->m_Extension
.m_IrpQueue
, p_IRP
) == (PIRP
) p_IRP
)
2136 IoSetCancelRoutine (p_IRP
, CancelIRPCallback
);
2137 l_Status
= STATUS_PENDING
;
2138 IoMarkIrpPending (p_IRP
);
2142 NdisReleaseSpinLock (&l_Adapter
->m_Extension
.m_QueueLock
);
2147 // Can't queue anymore IRP's
2148 DEBUGP (("[%s] TAP [%s] read IRP overrun\n",
2149 NAME (l_Adapter
), l_Adapter
->m_Extension
.m_TapName
));
2151 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2152 p_IRP
->IoStatus
.Information
= 0;
2153 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2157 //==============================================================
2158 // User mode issued a WriteFile request on the TAP file handle.
2159 // The request will always get satisfied here. The call may
2160 // fail if there are too many pending packets (queue full).
2161 //==============================================================
2164 if (p_IRP
->MdlAddress
== NULL
)
2166 DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n",
2169 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INVALID_PARAMETER
;
2170 p_IRP
->IoStatus
.Information
= 0;
2172 else if ((p_IRP
->AssociatedIrp
.SystemBuffer
=
2173 MmGetSystemAddressForMdlSafe
2174 (p_IRP
->MdlAddress
, NormalPagePriority
)) == NULL
)
2176 DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n",
2179 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_INSUFFICIENT_RESOURCES
;
2180 p_IRP
->IoStatus
.Information
= 0;
2182 else if (!l_Adapter
->m_InterfaceIsRunning
)
2184 DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n",
2187 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2188 p_IRP
->IoStatus
.Information
= 0;
2190 else if (!l_Adapter
->m_tun
&& ((l_IrpSp
->Parameters
.Write
.Length
) >= ETHERNET_HEADER_SIZE
))
2194 p_IRP
->IoStatus
.Information
= l_IrpSp
->Parameters
.Write
.Length
;
2196 DUMP_PACKET ("IRP_MJ_WRITE ETH",
2197 (unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
,
2198 l_IrpSp
->Parameters
.Write
.Length
);
2200 //=====================================================
2201 // If IPv4 packet, check whether or not packet
2203 //=====================================================
2204 #if PACKET_TRUNCATION_CHECK
2205 IPv4PacketSizeVerify ((unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
,
2206 l_IrpSp
->Parameters
.Write
.Length
,
2209 &l_Adapter
->m_RxTrunc
);
2212 NdisMEthIndicateReceive
2213 (l_Adapter
->m_MiniportAdapterHandle
,
2214 (NDIS_HANDLE
) l_Adapter
,
2215 (unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
,
2216 ETHERNET_HEADER_SIZE
,
2217 (unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
+ ETHERNET_HEADER_SIZE
,
2218 l_IrpSp
->Parameters
.Write
.Length
- ETHERNET_HEADER_SIZE
,
2219 l_IrpSp
->Parameters
.Write
.Length
- ETHERNET_HEADER_SIZE
);
2221 NdisMEthIndicateReceiveComplete (l_Adapter
->m_MiniportAdapterHandle
);
2223 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_SUCCESS
;
2225 __except (EXCEPTION_EXECUTE_HANDLER
)
2227 DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE\n",
2230 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2231 p_IRP
->IoStatus
.Information
= 0;
2234 else if (l_Adapter
->m_tun
&& ((l_IrpSp
->Parameters
.Write
.Length
) >= IP_HEADER_SIZE
))
2238 p_IRP
->IoStatus
.Information
= l_IrpSp
->Parameters
.Write
.Length
;
2240 DUMP_PACKET2 ("IRP_MJ_WRITE P2P",
2241 &l_Adapter
->m_UserToTap
,
2242 (unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
,
2243 l_IrpSp
->Parameters
.Write
.Length
);
2245 //=====================================================
2246 // If IPv4 packet, check whether or not packet
2248 //=====================================================
2249 #if PACKET_TRUNCATION_CHECK
2250 IPv4PacketSizeVerify ((unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
,
2251 l_IrpSp
->Parameters
.Write
.Length
,
2254 &l_Adapter
->m_RxTrunc
);
2257 NdisMEthIndicateReceive
2258 (l_Adapter
->m_MiniportAdapterHandle
,
2259 (NDIS_HANDLE
) l_Adapter
,
2260 (unsigned char *) &l_Adapter
->m_UserToTap
,
2261 sizeof (l_Adapter
->m_UserToTap
),
2262 (unsigned char *) p_IRP
->AssociatedIrp
.SystemBuffer
,
2263 l_IrpSp
->Parameters
.Write
.Length
,
2264 l_IrpSp
->Parameters
.Write
.Length
);
2266 NdisMEthIndicateReceiveComplete (l_Adapter
->m_MiniportAdapterHandle
);
2268 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_SUCCESS
;
2270 __except (EXCEPTION_EXECUTE_HANDLER
)
2272 DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE (P2P)\n",
2275 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2276 p_IRP
->IoStatus
.Information
= 0;
2281 DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n",
2283 l_IrpSp
->Parameters
.Write
.Length
));
2285 p_IRP
->IoStatus
.Information
= 0; // ETHERNET_HEADER_SIZE;
2286 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_BUFFER_TOO_SMALL
;
2289 if (l_Status
== STATUS_SUCCESS
)
2290 INCREMENT_STAT (l_Adapter
->m_Rx
);
2292 INCREMENT_STAT (l_Adapter
->m_RxErr
);
2294 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2298 //--------------------------------------------------------------
2299 // User mode thread has called CreateFile() on the tap device
2300 //--------------------------------------------------------------
2303 BOOLEAN succeeded
= FALSE
;
2304 BOOLEAN mutex_succeeded
;
2307 (("[%s] [TAP] release [%d.%d] open request (m_TapOpens=%d)\n",
2308 NAME (l_Adapter
), TAP_DRIVER_MAJOR_VERSION
,
2309 TAP_DRIVER_MINOR_VERSION
, l_Adapter
->m_Extension
.m_TapOpens
));
2311 ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter
->m_Extension
.m_OpenCloseMutex
, mutex_succeeded
);
2312 if (mutex_succeeded
)
2314 if (l_Adapter
->m_Extension
.m_TapIsRunning
&& !l_Adapter
->m_Extension
.m_TapOpens
)
2316 ResetTapAdapterState (l_Adapter
);
2317 l_Adapter
->m_Extension
.m_TapOpens
= 1;
2323 INCREMENT_STAT (l_Adapter
->m_Extension
.m_NumTapOpens
);
2324 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_SUCCESS
;
2325 p_IRP
->IoStatus
.Information
= 0;
2329 DEBUGP (("[%s] TAP is presently unavailable (m_TapOpens=%d)\n",
2330 NAME (l_Adapter
), l_Adapter
->m_Extension
.m_TapOpens
));
2332 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2333 p_IRP
->IoStatus
.Information
= 0;
2336 RELEASE_MUTEX (&l_Adapter
->m_Extension
.m_OpenCloseMutex
);
2340 DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
2341 NAME (l_Adapter
), l_Adapter
->m_Extension
.m_TapOpens
));
2343 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2344 p_IRP
->IoStatus
.Information
= 0;
2347 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2351 //-----------------------------------------------------------
2352 // User mode thread called CloseHandle() on the tap device
2353 //-----------------------------------------------------------
2356 BOOLEAN mutex_succeeded
;
2358 DEBUGP (("[%s] [TAP] release [%d.%d] close/cleanup request\n",
2359 NAME (l_Adapter
), TAP_DRIVER_MAJOR_VERSION
,
2360 TAP_DRIVER_MINOR_VERSION
));
2362 ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter
->m_Extension
.m_OpenCloseMutex
, mutex_succeeded
);
2363 if (mutex_succeeded
)
2365 l_Adapter
->m_Extension
.m_TapOpens
= 0;
2366 ResetTapAdapterState (l_Adapter
);
2367 FlushQueues (&l_Adapter
->m_Extension
);
2368 SetMediaStatus (l_Adapter
, FALSE
);
2369 RELEASE_MUTEX (&l_Adapter
->m_Extension
.m_OpenCloseMutex
);
2373 DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
2374 NAME (l_Adapter
), l_Adapter
->m_Extension
.m_TapOpens
));
2376 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2377 p_IRP
->IoStatus
.Information
= 0;
2380 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2384 //------------------
2386 //------------------
2390 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_UNSUCCESSFUL
;
2391 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2399 //=============================================================
2400 // CompleteIRP is normally called with an adapter -> userspace
2401 // network packet and an IRP (Pending I/O request) from userspace.
2403 // The IRP will normally represent a queued overlapped read
2404 // operation from userspace that is in a wait state.
2406 // Use the ethernet packet to satisfy the IRP.
2407 //=============================================================
2410 CompleteIRP (IN PIRP p_IRP
,
2411 IN TapPacketPointer p_PacketBuffer
,
2412 IN CCHAR PriorityBoost
)
2414 NTSTATUS l_Status
= STATUS_UNSUCCESSFUL
;
2420 MYASSERT (p_PacketBuffer
);
2422 IoSetCancelRoutine (p_IRP
, NULL
); // Disable cancel routine
2424 //-------------------------------------------
2425 // While p_PacketBuffer always contains a
2426 // full ethernet packet, including the
2427 // ethernet header, in point-to-point mode,
2428 // we only want to return the IPv4
2430 //-------------------------------------------
2432 if (p_PacketBuffer
->m_SizeFlags
& TP_TUN
)
2434 offset
= ETHERNET_HEADER_SIZE
;
2435 len
= (int) (p_PacketBuffer
->m_SizeFlags
& TP_SIZE_MASK
) - ETHERNET_HEADER_SIZE
;
2440 len
= (p_PacketBuffer
->m_SizeFlags
& TP_SIZE_MASK
);
2443 if (len
< 0 || (int) p_IRP
->IoStatus
.Information
< len
)
2445 p_IRP
->IoStatus
.Information
= 0;
2446 p_IRP
->IoStatus
.Status
= STATUS_BUFFER_OVERFLOW
;
2451 p_IRP
->IoStatus
.Information
= len
;
2452 p_IRP
->IoStatus
.Status
= l_Status
= STATUS_SUCCESS
;
2456 NdisMoveMemory (p_IRP
->AssociatedIrp
.SystemBuffer
,
2457 p_PacketBuffer
->m_Data
+ offset
,
2460 __except (EXCEPTION_EXECUTE_HANDLER
)
2463 p_IRP
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
2464 p_IRP
->IoStatus
.Information
= 0;
2470 NdisFreeMemory (p_PacketBuffer
,
2471 TAP_PACKET_SIZE (p_PacketBuffer
->m_SizeFlags
& TP_SIZE_MASK
),
2474 __except (EXCEPTION_EXECUTE_HANDLER
)
2478 if (l_Status
== STATUS_SUCCESS
)
2480 IoCompleteRequest (p_IRP
, PriorityBoost
);
2483 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2488 //==============================================
2489 // IRPs get cancelled for a number of reasons.
2491 // The TAP device could be closed by userspace
2492 // when there are still pending read operations.
2494 // The user could disable the TAP adapter in the
2495 // network connections control panel, while the
2496 // device is still open by a process.
2497 //==============================================
2499 CancelIRPCallback (IN PDEVICE_OBJECT p_DeviceObject
,
2502 TapAdapterPointer l_Adapter
= LookupAdapterInInstanceList (p_DeviceObject
);
2503 CancelIRP (l_Adapter
? &l_Adapter
->m_Extension
: NULL
, p_IRP
, TRUE
);
2507 CancelIRP (TapExtensionPointer p_Extension
,
2511 BOOLEAN exists
= FALSE
;
2517 NdisAcquireSpinLock (&p_Extension
->m_QueueLock
);
2518 exists
= (QueueExtract (p_Extension
->m_IrpQueue
, p_IRP
) == p_IRP
);
2519 NdisReleaseSpinLock (&p_Extension
->m_QueueLock
);
2526 IoSetCancelRoutine (p_IRP
, NULL
);
2527 p_IRP
->IoStatus
.Status
= STATUS_CANCELLED
;
2528 p_IRP
->IoStatus
.Information
= 0;
2532 IoReleaseCancelSpinLock (p_IRP
->CancelIrql
);
2535 IoCompleteRequest (p_IRP
, IO_NO_INCREMENT
);
2538 //===========================================
2539 // Exhaust packet, IRP, and injection queues.
2540 //===========================================
2542 FlushQueues (TapExtensionPointer p_Extension
)
2545 TapPacketPointer l_PacketBuffer
;
2546 InjectPacketPointer l_InjectBuffer
;
2547 int n_IRP
=0, n_Packet
=0, n_Inject
=0;
2549 MYASSERT (p_Extension
);
2550 MYASSERT (p_Extension
->m_TapDevice
);
2554 NdisAcquireSpinLock (&p_Extension
->m_QueueLock
);
2555 l_IRP
= QueuePop (p_Extension
->m_IrpQueue
);
2556 NdisReleaseSpinLock (&p_Extension
->m_QueueLock
);
2560 CancelIRP (NULL
, l_IRP
, FALSE
);
2568 NdisAcquireSpinLock (&p_Extension
->m_QueueLock
);
2569 l_PacketBuffer
= QueuePop (p_Extension
->m_PacketQueue
);
2570 NdisReleaseSpinLock (&p_Extension
->m_QueueLock
);
2574 MemFree (l_PacketBuffer
, TAP_PACKET_SIZE (l_PacketBuffer
->m_SizeFlags
& TP_SIZE_MASK
));
2582 NdisAcquireSpinLock (&p_Extension
->m_InjectLock
);
2583 l_InjectBuffer
= QueuePop (p_Extension
->m_InjectQueue
);
2584 NdisReleaseSpinLock (&p_Extension
->m_InjectLock
);
2588 INJECT_PACKET_FREE(l_InjectBuffer
);
2595 "[%s] [TAP] FlushQueues n_IRP=[%d,%d,%d] n_Packet=[%d,%d,%d] n_Inject=[%d,%d,%d]\n",
2596 p_Extension
->m_TapName
,
2598 p_Extension
->m_IrpQueue
->max_size
,
2601 p_Extension
->m_PacketQueue
->max_size
,
2604 p_Extension
->m_InjectQueue
->max_size
,
2609 //===================================================
2610 // Tell Windows whether the TAP device should be
2611 // considered "connected" or "disconnected".
2612 //===================================================
2614 SetMediaStatus (TapAdapterPointer p_Adapter
, BOOLEAN state
)
2616 if (p_Adapter
->m_MediaState
!= state
&& !p_Adapter
->m_MediaStateAlwaysConnected
)
2619 NdisMIndicateStatus (p_Adapter
->m_MiniportAdapterHandle
,
2620 NDIS_STATUS_MEDIA_CONNECT
, NULL
, 0);
2622 NdisMIndicateStatus (p_Adapter
->m_MiniportAdapterHandle
,
2623 NDIS_STATUS_MEDIA_DISCONNECT
, NULL
, 0);
2625 NdisMIndicateStatusComplete (p_Adapter
->m_MiniportAdapterHandle
);
2626 p_Adapter
->m_MediaState
= state
;
2631 //======================================================
2632 // If DHCP mode is used together with tun
2633 // mode, consider the fact that the P2P remote subnet
2634 // might enclose the DHCP masq server address.
2635 //======================================================
2637 CheckIfDhcpAndTunMode (TapAdapterPointer p_Adapter
)
2639 if (p_Adapter
->m_tun
&& p_Adapter
->m_dhcp_enabled
)
2641 if ((p_Adapter
->m_dhcp_server_ip
& p_Adapter
->m_remoteNetmask
) == p_Adapter
->m_remoteNetwork
)
2643 COPY_MAC (p_Adapter
->m_dhcp_server_mac
, p_Adapter
->m_TapToUser
.dest
);
2644 p_Adapter
->m_dhcp_server_arp
= FALSE
;
2649 //===================================================
2650 // Generate an ARP reply message for specific kinds
2652 //===================================================
2654 ProcessARP (TapAdapterPointer p_Adapter
,
2655 const PARP_PACKET src
,
2656 const IPADDR adapter_ip
,
2657 const IPADDR ip_network
,
2658 const IPADDR ip_netmask
,
2661 //-----------------------------------------------
2662 // Is this the kind of packet we are looking for?
2663 //-----------------------------------------------
2664 if (src
->m_Proto
== htons (ETH_P_ARP
)
2665 && MAC_EQUAL (src
->m_MAC_Source
, p_Adapter
->m_MAC
)
2666 && MAC_EQUAL (src
->m_ARP_MAC_Source
, p_Adapter
->m_MAC
)
2667 && MAC_EQUAL (src
->m_MAC_Destination
, p_Adapter
->m_MAC_Broadcast
)
2668 && src
->m_ARP_Operation
== htons (ARP_REQUEST
)
2669 && src
->m_MAC_AddressType
== htons (MAC_ADDR_TYPE
)
2670 && src
->m_MAC_AddressSize
== sizeof (MACADDR
)
2671 && src
->m_PROTO_AddressType
== htons (ETH_P_IP
)
2672 && src
->m_PROTO_AddressSize
== sizeof (IPADDR
)
2673 && src
->m_ARP_IP_Source
== adapter_ip
2674 && (src
->m_ARP_IP_Destination
& ip_netmask
) == ip_network
2675 && src
->m_ARP_IP_Destination
!= adapter_ip
)
2677 ARP_PACKET
*arp
= (ARP_PACKET
*) MemAlloc (sizeof (ARP_PACKET
), TRUE
);
2680 //----------------------------------------------
2681 // Initialize ARP reply fields
2682 //----------------------------------------------
2683 arp
->m_Proto
= htons (ETH_P_ARP
);
2684 arp
->m_MAC_AddressType
= htons (MAC_ADDR_TYPE
);
2685 arp
->m_PROTO_AddressType
= htons (ETH_P_IP
);
2686 arp
->m_MAC_AddressSize
= sizeof (MACADDR
);
2687 arp
->m_PROTO_AddressSize
= sizeof (IPADDR
);
2688 arp
->m_ARP_Operation
= htons (ARP_REPLY
);
2690 //----------------------------------------------
2692 //----------------------------------------------
2693 COPY_MAC (arp
->m_MAC_Source
, mac
);
2694 COPY_MAC (arp
->m_MAC_Destination
, p_Adapter
->m_MAC
);
2695 COPY_MAC (arp
->m_ARP_MAC_Source
, mac
);
2696 COPY_MAC (arp
->m_ARP_MAC_Destination
, p_Adapter
->m_MAC
);
2697 arp
->m_ARP_IP_Source
= src
->m_ARP_IP_Destination
;
2698 arp
->m_ARP_IP_Destination
= adapter_ip
;
2700 DUMP_PACKET ("ProcessARP",
2701 (unsigned char *) arp
,
2702 sizeof (ARP_PACKET
));
2704 InjectPacketDeferred (p_Adapter
, (UCHAR
*) arp
, sizeof (ARP_PACKET
));
2706 MemFree (arp
, sizeof (ARP_PACKET
));
2715 //===============================================================
2716 // Used in cases where internally generated packets such as
2717 // ARP or DHCP replies must be returned to the kernel, to be
2718 // seen as an incoming packet "arriving" on the interface.
2719 //===============================================================
2721 // Defer packet injection till IRQL < DISPATCH_LEVEL
2723 InjectPacketDeferred (TapAdapterPointer p_Adapter
,
2725 const unsigned int len
)
2727 InjectPacketPointer l_InjectBuffer
;
2730 if (NdisAllocateMemoryWithTag (&l_InjectBuffer
,
2731 INJECT_PACKET_SIZE (len
),
2732 'IPAT') == NDIS_STATUS_SUCCESS
)
2734 l_InjectBuffer
->m_Size
= len
;
2735 NdisMoveMemory (l_InjectBuffer
->m_Data
, packet
, len
);
2736 NdisAcquireSpinLock (&p_Adapter
->m_Extension
.m_InjectLock
);
2737 result
= QueuePush (p_Adapter
->m_Extension
.m_InjectQueue
, l_InjectBuffer
);
2738 NdisReleaseSpinLock (&p_Adapter
->m_Extension
.m_InjectLock
);
2740 KeInsertQueueDpc (&p_Adapter
->m_Extension
.m_InjectDpc
, p_Adapter
, NULL
);
2742 INJECT_PACKET_FREE(l_InjectBuffer
);
2746 // Handle the injection of previously deferred packets
2748 InjectPacketDpc(KDPC
*Dpc
,
2749 PVOID DeferredContext
,
2750 PVOID SystemArgument1
,
2751 PVOID SystemArgument2
)
2753 InjectPacketPointer l_InjectBuffer
;
2754 TapAdapterPointer l_Adapter
= (TapAdapterPointer
)SystemArgument1
;
2757 NdisAcquireSpinLock (&l_Adapter
->m_Extension
.m_InjectLock
);
2758 l_InjectBuffer
= QueuePop (l_Adapter
->m_Extension
.m_InjectQueue
);
2759 NdisReleaseSpinLock (&l_Adapter
->m_Extension
.m_InjectLock
);
2762 InjectPacketNow(l_Adapter
, l_InjectBuffer
->m_Data
, l_InjectBuffer
->m_Size
);
2763 INJECT_PACKET_FREE(l_InjectBuffer
);
2770 // Do packet injection now
2772 InjectPacketNow (TapAdapterPointer p_Adapter
,
2774 const unsigned int len
)
2776 MYASSERT (len
>= ETHERNET_HEADER_SIZE
);
2780 //------------------------------------------------------------
2781 // NdisMEthIndicateReceive and NdisMEthIndicateReceiveComplete
2782 // could potentially be called reentrantly both here and in
2783 // TapDeviceHook/IRP_MJ_WRITE.
2785 // The DDK docs imply that this is okay.
2787 // Note that reentrant behavior could only occur if the
2788 // non-deferred version of InjectPacket is used.
2789 //------------------------------------------------------------
2790 NdisMEthIndicateReceive
2791 (p_Adapter
->m_MiniportAdapterHandle
,
2792 (NDIS_HANDLE
) p_Adapter
,
2794 ETHERNET_HEADER_SIZE
,
2795 packet
+ ETHERNET_HEADER_SIZE
,
2796 len
- ETHERNET_HEADER_SIZE
,
2797 len
- ETHERNET_HEADER_SIZE
);
2799 NdisMEthIndicateReceiveComplete (p_Adapter
->m_MiniportAdapterHandle
);
2801 __except (EXCEPTION_EXECUTE_HANDLER
)
2803 DEBUGP (("[%s] NdisMEthIndicateReceive failed in InjectPacketNow\n",
2809 //===================================================================
2810 // Go back to default TAP mode from Point-To-Point mode.
2811 // Also reset (i.e. disable) DHCP Masq mode.
2812 //===================================================================
2813 VOID
ResetTapAdapterState (TapAdapterPointer p_Adapter
)
2816 p_Adapter
->m_tun
= FALSE
;
2817 p_Adapter
->m_localIP
= 0;
2818 p_Adapter
->m_remoteNetwork
= 0;
2819 p_Adapter
->m_remoteNetmask
= 0;
2820 NdisZeroMemory (&p_Adapter
->m_TapToUser
, sizeof (p_Adapter
->m_TapToUser
));
2821 NdisZeroMemory (&p_Adapter
->m_UserToTap
, sizeof (p_Adapter
->m_UserToTap
));
2824 p_Adapter
->m_dhcp_enabled
= FALSE
;
2825 p_Adapter
->m_dhcp_server_arp
= FALSE
;
2826 p_Adapter
->m_dhcp_user_supplied_options_buffer_len
= 0;
2827 p_Adapter
->m_dhcp_addr
= 0;
2828 p_Adapter
->m_dhcp_netmask
= 0;
2829 p_Adapter
->m_dhcp_server_ip
= 0;
2830 p_Adapter
->m_dhcp_lease_time
= 0;
2831 p_Adapter
->m_dhcp_received_discover
= FALSE
;
2832 p_Adapter
->m_dhcp_bad_requests
= 0;
2833 NdisZeroMemory (p_Adapter
->m_dhcp_server_mac
, sizeof (MACADDR
));
2838 //===================================================================
2839 // Set TAP device handle to be accessible without admin privileges.
2840 //===================================================================
2841 VOID
AllowNonAdmin (TapExtensionPointer p_Extension
)
2844 SECURITY_DESCRIPTOR sd
;
2845 OBJECT_ATTRIBUTES oa
;
2846 IO_STATUS_BLOCK isb
;
2849 NdisZeroMemory (&sd
, sizeof (sd
));
2850 NdisZeroMemory (&oa
, sizeof (oa
));
2851 NdisZeroMemory (&isb
, sizeof (isb
));
2853 if (!p_Extension
->m_CreatedUnicodeLinkName
)
2855 DEBUGP (("[TAP] AllowNonAdmin: UnicodeLinkName is uninitialized\n"));
2860 stat
= RtlCreateSecurityDescriptor (&sd
, SECURITY_DESCRIPTOR_REVISION
);
2861 if (stat
!= STATUS_SUCCESS
)
2863 DEBUGP (("[TAP] AllowNonAdmin: RtlCreateSecurityDescriptor failed\n"));
2868 InitializeObjectAttributes (
2870 &p_Extension
->m_UnicodeLinkName
,
2884 if (stat
!= STATUS_SUCCESS
)
2886 DEBUGP (("[TAP] AllowNonAdmin: ZwOpenFile failed, status=0x%08x\n", (unsigned int)stat
));
2891 stat
= ZwSetSecurityObject (hand
, DACL_SECURITY_INFORMATION
, &sd
);
2892 if (stat
!= STATUS_SUCCESS
)
2894 DEBUGP (("[TAP] AllowNonAdmin: ZwSetSecurityObject failed\n"));
2899 stat
= ZwClose (hand
);
2900 if (stat
!= STATUS_SUCCESS
)
2902 DEBUGP (("[TAP] AllowNonAdmin: ZwClose failed\n"));
2907 DEBUGP (("[TAP] AllowNonAdmin: SUCCEEDED\n"));
2912 #if PACKET_TRUNCATION_CHECK
2915 IPv4PacketSizeVerify (const UCHAR
*data
, ULONG length
, BOOLEAN tun
, const char *prefix
, LONG
*counter
)
2922 ip
= (IPHDR
*) data
;
2926 if (length
>= sizeof (ETH_HEADER
))
2928 const ETH_HEADER
*eth
= (ETH_HEADER
*) data
;
2930 if (eth
->proto
!= htons (ETH_P_IP
))
2933 ip
= (IPHDR
*) (data
+ sizeof (ETH_HEADER
));
2934 len
-= sizeof (ETH_HEADER
);
2940 if (len
>= sizeof (IPHDR
))
2942 const int totlen
= ntohs (ip
->tot_len
);
2944 DEBUGP (("[TAP] IPv4PacketSizeVerify %s len=%d totlen=%d\n", prefix
, len
, totlen
));
2953 //======================================================================
2955 //======================================================================