Upgrade to OpenVPN 2.1.0
[tomato.git] / release / src / router / openvpn / tap-win32 / tapdrvr.c
blob2c6af4853360fa7434e85b696a2c9f5f8fb585d8
1 /*
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"
39 #ifndef DDKVER_MAJOR
40 #error DDKVER_MAJOR must be defined as the major number of the DDK Version
41 #endif
43 #define NDIS_MINIPORT_DRIVER
44 #define BINARY_COMPATIBLE 0
45 #define NDIS50_MINIPORT 1
46 #define NDIS_WDM 0
47 #define NDIS50 1
48 #define NTSTRSAFE_LIB
50 // Debug info output
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
70 #include <ndis.h>
71 #include <ntstrsafe.h>
72 #include <ntddk.h>
73 #else
74 #include <ntifs.h>
75 #include <ndis.h>
76 #include <ntstrsafe.h>
77 #endif
79 #include "lock.h"
80 #include "constants.h"
81 #include "common.h"
82 #include "proto.h"
83 #include "error.h"
84 #include "endian.h"
85 #include "dhcp.h"
86 #include "types.h"
87 #include "prototypes.h"
89 #include "mem.c"
90 #include "macinfo.c"
91 #include "error.c"
92 #include "dhcp.c"
93 #include "instance.c"
95 #define IS_UP(ta) \
96 ((ta)->m_InterfaceIsRunning && (ta)->m_Extension.m_TapIsRunning)
98 #define INCREMENT_STAT(s) ++(s)
100 #define NAME_BUFFER_SIZE 80
102 //========================================================
103 // Globals
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,
113 OID_GEN_MAC_OPTIONS,
114 OID_GEN_LINK_SPEED,
115 OID_GEN_TRANSMIT_BLOCK_SIZE,
116 OID_GEN_RECEIVE_BLOCK_SIZE,
117 OID_GEN_VENDOR_DESCRIPTION,
118 OID_GEN_DRIVER_VERSION,
119 OID_GEN_XMIT_OK,
120 OID_GEN_RCV_OK,
121 OID_GEN_XMIT_ERROR,
122 OID_GEN_RCV_ERROR,
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,
131 OID_GEN_VENDOR_ID,
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 //============================================================
146 // Driver Entry
147 //============================================================
148 #pragma NDIS_INIT_FUNCTION (DriverEntry)
150 NTSTATUS
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,
162 p_DriverObject,
163 p_RegistryPath, NULL);
165 //======================
166 // Global initialization
167 //======================
169 #if DBG
170 MyDebugInit (10000); // Allocate debugging text space
171 #endif
173 if (!InitInstanceList ())
175 DEBUGP (("[TAP] Allocation failed for adapter instance list\n"));
176 goto cleanup;
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"));
188 goto cleanup;
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 */
201 switch (l_Status =
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,
210 __DATE__,
211 __TIME__));
212 DEBUGP (("Registry Path: '%S'\n", p_RegistryPath->Buffer));
213 break;
216 case NDIS_STATUS_BAD_CHARACTERISTICS:
218 DEBUGP (("[TAP] Miniport characteristics were badly defined\n"));
219 NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
220 break;
223 case NDIS_STATUS_BAD_VERSION:
225 DEBUGP
226 (("[TAP] NDIS Version is wrong for the given characteristics\n"));
227 NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
228 break;
231 case NDIS_STATUS_RESOURCES:
233 DEBUGP (("[TAP] Insufficient resources\n"));
234 NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
235 break;
238 default:
239 case NDIS_STATUS_FAILURE:
241 DEBUGP (("[TAP] Unknown fatal registration error\n"));
242 NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
243 break;
247 cleanup:
248 if (l_Properties)
249 MemFree (l_Properties, sizeof (NDIS_MINIPORT_CHARACTERISTICS));
251 if (l_Status == NDIS_STATUS_SUCCESS)
252 NdisMRegisterUnloadHandler (g_NdisWrapperHandle, TapDriverUnload);
253 else
254 TapDriverUnload (p_DriverObject);
256 return l_Status;
259 //============================================================
260 // Driver Unload
261 //============================================================
262 VOID
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,
268 __DATE__,
269 __TIME__,
270 NInstances(),
271 InstanceMaxBucketSize()));
273 FreeInstanceList ();
275 //==============================
276 // Free debugging text space
277 //==============================
278 #if DBG
279 MyDebugFree ();
280 #endif
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;
298 UINT l_Index;
299 NDIS_STATUS status;
301 #if ENABLE_NONADMIN
302 BOOLEAN enable_non_admin = FALSE;
303 #endif
305 DEBUGP (("[TAP] AdapterCreate called\n"));
307 //====================================
308 // Make sure adapter type is supported
309 //====================================
311 for (l_Index = 0;
312 l_Index < p_MediaCount && p_Media[l_Index] != l_PreferredMedium;
313 ++l_Index);
315 if (l_Index == p_MediaCount)
317 DEBUGP (("[TAP] Unsupported adapter type [wanted: %d]\n",
318 l_PreferredMedium));
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 //==========================================
341 NdisMSetAttributesEx
342 (p_AdapterHandle,
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,
373 AdapterHalt);
374 l_Adapter->m_RegisteredAdapterShutdownHandler = TRUE;
376 //============================================
377 // Get parameters from registry which were set
378 // in the adapter advanced properties dialog.
379 //============================================
381 NDIS_STATUS status;
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);
395 return status;
398 //====================================
399 // Allocate and construct adapter name
400 //====================================
403 NDIS_STRING mkey = NDIS_STRING_CONST("MiniportName");
404 NDIS_STRING vkey = NDIS_STRING_CONST("NdisVersion");
405 NDIS_STATUS vstatus;
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;
429 else
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;
443 else
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)
472 mtu = MINIMUM_MTU;
473 if (mtu > MAXIMUM_MTU)
474 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;
498 #if ENABLE_NONADMIN
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;
515 #endif
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",
549 NAME (l_Adapter),
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]));
553 //==================
554 // Set broadcast MAC
555 //==================
557 int i;
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"));
572 return tap_status;
576 if (!AddAdapterToInstanceList (l_Adapter))
578 NOTE_ERROR ();
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;
587 #if ENABLE_NONADMIN
588 if (enable_non_admin)
589 AllowNonAdmin (&l_Adapter->m_Extension);
590 #endif
592 return NDIS_STATUS_SUCCESS;
595 VOID
596 AdapterHalt (IN NDIS_HANDLE p_AdapterContext)
598 BOOLEAN status;
600 TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
602 NOTE_ERROR ();
604 l_Adapter->m_InterfaceIsRunning = FALSE;
606 DEBUGP (("[%s] is being halted\n", NAME (l_Adapter)));
608 DestroyTapDevice (&l_Adapter->m_Extension);
610 // Free resources
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,
620 __DATE__,
621 __TIME__));
624 VOID
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);
640 VOID
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
658 // NdisMSleep.
659 //=====================================
660 NdisMSleep (500000);
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);
680 VOID
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)
709 BOOLEAN status;
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 //========================================================================
732 NDIS_STATUS
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,
746 p_Name));
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;
765 goto cleanup;
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;
784 goto cleanup;
786 ++l_UsableName;
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;
798 goto cleanup;
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",
809 p_Name));
810 l_Return = NDIS_STATUS_RESOURCES;
811 goto cleanup;
814 //=======================================================
815 // Set TAP device name
816 //=======================================================
818 l_Status = RtlStringCchPrintfExA
819 (l_TapString.Buffer,
820 l_TapString.MaximumLength,
821 NULL,
822 NULL,
823 STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,
824 "%s%s%s",
825 SYSDEVICEDIR,
826 l_UsableName,
827 TAPSUFFIX);
829 if (l_Status != STATUS_SUCCESS)
831 DEBUGP (("[%s] couldn't format TAP device name\n",
832 p_Name));
833 l_Return = NDIS_STATUS_RESOURCES;
834 goto cleanup;
836 l_TapString.Length = (USHORT) strlen (l_TapString.Buffer);
838 DEBUGP (("TAP DEV NAME: '%s'\n", l_TapString.Buffer));
840 //=======================================================
841 // Set TAP link name
842 //=======================================================
844 l_Status = RtlStringCchPrintfExA
845 (l_LinkString.Buffer,
846 l_LinkString.MaximumLength,
847 NULL,
848 NULL,
849 STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,
850 "%s%s%s",
851 USERDEVICEDIR,
852 l_UsableName,
853 TAPSUFFIX);
855 if (l_Status != STATUS_SUCCESS)
857 DEBUGP (("[%s] couldn't format TAP device symbolic link\n",
858 p_Name));
859 l_Return = NDIS_STATUS_RESOURCES;
860 goto cleanup;
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) !=
870 STATUS_SUCCESS)
872 DEBUGP (("[%s] couldn't alloc TAP unicode name buffer\n",
873 p_Name));
874 l_Return = NDIS_STATUS_RESOURCES;
875 goto cleanup;
877 l_FreeTapUnicode = TRUE;
879 if (RtlAnsiStringToUnicodeString
880 (&p_Extension->m_UnicodeLinkName, &l_LinkString, TRUE)
881 != STATUS_SUCCESS)
883 DEBUGP
884 (("[%s] Couldn't allocate unicode string for symbolic link name\n",
885 p_Name));
886 l_Return = NDIS_STATUS_RESOURCES;
887 goto cleanup;
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,
898 &l_TapUnicode,
899 &p_Extension->m_UnicodeLinkName,
900 l_Dispatch,
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;
909 goto cleanup;
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
925 // the virtual NIC.
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;
951 goto cleanup;
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));
970 cleanup:
971 if (l_FreeTapUnicode)
972 RtlFreeUnicodeString (&l_TapUnicode);
973 if (l_LinkString.Buffer)
974 MemFree (l_LinkString.Buffer, NAME_BUFFER_SIZE);
975 if (l_Dispatch)
976 MemFree (l_Dispatch, SIZEOF_DISPATCH);
978 if (l_Return != NDIS_STATUS_SUCCESS)
979 TapDeviceFreeResources (p_Extension);
981 return l_Return;
983 #undef SIZEOF_DISPATCH
985 //========================================================
986 // Adapter Control
987 //========================================================
988 NDIS_STATUS
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,
1001 IN UINT p_Offset,
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,
1012 IN NDIS_OID p_OID,
1013 IN PVOID p_Buffer,
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));
1025 switch (p_OID)
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;
1033 break;
1035 case OID_GEN_VENDOR_ID:
1036 l_Query.m_Long = 0xffffff;
1037 break;
1039 case OID_GEN_DRIVER_VERSION:
1040 l_Query.m_Short =
1041 (((USHORT) TAP_NDIS_MAJOR_VERSION) << 8 | (USHORT)
1042 TAP_NDIS_MINOR_VERSION);
1043 l_QueryLength = sizeof (unsigned short);
1044 break;
1046 case OID_GEN_VENDOR_DRIVER_VERSION:
1047 l_Query.m_Long =
1048 (((USHORT) TAP_DRIVER_MAJOR_VERSION) << 8 | (USHORT)
1049 TAP_DRIVER_MINOR_VERSION);
1050 break;
1052 //=================================================================
1053 // Statistics
1054 //=================================================================
1055 case OID_GEN_RCV_NO_BUFFER:
1056 l_Query.m_Long = 0;
1057 break;
1059 case OID_802_3_RCV_ERROR_ALIGNMENT:
1060 l_Query.m_Long = 0;
1061 break;
1063 case OID_802_3_XMIT_ONE_COLLISION:
1064 l_Query.m_Long = 0;
1065 break;
1067 case OID_802_3_XMIT_MORE_COLLISIONS:
1068 l_Query.m_Long = 0;
1069 break;
1071 case OID_GEN_XMIT_OK:
1072 l_Query.m_Long = l_Adapter->m_Tx;
1073 break;
1075 case OID_GEN_RCV_OK:
1076 l_Query.m_Long = l_Adapter->m_Rx;
1077 break;
1079 case OID_GEN_XMIT_ERROR:
1080 l_Query.m_Long = l_Adapter->m_TxErr;
1081 break;
1083 case OID_GEN_RCV_ERROR:
1084 l_Query.m_Long = l_Adapter->m_RxErr;
1085 break;
1087 //===================================================================
1088 // Device & Protocol Options
1089 //===================================================================
1090 case OID_GEN_SUPPORTED_LIST:
1091 l_QueryPtr = (TapAdapterQueryPointer) g_SupportedOIDList;
1092 l_QueryLength = sizeof (g_SupportedOIDList);
1093 break;
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);
1102 break;
1104 case OID_GEN_CURRENT_PACKET_FILTER:
1105 l_Query.m_Long =
1106 (NDIS_PACKET_TYPE_ALL_LOCAL |
1107 NDIS_PACKET_TYPE_BROADCAST |
1108 NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_FUNCTIONAL);
1110 break;
1112 case OID_GEN_PROTOCOL_OPTIONS:
1113 l_Query.m_Long = 0;
1114 break;
1116 //==================================================================
1117 // Device Info
1118 //==================================================================
1119 case OID_GEN_MEDIA_CONNECT_STATUS:
1120 l_Query.m_Long = l_Adapter->m_MediaState
1121 ? NdisMediaStateConnected : NdisMediaStateDisconnected;
1122 break;
1124 case OID_GEN_HARDWARE_STATUS:
1125 l_Query.m_HardwareStatus = NdisHardwareStatusReady;
1126 l_QueryLength = sizeof (NDIS_HARDWARE_STATUS);
1127 break;
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);
1133 break;
1135 case OID_GEN_PHYSICAL_MEDIUM:
1136 l_Query.m_PhysicalMedium = NdisPhysicalMediumUnspecified;
1137 l_QueryLength = sizeof (NDIS_PHYSICAL_MEDIUM);
1138 break;
1140 case OID_GEN_LINK_SPEED:
1141 l_Query.m_Long = 100000; // rate / 100 bps
1142 break;
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);
1148 break;
1150 //==================================================================
1151 // Limits
1152 //==================================================================
1154 case OID_GEN_MAXIMUM_SEND_PACKETS:
1155 l_Query.m_Long = 1;
1156 break;
1158 case OID_802_3_MAXIMUM_LIST_SIZE:
1159 l_Query.m_Long = NIC_MAX_MCAST_LIST;
1160 break;
1162 case OID_GEN_CURRENT_LOOKAHEAD:
1163 l_Query.m_Long = l_Adapter->m_Lookahead;
1164 break;
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;
1171 break;
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;
1177 break;
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);
1200 while (FALSE);
1201 break;
1202 case OID_PNP_QUERY_POWER:
1203 break;
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;
1212 break;
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;
1229 break;
1231 //===================================================================
1232 // Not Handled
1233 //===================================================================
1234 default:
1235 DEBUGP (("[%s] Unhandled OID %lx\n", NAME (l_Adapter), p_OID));
1236 l_Status = NDIS_STATUS_INVALID_OID;
1237 break;
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;
1247 else
1248 NdisMoveMemory (p_Buffer, (PVOID) l_QueryPtr,
1249 (*p_BytesWritten = l_QueryLength));
1251 return l_Status;
1254 NDIS_STATUS AdapterModify
1255 (IN NDIS_HANDLE p_AdapterContext,
1256 IN NDIS_OID p_OID,
1257 IN PVOID p_Buffer,
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;
1265 ULONG l_Long;
1267 switch (p_OID)
1269 //==================================================================
1270 // Device Info
1271 //==================================================================
1272 case OID_802_3_MULTICAST_LIST:
1273 DEBUGP (("[%s] Setting [OID_802_3_MULTICAST_LIST]\n",
1274 NAME (l_Adapter)));
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);
1286 else
1288 NdisAcquireSpinLock (&l_Adapter->m_MCLock);
1290 NdisZeroMemory(&l_Adapter->m_MCList, sizeof (MC_LIST));
1292 NdisMoveMemory(&l_Adapter->m_MCList,
1293 p_Buffer,
1294 p_BufferLength);
1296 l_Adapter->m_MCListSize = p_BufferLength / sizeof (ETH_ADDR);
1298 NdisReleaseSpinLock (&l_Adapter->m_MCLock);
1300 l_Status = NDIS_STATUS_SUCCESS;
1302 break;
1304 case OID_GEN_CURRENT_PACKET_FILTER:
1305 l_Status = NDIS_STATUS_INVALID_LENGTH;
1306 *p_BytesNeeded = 4;
1308 if (p_BufferLength >= sizeof (ULONG))
1310 DEBUGP
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);
1316 break;
1318 case OID_GEN_CURRENT_LOOKAHEAD:
1319 if (p_BufferLength < sizeof (ULONG))
1321 l_Status = NDIS_STATUS_INVALID_LENGTH;
1322 *p_BytesNeeded = 4;
1324 else if (l_Query->m_Long > DEFAULT_PACKET_LOOKAHEAD
1325 || l_Query->m_Long <= 0)
1327 l_Status = NDIS_STATUS_INVALID_DATA;
1329 else
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);
1337 break;
1339 case OID_GEN_NETWORK_LAYER_ADDRESSES:
1340 l_Status = NDIS_STATUS_SUCCESS;
1341 *p_BytesRead = *p_BytesNeeded = 0;
1342 break;
1344 case OID_GEN_TRANSPORT_HEADER_OFFSET:
1345 l_Status = NDIS_STATUS_SUCCESS;
1346 *p_BytesRead = *p_BytesNeeded = 0;
1347 break;
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';
1360 break;
1361 case NdisDeviceStateD1:
1362 l_Adapter->m_DeviceState = '1';
1363 break;
1364 case NdisDeviceStateD2:
1365 l_Adapter->m_DeviceState = '2';
1366 break;
1367 case NdisDeviceStateD3:
1368 l_Adapter->m_DeviceState = '3';
1369 break;
1370 default:
1371 l_Adapter->m_DeviceState = '?';
1372 break;
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;
1383 break;
1386 if (NewDeviceState > NdisDeviceStateD0)
1388 l_Adapter->m_InterfaceIsRunning = FALSE;
1389 DEBUGP (("[%s] Power management device state OFF\n",
1390 NAME (l_Adapter)));
1392 else
1394 l_Adapter->m_InterfaceIsRunning = TRUE;
1395 DEBUGP (("[%s] Power management device state ON\n",
1396 NAME (l_Adapter)));
1399 l_Status = NDIS_STATUS_SUCCESS;
1401 while (FALSE);
1403 if (l_Status == NDIS_STATUS_SUCCESS)
1405 *p_BytesRead = sizeof (NDIS_DEVICE_POWER_STATE);
1406 *p_BytesNeeded = 0;
1408 else
1410 *p_BytesRead = 0;
1411 *p_BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE);
1413 break;
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;
1419 break;
1421 default:
1422 DEBUGP (("[%s] Can't set value for OID %lx\n", NAME (l_Adapter),
1423 p_OID));
1424 l_Status = NDIS_STATUS_INVALID_OID;
1425 *p_BytesRead = *p_BytesNeeded = 0;
1426 break;
1429 return l_Status;
1432 //====================================================================
1433 // Adapter Transmission
1434 //====================================================================
1435 NDIS_STATUS
1436 AdapterTransmit (IN NDIS_HANDLE p_AdapterContext,
1437 IN PNDIS_PACKET p_Packet,
1438 IN UINT p_Flags)
1440 TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
1441 ULONG l_Index = 0, l_PacketLength = 0;
1442 UINT l_BufferLength = 0;
1443 PIRP l_IRP;
1444 TapPacketPointer l_PacketBuffer;
1445 PNDIS_BUFFER l_NDIS_Buffer;
1446 PUCHAR l_Buffer;
1447 PVOID result;
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)
1459 goto exit_fail;
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 //===========================
1477 __try
1479 l_Index = 0;
1480 while (l_NDIS_Buffer && l_Index < l_PacketLength)
1482 ULONG newlen;
1483 NdisQueryBuffer (l_NDIS_Buffer, (PVOID *) & l_Buffer,
1484 &l_BufferLength);
1485 newlen = l_Index + l_BufferLength;
1486 if (newlen > l_PacketLength)
1488 NOTE_ERROR ();
1489 goto no_queue; /* overflow */
1491 NdisMoveMemory (l_PacketBuffer->m_Data + l_Index, l_Buffer,
1492 l_BufferLength);
1493 l_Index = newlen;
1494 NdisGetNextBuffer (l_NDIS_Buffer, &l_NDIS_Buffer);
1496 if (l_Index != l_PacketLength)
1498 NOTE_ERROR ();
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
1506 // was truncated.
1507 //=====================================================
1508 #if PACKET_TRUNCATION_CHECK
1509 IPv4PacketSizeVerify (l_PacketBuffer->m_Data, l_PacketLength, FALSE, "TX", &l_Adapter->m_TxTrunc);
1510 #endif
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));
1524 // ARP packet?
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))
1535 goto no_queue;
1538 // DHCP packet?
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)
1547 + sizeof (IPHDR)
1548 + sizeof (UDPHDR));
1550 const int optlen = l_PacketLength
1551 - sizeof (ETH_HEADER)
1552 - sizeof (IPHDR)
1553 - sizeof (UDPHDR)
1554 - sizeof (DHCP);
1556 if (optlen > 0) // we must have at least one DHCP option
1558 if (ProcessDHCP (l_Adapter, eth, ip, udp, dhcp, optlen))
1559 goto no_queue;
1561 else
1562 goto no_queue;
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)
1572 ETH_HEADER *e;
1574 if (l_PacketLength < ETHERNET_HEADER_SIZE)
1575 goto no_queue;
1577 e = (ETH_HEADER *) l_PacketBuffer->m_Data;
1579 switch (ntohs (e->proto))
1581 case ETH_P_ARP:
1583 // Make sure that packet is the
1584 // right size for ARP.
1585 if (l_PacketLength != sizeof (ARP_PACKET))
1586 goto no_queue;
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);
1595 default:
1596 goto no_queue;
1598 case ETH_P_IP:
1600 // Make sure that packet is large
1601 // enough to be IPv4.
1602 if (l_PacketLength
1603 < ETHERNET_HEADER_SIZE + IP_HEADER_SIZE)
1604 goto no_queue;
1606 // Only accept directed packets,
1607 // not broadcasts.
1608 if (memcmp (e, &l_Adapter->m_TapToUser, ETHERNET_HEADER_SIZE))
1609 goto no_queue;
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
1618 // userspace.
1619 //===============================================
1621 NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
1623 result = NULL;
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);
1633 goto no_queue;
1635 else
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 //============================================================
1644 while (TRUE)
1646 l_IRP = NULL;
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)
1666 CompleteIRP (l_IRP,
1667 l_PacketBuffer,
1668 IO_NETWORK_INCREMENT);
1670 else
1671 break;
1674 __except (EXCEPTION_EXECUTE_HANDLER)
1678 return NDIS_STATUS_SUCCESS;
1680 no_queue:
1681 NdisFreeMemory (l_PacketBuffer,
1682 TAP_PACKET_SIZE (l_PacketLength),
1685 exit_success:
1686 return NDIS_STATUS_SUCCESS;
1688 exit_fail:
1689 return NDIS_STATUS_FAILURE;
1691 exit_no_resources:
1692 return NDIS_STATUS_RESOURCES;
1695 //======================================================================
1696 // Hooks for catching TAP device IRP's.
1697 //======================================================================
1699 NTSTATUS
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;
1705 BOOLEAN accessible;
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;
1722 else
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,
1745 l_Adapter->m_MAC);
1746 p_IRP->IoStatus.Information = sizeof (MACADDR);
1748 else
1750 NOTE_ERROR ();
1751 p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
1753 break;
1755 case TAP_IOCTL_GET_VERSION:
1757 const ULONG size = sizeof (ULONG) * 3;
1758 if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
1759 >= size)
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]
1766 #if DBG
1767 = 1;
1768 #else
1769 = 0;
1770 #endif
1771 p_IRP->IoStatus.Information = size;
1773 else
1775 NOTE_ERROR ();
1776 p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
1779 break;
1781 case TAP_IOCTL_GET_MTU:
1783 const ULONG size = sizeof (ULONG) * 1;
1784 if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
1785 >= size)
1787 ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0]
1788 = l_Adapter->m_MTU;
1789 p_IRP->IoStatus.Information = size;
1791 else
1793 NOTE_ERROR ();
1794 p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
1797 break;
1799 case TAP_IOCTL_GET_INFO:
1801 char state[16];
1802 if (l_Adapter->m_InterfaceIsRunning)
1803 state[0] = 'A';
1804 else
1805 state[0] = 'a';
1806 if (l_Adapter->m_Extension.m_TapIsRunning)
1807 state[1] = 'T';
1808 else
1809 state[1] = 't';
1810 state[2] = l_Adapter->m_DeviceState;
1811 if (l_Adapter->m_MediaStateAlwaysConnected)
1812 state[3] = 'C';
1813 else
1814 state[3] = 'c';
1815 state[4] = '\0';
1817 p_IRP->IoStatus.Status = l_Status = RtlStringCchPrintfExA (
1818 ((LPTSTR) (p_IRP->AssociatedIrp.SystemBuffer)),
1819 l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
1820 NULL,
1821 NULL,
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]",
1825 #else
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]",
1827 #endif
1828 state,
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,
1836 #endif
1837 (int)l_Adapter->m_Rx,
1838 (int)l_Adapter->m_RxErr,
1839 #if PACKET_TRUNCATION_CHECK
1840 (int)l_Adapter->m_RxTrunc,
1841 #endif
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;
1856 break;
1859 #if DBG
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;
1865 else
1866 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
1868 p_IRP->IoStatus.Information
1869 = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1871 break;
1873 #endif
1875 case TAP_IOCTL_CONFIG_TUN:
1877 if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
1878 (sizeof (IPADDR) * 3))
1880 MACADDR dest;
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)
1893 NOTE_ERROR ();
1894 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1895 break;
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
1911 else
1913 NOTE_ERROR ();
1914 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1917 break;
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))
1925 MACADDR dest;
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
1948 else
1950 NOTE_ERROR ();
1951 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1954 break;
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;
1966 else
1968 NOTE_ERROR ();
1969 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1971 break;
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
2006 else
2008 NOTE_ERROR ();
2009 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
2012 break;
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
2032 else
2034 NOTE_ERROR ();
2035 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
2038 break;
2041 default:
2043 NOTE_ERROR ();
2044 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
2045 break;
2049 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2050 break;
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 //===========================================================
2060 case IRP_MJ_READ:
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",
2071 NAME (l_Adapter)));
2072 NOTE_ERROR ();
2073 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
2074 p_IRP->IoStatus.Information = 0;
2075 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2076 break;
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",
2083 NAME (l_Adapter)));
2084 NOTE_ERROR ();
2085 p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES;
2086 p_IRP->IoStatus.Information = 0;
2087 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2088 break;
2090 else if (!l_Adapter->m_InterfaceIsRunning)
2092 DEBUGP (("[%s] Interface is down in IRP_MJ_READ\n",
2093 NAME (l_Adapter)));
2094 NOTE_ERROR ();
2095 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2096 p_IRP->IoStatus.Information = 0;
2097 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2098 break;
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);
2119 if (l_PacketBuffer)
2121 l_Status = CompleteIRP (p_IRP,
2122 l_PacketBuffer,
2123 IO_NO_INCREMENT);
2124 break;
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);
2139 pending = TRUE;
2142 NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
2144 if (pending)
2145 break;
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));
2150 NOTE_ERROR ();
2151 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2152 p_IRP->IoStatus.Information = 0;
2153 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2154 break;
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 //==============================================================
2162 case IRP_MJ_WRITE:
2164 if (p_IRP->MdlAddress == NULL)
2166 DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n",
2167 NAME (l_Adapter)));
2168 NOTE_ERROR ();
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",
2177 NAME (l_Adapter)));
2178 NOTE_ERROR ();
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",
2185 NAME (l_Adapter)));
2186 NOTE_ERROR ();
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))
2192 __try
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
2202 // was truncated.
2203 //=====================================================
2204 #if PACKET_TRUNCATION_CHECK
2205 IPv4PacketSizeVerify ((unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2206 l_IrpSp->Parameters.Write.Length,
2207 FALSE,
2208 "RX",
2209 &l_Adapter->m_RxTrunc);
2210 #endif
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",
2228 NAME (l_Adapter)));
2229 NOTE_ERROR ();
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))
2236 __try
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
2247 // was truncated.
2248 //=====================================================
2249 #if PACKET_TRUNCATION_CHECK
2250 IPv4PacketSizeVerify ((unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2251 l_IrpSp->Parameters.Write.Length,
2252 TRUE,
2253 "RX",
2254 &l_Adapter->m_RxTrunc);
2255 #endif
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",
2273 NAME (l_Adapter)));
2274 NOTE_ERROR ();
2275 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2276 p_IRP->IoStatus.Information = 0;
2279 else
2281 DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n",
2282 NAME (l_Adapter),
2283 l_IrpSp->Parameters.Write.Length));
2284 NOTE_ERROR ();
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);
2291 else
2292 INCREMENT_STAT (l_Adapter->m_RxErr);
2294 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2295 break;
2298 //--------------------------------------------------------------
2299 // User mode thread has called CreateFile() on the tap device
2300 //--------------------------------------------------------------
2301 case IRP_MJ_CREATE:
2303 BOOLEAN succeeded = FALSE;
2304 BOOLEAN mutex_succeeded;
2306 DEBUGP
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;
2318 succeeded = TRUE;
2321 if (succeeded)
2323 INCREMENT_STAT (l_Adapter->m_Extension.m_NumTapOpens);
2324 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2325 p_IRP->IoStatus.Information = 0;
2327 else
2329 DEBUGP (("[%s] TAP is presently unavailable (m_TapOpens=%d)\n",
2330 NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
2331 NOTE_ERROR ();
2332 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2333 p_IRP->IoStatus.Information = 0;
2336 RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex);
2338 else
2340 DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
2341 NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
2342 NOTE_ERROR ();
2343 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2344 p_IRP->IoStatus.Information = 0;
2347 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2348 break;
2351 //-----------------------------------------------------------
2352 // User mode thread called CloseHandle() on the tap device
2353 //-----------------------------------------------------------
2354 case IRP_MJ_CLOSE:
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);
2371 else
2373 DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
2374 NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
2375 NOTE_ERROR ();
2376 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2377 p_IRP->IoStatus.Information = 0;
2380 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2381 break;
2384 //------------------
2385 // Strange Request
2386 //------------------
2387 default:
2389 //NOTE_ERROR ();
2390 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2391 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2392 break;
2396 return l_Status;
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 //=============================================================
2409 NTSTATUS
2410 CompleteIRP (IN PIRP p_IRP,
2411 IN TapPacketPointer p_PacketBuffer,
2412 IN CCHAR PriorityBoost)
2414 NTSTATUS l_Status = STATUS_UNSUCCESSFUL;
2416 int offset;
2417 int len;
2419 MYASSERT (p_IRP);
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
2429 // component.
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;
2437 else
2439 offset = 0;
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;
2447 NOTE_ERROR ();
2449 else
2451 p_IRP->IoStatus.Information = len;
2452 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2454 __try
2456 NdisMoveMemory (p_IRP->AssociatedIrp.SystemBuffer,
2457 p_PacketBuffer->m_Data + offset,
2458 len);
2460 __except (EXCEPTION_EXECUTE_HANDLER)
2462 NOTE_ERROR ();
2463 p_IRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
2464 p_IRP->IoStatus.Information = 0;
2468 __try
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);
2482 else
2483 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2485 return l_Status;
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 //==============================================
2498 VOID
2499 CancelIRPCallback (IN PDEVICE_OBJECT p_DeviceObject,
2500 IN PIRP p_IRP)
2502 TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject);
2503 CancelIRP (l_Adapter ? &l_Adapter->m_Extension : NULL, p_IRP, TRUE);
2506 VOID
2507 CancelIRP (TapExtensionPointer p_Extension,
2508 IN PIRP p_IRP,
2509 BOOLEAN callback)
2511 BOOLEAN exists = FALSE;
2513 MYASSERT (p_IRP);
2515 if (p_Extension)
2517 NdisAcquireSpinLock (&p_Extension->m_QueueLock);
2518 exists = (QueueExtract (p_Extension->m_IrpQueue, p_IRP) == p_IRP);
2519 NdisReleaseSpinLock (&p_Extension->m_QueueLock);
2521 else
2522 exists = TRUE;
2524 if (exists)
2526 IoSetCancelRoutine (p_IRP, NULL);
2527 p_IRP->IoStatus.Status = STATUS_CANCELLED;
2528 p_IRP->IoStatus.Information = 0;
2531 if (callback)
2532 IoReleaseCancelSpinLock (p_IRP->CancelIrql);
2534 if (exists)
2535 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2538 //===========================================
2539 // Exhaust packet, IRP, and injection queues.
2540 //===========================================
2541 VOID
2542 FlushQueues (TapExtensionPointer p_Extension)
2544 PIRP l_IRP;
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);
2552 while (TRUE)
2554 NdisAcquireSpinLock (&p_Extension->m_QueueLock);
2555 l_IRP = QueuePop (p_Extension->m_IrpQueue);
2556 NdisReleaseSpinLock (&p_Extension->m_QueueLock);
2557 if (l_IRP)
2559 ++n_IRP;
2560 CancelIRP (NULL, l_IRP, FALSE);
2562 else
2563 break;
2566 while (TRUE)
2568 NdisAcquireSpinLock (&p_Extension->m_QueueLock);
2569 l_PacketBuffer = QueuePop (p_Extension->m_PacketQueue);
2570 NdisReleaseSpinLock (&p_Extension->m_QueueLock);
2571 if (l_PacketBuffer)
2573 ++n_Packet;
2574 MemFree (l_PacketBuffer, TAP_PACKET_SIZE (l_PacketBuffer->m_SizeFlags & TP_SIZE_MASK));
2576 else
2577 break;
2580 while (TRUE)
2582 NdisAcquireSpinLock (&p_Extension->m_InjectLock);
2583 l_InjectBuffer = QueuePop (p_Extension->m_InjectQueue);
2584 NdisReleaseSpinLock (&p_Extension->m_InjectLock);
2585 if (l_InjectBuffer)
2587 ++n_Inject;
2588 INJECT_PACKET_FREE(l_InjectBuffer);
2590 else
2591 break;
2594 DEBUGP ((
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,
2597 n_IRP,
2598 p_Extension->m_IrpQueue->max_size,
2599 IRP_QUEUE_SIZE,
2600 n_Packet,
2601 p_Extension->m_PacketQueue->max_size,
2602 PACKET_QUEUE_SIZE,
2603 n_Inject,
2604 p_Extension->m_InjectQueue->max_size,
2605 INJECT_QUEUE_SIZE
2609 //===================================================
2610 // Tell Windows whether the TAP device should be
2611 // considered "connected" or "disconnected".
2612 //===================================================
2613 VOID
2614 SetMediaStatus (TapAdapterPointer p_Adapter, BOOLEAN state)
2616 if (p_Adapter->m_MediaState != state && !p_Adapter->m_MediaStateAlwaysConnected)
2618 if (state)
2619 NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle,
2620 NDIS_STATUS_MEDIA_CONNECT, NULL, 0);
2621 else
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 //======================================================
2636 VOID
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
2651 // ARP queries.
2652 //===================================================
2653 BOOLEAN
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,
2659 const MACADDR mac)
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);
2678 if (arp)
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 //----------------------------------------------
2691 // ARP addresses
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));
2709 return TRUE;
2711 else
2712 return FALSE;
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
2722 VOID
2723 InjectPacketDeferred (TapAdapterPointer p_Adapter,
2724 UCHAR *packet,
2725 const unsigned int len)
2727 InjectPacketPointer l_InjectBuffer;
2728 PVOID result;
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);
2739 if (result)
2740 KeInsertQueueDpc (&p_Adapter->m_Extension.m_InjectDpc, p_Adapter, NULL);
2741 else
2742 INJECT_PACKET_FREE(l_InjectBuffer);
2746 // Handle the injection of previously deferred packets
2747 VOID
2748 InjectPacketDpc(KDPC *Dpc,
2749 PVOID DeferredContext,
2750 PVOID SystemArgument1,
2751 PVOID SystemArgument2)
2753 InjectPacketPointer l_InjectBuffer;
2754 TapAdapterPointer l_Adapter = (TapAdapterPointer)SystemArgument1;
2755 while (TRUE)
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);
2760 if (l_InjectBuffer)
2762 InjectPacketNow(l_Adapter, l_InjectBuffer->m_Data, l_InjectBuffer->m_Size);
2763 INJECT_PACKET_FREE(l_InjectBuffer);
2765 else
2766 break;
2770 // Do packet injection now
2771 VOID
2772 InjectPacketNow (TapAdapterPointer p_Adapter,
2773 UCHAR *packet,
2774 const unsigned int len)
2776 MYASSERT (len >= ETHERNET_HEADER_SIZE);
2778 __try
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,
2793 packet,
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",
2804 NAME (p_Adapter)));
2805 NOTE_ERROR ();
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)
2815 // Point-To-Point
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));
2823 // DHCP Masq
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));
2836 #if ENABLE_NONADMIN
2838 //===================================================================
2839 // Set TAP device handle to be accessible without admin privileges.
2840 //===================================================================
2841 VOID AllowNonAdmin (TapExtensionPointer p_Extension)
2843 NTSTATUS stat;
2844 SECURITY_DESCRIPTOR sd;
2845 OBJECT_ATTRIBUTES oa;
2846 IO_STATUS_BLOCK isb;
2847 HANDLE hand = NULL;
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"));
2856 NOTE_ERROR ();
2857 return;
2860 stat = RtlCreateSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
2861 if (stat != STATUS_SUCCESS)
2863 DEBUGP (("[TAP] AllowNonAdmin: RtlCreateSecurityDescriptor failed\n"));
2864 NOTE_ERROR ();
2865 return;
2868 InitializeObjectAttributes (
2869 &oa,
2870 &p_Extension->m_UnicodeLinkName,
2871 OBJ_KERNEL_HANDLE,
2872 NULL,
2873 NULL
2876 stat = ZwOpenFile (
2877 &hand,
2878 WRITE_DAC,
2879 &oa,
2880 &isb,
2884 if (stat != STATUS_SUCCESS)
2886 DEBUGP (("[TAP] AllowNonAdmin: ZwOpenFile failed, status=0x%08x\n", (unsigned int)stat));
2887 NOTE_ERROR ();
2888 return;
2891 stat = ZwSetSecurityObject (hand, DACL_SECURITY_INFORMATION, &sd);
2892 if (stat != STATUS_SUCCESS)
2894 DEBUGP (("[TAP] AllowNonAdmin: ZwSetSecurityObject failed\n"));
2895 NOTE_ERROR ();
2896 return;
2899 stat = ZwClose (hand);
2900 if (stat != STATUS_SUCCESS)
2902 DEBUGP (("[TAP] AllowNonAdmin: ZwClose failed\n"));
2903 NOTE_ERROR ();
2904 return;
2907 DEBUGP (("[TAP] AllowNonAdmin: SUCCEEDED\n"));
2910 #endif
2912 #if PACKET_TRUNCATION_CHECK
2914 VOID
2915 IPv4PacketSizeVerify (const UCHAR *data, ULONG length, BOOLEAN tun, const char *prefix, LONG *counter)
2917 const IPHDR *ip;
2918 int len = length;
2920 if (tun)
2922 ip = (IPHDR *) data;
2924 else
2926 if (length >= sizeof (ETH_HEADER))
2928 const ETH_HEADER *eth = (ETH_HEADER *) data;
2930 if (eth->proto != htons (ETH_P_IP))
2931 return;
2933 ip = (IPHDR *) (data + sizeof (ETH_HEADER));
2934 len -= sizeof (ETH_HEADER);
2936 else
2937 return;
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));
2946 if (len != totlen)
2947 ++(*counter);
2951 #endif
2953 //======================================================================
2954 // End of Source
2955 //======================================================================