big svn cleanup
[anytun.git] / src / openvpn / tap-win32 / tapdrvr.c
blob9c6304bc2de2d6bc31192db0b9a8e84a55cd70ce
1 /*
2 * TAP-Win32 -- A kernel driver to provide virtual tap device
3 * functionality on Windows. Originally derived
4 * from the CIPE-Win32 project by Damion K. Wilson,
5 * with extensive modifications by James Yonan.
7 * All source code which derives from the CIPE-Win32 project is
8 * Copyright (C) Damion K. Wilson, 2003, and is released under the
9 * GPL version 2 (see below).
11 * All other source code is Copyright (C) 2002-2006 OpenVPN Solutions LLC,
12 * and is released under the GPL version 2 (see below).
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2
16 * as published by the Free Software Foundation.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program (see the file COPYING included with this
25 * distribution); if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 //======================================================
30 // This driver is designed to work on Win 2000 or higher
31 // versions of Windows.
33 // It is SMP-safe and handles NDIS 5 power management.
35 // By default we operate as a "tap" virtual ethernet
36 // 802.3 interface, but we can emulate a "tun"
37 // interface (point-to-point IPv4) through the
38 // TAP_IOCTL_CONFIG_POINT_TO_POINT or
39 // TAP_IOCTL_CONFIG_TUN ioctl.
40 //======================================================
42 #define NDIS_MINIPORT_DRIVER
43 #define BINARY_COMPATIBLE 0
44 #define NDIS50_MINIPORT 1
45 #define NDIS_WDM 0
46 #define NDIS50 1
47 #define NTSTRSAFE_LIB
49 // Debug info output
50 #define ALSO_DBGPRINT 1
51 #define DEBUGP_AT_DISPATCH 0
53 //========================================================
54 // Check for truncated IPv4 packets, log errors if found.
55 //========================================================
56 #define PACKET_TRUNCATION_CHECK 1 // JYFIXME
58 //========================================================
59 // EXPERIMENTAL -- Configure TAP device object to be
60 // accessible from non-administrative accounts, based
61 // on an advanced properties setting.
63 // Duplicates the functionality of OpenVPN's
64 // --allow-nonadmin directive.
65 //========================================================
66 #define ENABLE_NONADMIN 1 // JYFIXME
68 #include <ndis.h>
69 #include <ntstrsafe.h>
70 #include <ntddk.h>
72 #include "lock.h"
73 #include "constants.h"
74 #include "common.h"
75 #include "proto.h"
76 #include "error.h"
77 #include "endian.h"
78 #include "dhcp.h"
79 #include "types.h"
80 #include "prototypes.h"
82 #include "mem.c"
83 #include "macinfo.c"
84 #include "error.c"
85 #include "dhcp.c"
86 #include "instance.c"
88 #define IS_UP(ta) \
89 ((ta)->m_InterfaceIsRunning && (ta)->m_Extension.m_TapIsRunning)
91 #define INCREMENT_STAT(s) ++(s)
93 #define NAME_BUFFER_SIZE 80
95 //========================================================
96 // Globals
97 //========================================================
99 NDIS_HANDLE g_NdisWrapperHandle;
101 const UINT g_SupportedOIDList[] = {
102 OID_GEN_HARDWARE_STATUS,
103 OID_GEN_MEDIA_SUPPORTED,
104 OID_GEN_MEDIA_IN_USE,
105 OID_GEN_MAXIMUM_LOOKAHEAD,
106 OID_GEN_MAC_OPTIONS,
107 OID_GEN_LINK_SPEED,
108 OID_GEN_TRANSMIT_BLOCK_SIZE,
109 OID_GEN_RECEIVE_BLOCK_SIZE,
110 OID_GEN_VENDOR_DESCRIPTION,
111 OID_GEN_DRIVER_VERSION,
112 OID_GEN_XMIT_OK,
113 OID_GEN_RCV_OK,
114 OID_GEN_XMIT_ERROR,
115 OID_GEN_RCV_ERROR,
116 OID_802_3_PERMANENT_ADDRESS,
117 OID_802_3_CURRENT_ADDRESS,
118 OID_GEN_RCV_NO_BUFFER,
119 OID_802_3_RCV_ERROR_ALIGNMENT,
120 OID_802_3_XMIT_ONE_COLLISION,
121 OID_802_3_XMIT_MORE_COLLISIONS,
122 OID_802_3_MULTICAST_LIST,
123 OID_802_3_MAXIMUM_LIST_SIZE,
124 OID_GEN_VENDOR_ID,
125 OID_GEN_CURRENT_LOOKAHEAD,
126 OID_GEN_CURRENT_PACKET_FILTER,
127 OID_GEN_PROTOCOL_OPTIONS,
128 OID_GEN_MAXIMUM_TOTAL_SIZE,
129 OID_GEN_TRANSMIT_BUFFER_SPACE,
130 OID_GEN_RECEIVE_BUFFER_SPACE,
131 OID_GEN_MAXIMUM_FRAME_SIZE,
132 OID_GEN_VENDOR_DRIVER_VERSION,
133 OID_GEN_MAXIMUM_SEND_PACKETS,
134 OID_GEN_MEDIA_CONNECT_STATUS,
135 OID_GEN_SUPPORTED_LIST
138 //============================================================
139 // Driver Entry
140 //============================================================
141 #pragma NDIS_INIT_FUNCTION (DriverEntry)
143 NTSTATUS
144 DriverEntry (IN PDRIVER_OBJECT p_DriverObject,
145 IN PUNICODE_STRING p_RegistryPath)
147 NDIS_STATUS l_Status = NDIS_STATUS_FAILURE;
148 NDIS_MINIPORT_CHARACTERISTICS *l_Properties = NULL;
150 //========================================================
151 // Notify NDIS that a new miniport driver is initializing.
152 //========================================================
154 NdisMInitializeWrapper (&g_NdisWrapperHandle,
155 p_DriverObject,
156 p_RegistryPath, NULL);
158 //======================
159 // Global initialization
160 //======================
162 #if DBG
163 MyDebugInit (10000); // Allocate debugging text space
164 #endif
166 if (!InitInstanceList ())
168 DEBUGP (("[TAP] Allocation failed for adapter instance list\n"));
169 goto cleanup;
172 //=======================================
173 // Set and register miniport entry points
174 //=======================================
176 l_Properties = MemAlloc (sizeof (NDIS_MINIPORT_CHARACTERISTICS), TRUE);
178 if (l_Properties == NULL)
180 DEBUGP (("[TAP] Allocation failed for miniport entry points\n"));
181 goto cleanup;
184 l_Properties->MajorNdisVersion = TAP_NDIS_MAJOR_VERSION;
185 l_Properties->MinorNdisVersion = TAP_NDIS_MINOR_VERSION;
186 l_Properties->InitializeHandler = AdapterCreate;
187 l_Properties->HaltHandler = AdapterHalt;
188 l_Properties->ResetHandler = AdapterReset; /* DISPATCH_LEVEL */
189 l_Properties->TransferDataHandler = AdapterReceive; /* DISPATCH_LEVEL */
190 l_Properties->SendHandler = AdapterTransmit; /* DISPATCH_LEVEL */
191 l_Properties->QueryInformationHandler = AdapterQuery; /* DISPATCH_LEVEL */
192 l_Properties->SetInformationHandler = AdapterModify; /* DISPATCH_LEVEL */
194 switch (l_Status =
195 NdisMRegisterMiniport (g_NdisWrapperHandle, l_Properties,
196 sizeof (NDIS_MINIPORT_CHARACTERISTICS)))
198 case NDIS_STATUS_SUCCESS:
200 DEBUGP (("[TAP] version [%d.%d] %s %s registered miniport successfully\n",
201 TAP_DRIVER_MAJOR_VERSION,
202 TAP_DRIVER_MINOR_VERSION,
203 __DATE__,
204 __TIME__));
205 DEBUGP (("Registry Path: '%S'\n", p_RegistryPath->Buffer));
206 break;
209 case NDIS_STATUS_BAD_CHARACTERISTICS:
211 DEBUGP (("[TAP] Miniport characteristics were badly defined\n"));
212 NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
213 break;
216 case NDIS_STATUS_BAD_VERSION:
218 DEBUGP
219 (("[TAP] NDIS Version is wrong for the given characteristics\n"));
220 NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
221 break;
224 case NDIS_STATUS_RESOURCES:
226 DEBUGP (("[TAP] Insufficient resources\n"));
227 NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
228 break;
231 default:
232 case NDIS_STATUS_FAILURE:
234 DEBUGP (("[TAP] Unknown fatal registration error\n"));
235 NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
236 break;
240 cleanup:
241 if (l_Properties)
242 MemFree (l_Properties, sizeof (NDIS_MINIPORT_CHARACTERISTICS));
244 if (l_Status == NDIS_STATUS_SUCCESS)
245 NdisMRegisterUnloadHandler (g_NdisWrapperHandle, TapDriverUnload);
246 else
247 TapDriverUnload (p_DriverObject);
249 return l_Status;
252 //============================================================
253 // Driver Unload
254 //============================================================
255 VOID
256 TapDriverUnload (IN PDRIVER_OBJECT p_DriverObject)
258 DEBUGP (("[TAP] version [%d.%d] %s %s unloaded, instances=%d, imbs=%d\n",
259 TAP_DRIVER_MAJOR_VERSION,
260 TAP_DRIVER_MINOR_VERSION,
261 __DATE__,
262 __TIME__,
263 NInstances(),
264 InstanceMaxBucketSize()));
266 FreeInstanceList ();
268 //==============================
269 // Free debugging text space
270 //==============================
271 #if DBG
272 MyDebugFree ();
273 #endif
276 //==========================================================
277 // Adapter Initialization
278 //==========================================================
279 NDIS_STATUS AdapterCreate
280 (OUT PNDIS_STATUS p_ErrorStatus,
281 OUT PUINT p_MediaIndex,
282 IN PNDIS_MEDIUM p_Media,
283 IN UINT p_MediaCount,
284 IN NDIS_HANDLE p_AdapterHandle,
285 IN NDIS_HANDLE p_ConfigurationHandle)
287 TapAdapterPointer l_Adapter = NULL;
289 NDIS_MEDIUM l_PreferredMedium = NdisMedium802_3; // Ethernet
290 BOOLEAN l_MacFromRegistry = FALSE;
291 UINT l_Index;
292 NDIS_STATUS status;
294 #if ENABLE_NONADMIN
295 BOOLEAN enable_non_admin = FALSE;
296 #endif
298 //====================================
299 // Make sure adapter type is supported
300 //====================================
302 for (l_Index = 0;
303 l_Index < p_MediaCount && p_Media[l_Index] != l_PreferredMedium;
304 ++l_Index);
306 if (l_Index == p_MediaCount)
308 DEBUGP (("[TAP] Unsupported adapter type [wanted: %d]\n",
309 l_PreferredMedium));
310 return NDIS_STATUS_UNSUPPORTED_MEDIA;
313 *p_MediaIndex = l_Index;
315 //=========================================
316 // Allocate memory for TapAdapter structure
317 //=========================================
319 l_Adapter = MemAlloc (sizeof (TapAdapter), TRUE);
321 if (l_Adapter == NULL)
323 DEBUGP (("[TAP] Couldn't allocate adapter memory\n"));
324 return NDIS_STATUS_RESOURCES;
327 //==========================================
328 // Inform the NDIS library about significant
329 // features of our virtual NIC.
330 //==========================================
332 NdisMSetAttributesEx
333 (p_AdapterHandle,
334 (NDIS_HANDLE) l_Adapter,
336 NDIS_ATTRIBUTE_DESERIALIZE
337 | NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT
338 | NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT
339 | NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
340 NdisInterfaceInternal);
342 //=====================================
343 // Initialize simple Adapter parameters
344 //=====================================
346 l_Adapter->m_Lookahead = DEFAULT_PACKET_LOOKAHEAD;
347 l_Adapter->m_Medium = l_PreferredMedium;
348 l_Adapter->m_DeviceState = '?';
349 l_Adapter->m_MiniportAdapterHandle = p_AdapterHandle;
351 //==================================
352 // Allocate spinlock for controlling
353 // access to multicast address list.
354 //==================================
355 NdisAllocateSpinLock (&l_Adapter->m_MCLock);
356 l_Adapter->m_MCLockAllocated = TRUE;
358 //====================================================
359 // Register a shutdown handler which will be called
360 // on system restart/shutdown to halt our virtual NIC.
361 //====================================================
363 NdisMRegisterAdapterShutdownHandler (p_AdapterHandle, l_Adapter,
364 AdapterHalt);
365 l_Adapter->m_RegisteredAdapterShutdownHandler = TRUE;
367 //============================================
368 // Get parameters from registry which were set
369 // in the adapter advanced properties dialog.
370 //============================================
372 NDIS_STATUS status;
373 NDIS_HANDLE configHandle;
374 NDIS_CONFIGURATION_PARAMETER *parm;
376 // set defaults in case our registry query fails
377 l_Adapter->m_MTU = ETHERNET_MTU;
378 l_Adapter->m_MediaStateAlwaysConnected = FALSE;
379 l_Adapter->m_MediaState = FALSE;
381 NdisOpenConfiguration (&status, &configHandle, p_ConfigurationHandle);
382 if (status != NDIS_STATUS_SUCCESS)
384 DEBUGP (("[TAP] Couldn't open adapter registry\n"));
385 AdapterFreeResources (l_Adapter);
386 return status;
389 //====================================
390 // Allocate and construct adapter name
391 //====================================
393 NDIS_STRING key = NDIS_STRING_CONST("MiniportName");
394 NdisReadConfiguration (&status, &parm, configHandle, &key, NdisParameterString);
395 if (status == NDIS_STATUS_SUCCESS)
397 if (parm->ParameterType == NdisParameterString)
399 DEBUGP (("[TAP] NdisReadConfiguration (MiniportName=%s)\n", parm->ParameterData.StringData.Buffer));
401 if (RtlUnicodeStringToAnsiString (
402 &l_Adapter->m_NameAnsi,
403 &parm->ParameterData.StringData,
404 TRUE) != STATUS_SUCCESS)
406 DEBUGP (("[TAP] RtlUnicodeStringToAnsiString MiniportName failed\n"));
407 status = NDIS_STATUS_RESOURCES;
410 } else {
411 /* "MiniportName" is available only XP and above. Not on Windows 2000. */
412 NDIS_STRING key = NDIS_STRING_CONST("NdisVersion");
413 NdisReadConfiguration (&status, &parm, configHandle, &key, NdisParameterInteger);
414 if (status == NDIS_STATUS_SUCCESS)
416 if (parm->ParameterData.IntegerData == 0x50000)
418 /* Fallback for Windows 2000 with NDIS version 5.00.00
419 Don't use this on Vista, 'NDIS_MINIPORT_BLOCK' was changed! */
420 DEBUGP (("[TAP] NdisReadConfiguration NdisVersion (Int=%X)\n", parm->ParameterData.IntegerData));
421 if (RtlUnicodeStringToAnsiString (
422 &l_Adapter->m_NameAnsi,
423 &((PNDIS_MINIPORT_BLOCK) p_AdapterHandle)->MiniportName,
424 TRUE) != STATUS_SUCCESS)
426 DEBUGP (("[TAP] RtlUnicodeStringToAnsiString MiniportName (W2K) failed\n"));
427 status = NDIS_STATUS_RESOURCES;
434 /* Can't continue without name (see macro 'NAME') */
435 if (status != NDIS_STATUS_SUCCESS || !l_Adapter->m_NameAnsi.Buffer)
437 NdisCloseConfiguration (configHandle);
438 AdapterFreeResources (l_Adapter);
439 return NDIS_STATUS_RESOURCES;
442 /* Read MTU setting from registry */
444 NDIS_STRING key = NDIS_STRING_CONST("MTU");
445 NdisReadConfiguration (&status, &parm, configHandle,
446 &key, NdisParameterInteger);
447 if (status == NDIS_STATUS_SUCCESS)
449 if (parm->ParameterType == NdisParameterInteger)
451 int mtu = parm->ParameterData.IntegerData;
452 if (mtu < MINIMUM_MTU)
453 mtu = MINIMUM_MTU;
454 if (mtu > MAXIMUM_MTU)
455 mtu = MAXIMUM_MTU;
456 l_Adapter->m_MTU = mtu;
461 /* Read Media Status setting from registry */
463 NDIS_STRING key = NDIS_STRING_CONST("MediaStatus");
464 NdisReadConfiguration (&status, &parm, configHandle,
465 &key, NdisParameterInteger);
466 if (status == NDIS_STATUS_SUCCESS)
468 if (parm->ParameterType == NdisParameterInteger)
470 if (parm->ParameterData.IntegerData)
472 l_Adapter->m_MediaStateAlwaysConnected = TRUE;
473 l_Adapter->m_MediaState = TRUE;
479 #if ENABLE_NONADMIN
480 /* Read AllowNonAdmin setting from registry */
482 NDIS_STRING key = NDIS_STRING_CONST("AllowNonAdmin");
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 enable_non_admin = TRUE;
496 #endif
498 /* Read optional MAC setting from registry */
500 NDIS_STRING key = NDIS_STRING_CONST("MAC");
501 ANSI_STRING mac_string;
502 NdisReadConfiguration (&status, &parm, configHandle,
503 &key, NdisParameterString);
504 if (status == NDIS_STATUS_SUCCESS)
506 if (parm->ParameterType == NdisParameterString)
508 if (RtlUnicodeStringToAnsiString (&mac_string, &parm->ParameterData.StringData, TRUE) == STATUS_SUCCESS)
510 l_MacFromRegistry = ParseMAC (l_Adapter->m_MAC, mac_string.Buffer);
511 RtlFreeAnsiString (&mac_string);
517 NdisCloseConfiguration (configHandle);
519 DEBUGP (("[%s] MTU=%d\n", NAME (l_Adapter), l_Adapter->m_MTU));
522 //==================================
523 // Store and update MAC address info
524 //==================================
526 if (!l_MacFromRegistry)
527 GenerateRandomMac (l_Adapter->m_MAC, NAME (l_Adapter));
529 DEBUGP (("[%s] Using MAC %x:%x:%x:%x:%x:%x\n",
530 NAME (l_Adapter),
531 l_Adapter->m_MAC[0], l_Adapter->m_MAC[1], l_Adapter->m_MAC[2],
532 l_Adapter->m_MAC[3], l_Adapter->m_MAC[4], l_Adapter->m_MAC[5]));
534 //==================
535 // Set broadcast MAC
536 //==================
538 int i;
539 for (i = 0; i < sizeof (MACADDR); ++i)
540 l_Adapter->m_MAC_Broadcast[i] = 0xFF;
543 //====================================
544 // Initialize TAP device
545 //====================================
547 NDIS_STATUS tap_status;
548 tap_status = CreateTapDevice (&l_Adapter->m_Extension, NAME (l_Adapter));
549 if (tap_status != NDIS_STATUS_SUCCESS)
551 AdapterFreeResources (l_Adapter);
552 return tap_status;
556 if (!AddAdapterToInstanceList (l_Adapter))
558 NOTE_ERROR ();
559 TapDeviceFreeResources (&l_Adapter->m_Extension);
560 AdapterFreeResources (l_Adapter);
561 return NDIS_STATUS_RESOURCES;
564 l_Adapter->m_InterfaceIsRunning = TRUE;
566 #if ENABLE_NONADMIN
567 if (enable_non_admin)
568 AllowNonAdmin (&l_Adapter->m_Extension);
569 #endif
571 return NDIS_STATUS_SUCCESS;
574 VOID
575 AdapterHalt (IN NDIS_HANDLE p_AdapterContext)
577 BOOLEAN status;
579 TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
581 NOTE_ERROR ();
583 l_Adapter->m_InterfaceIsRunning = FALSE;
585 DEBUGP (("[%s] is being halted\n", NAME (l_Adapter)));
587 DestroyTapDevice (&l_Adapter->m_Extension);
589 // Free resources
590 DEBUGP (("[%s] Freeing Resources\n", NAME (l_Adapter)));
591 AdapterFreeResources (l_Adapter);
593 status = RemoveAdapterFromInstanceList (l_Adapter);
594 DEBUGP (("[TAP] RemoveAdapterFromInstanceList returned %d\n", (int) status));
596 DEBUGP (("[TAP] version [%d.%d] %s %s AdapterHalt returning\n",
597 TAP_DRIVER_MAJOR_VERSION,
598 TAP_DRIVER_MINOR_VERSION,
599 __DATE__,
600 __TIME__));
603 VOID
604 AdapterFreeResources (TapAdapterPointer p_Adapter)
606 MYASSERT (!p_Adapter->m_CalledAdapterFreeResources);
607 p_Adapter->m_CalledAdapterFreeResources = TRUE;
609 if (p_Adapter->m_NameAnsi.Buffer)
610 RtlFreeAnsiString (&p_Adapter->m_NameAnsi);
612 if (p_Adapter->m_RegisteredAdapterShutdownHandler)
613 NdisMDeregisterAdapterShutdownHandler (p_Adapter->m_MiniportAdapterHandle);
615 if (p_Adapter->m_MCLockAllocated)
616 NdisFreeSpinLock (&l_Adapter->m_MCLock);
619 VOID
620 DestroyTapDevice (TapExtensionPointer p_Extension)
622 DEBUGP (("[%s] Destroying tap device\n", p_Extension->m_TapName));
624 //======================================
625 // Let clients know we are shutting down
626 //======================================
627 p_Extension->m_TapIsRunning = FALSE;
628 p_Extension->m_TapOpens = 0;
629 p_Extension->m_Halt = TRUE;
631 //=====================================
632 // If we are concurrently executing in
633 // TapDeviceHook or AdapterTransmit,
634 // give those calls time to finish.
635 // Note that we must be running at IRQL
636 // < DISPATCH_LEVEL in order to call
637 // NdisMSleep.
638 //=====================================
639 NdisMSleep (500000);
641 //===========================================================
642 // Exhaust IRP and packet queues. Any pending IRPs will
643 // be cancelled, causing user-space to get this error
644 // on overlapped reads:
645 // The I/O operation has been aborted because of either a
646 // thread exit or an application request. (code=995)
647 // It's important that user-space close the device handle
648 // when this code is returned, so that when we finally
649 // do a NdisMDeregisterDevice, the device reference count
650 // is 0. Otherwise the driver will not unload even if the
651 // the last adapter has been halted.
652 //===========================================================
653 FlushQueues (p_Extension);
654 NdisMSleep (500000); // give user space time to respond to IRP cancel
656 TapDeviceFreeResources (p_Extension);
659 VOID
660 TapDeviceFreeResources (TapExtensionPointer p_Extension)
662 MYASSERT (p_Extension);
663 MYASSERT (!p_Extension->m_CalledTapDeviceFreeResources);
664 p_Extension->m_CalledTapDeviceFreeResources = TRUE;
666 if (p_Extension->m_PacketQueue)
667 QueueFree (p_Extension->m_PacketQueue);
668 if (p_Extension->m_IrpQueue)
669 QueueFree (p_Extension->m_IrpQueue);
671 if (p_Extension->m_CreatedUnicodeLinkName)
672 RtlFreeUnicodeString (&p_Extension->m_UnicodeLinkName);
674 //==========================================================
675 // According to DDK docs, the device is not actually deleted
676 // until its reference count falls to zero. That means we
677 // still need to gracefully fail TapDeviceHook requests
678 // after this point, otherwise ugly things would happen if
679 // the device was disabled (e.g. in the network connections
680 // control panel) while a userspace app still held an open
681 // file handle to it.
682 //==========================================================
684 if (p_Extension->m_TapDevice)
686 BOOLEAN status;
687 status = (NdisMDeregisterDevice (p_Extension->m_TapDeviceHandle)
688 == NDIS_STATUS_SUCCESS);
689 DEBUGP (("[TAP] Deregistering TAP device, status=%d\n", (int)status));
692 if (p_Extension->m_TapName)
693 MemFree (p_Extension->m_TapName, NAME_BUFFER_SIZE);
695 if (p_Extension->m_AllocatedSpinlocks)
696 NdisFreeSpinLock (&p_Extension->m_QueueLock);
699 //========================================================================
700 // Tap Device Initialization
701 //========================================================================
703 NDIS_STATUS
704 CreateTapDevice (TapExtensionPointer p_Extension, const char *p_Name)
706 # define SIZEOF_DISPATCH (sizeof(PDRIVER_DISPATCH) * (IRP_MJ_MAXIMUM_FUNCTION + 1))
707 PDRIVER_DISPATCH *l_Dispatch = NULL;
708 ANSI_STRING l_TapString, l_LinkString;
709 UNICODE_STRING l_TapUnicode;
710 BOOLEAN l_FreeTapUnicode = FALSE;
711 NTSTATUS l_Status, l_Return = NDIS_STATUS_SUCCESS;
712 const char *l_UsableName;
714 DEBUGP (("[TAP] version [%d.%d] creating tap device: %s\n",
715 TAP_DRIVER_MAJOR_VERSION,
716 TAP_DRIVER_MINOR_VERSION,
717 p_Name));
719 NdisZeroMemory (p_Extension, sizeof (TapExtension));
721 INIT_MUTEX (&p_Extension->m_OpenCloseMutex);
723 l_LinkString.Buffer = NULL;
724 l_TapString.Buffer = NULL;
726 l_TapString.MaximumLength = l_LinkString.MaximumLength = NAME_BUFFER_SIZE;
728 //=======================================
729 // Set TAP device entry points
730 //=======================================
732 if ((l_Dispatch = MemAlloc (SIZEOF_DISPATCH, TRUE)) == NULL)
734 DEBUGP (("[%s] couldn't alloc TAP dispatch table\n", p_Name));
735 l_Return = NDIS_STATUS_RESOURCES;
736 goto cleanup;
739 l_Dispatch[IRP_MJ_DEVICE_CONTROL] = TapDeviceHook;
740 l_Dispatch[IRP_MJ_READ] = TapDeviceHook;
741 l_Dispatch[IRP_MJ_WRITE] = TapDeviceHook;
742 l_Dispatch[IRP_MJ_CREATE] = TapDeviceHook;
743 l_Dispatch[IRP_MJ_CLOSE] = TapDeviceHook;
745 //==================================
746 // Find the beginning of the GUID
747 //==================================
748 l_UsableName = p_Name;
749 while (*l_UsableName != '{')
751 if (*l_UsableName == '\0')
753 DEBUGP (("[%s] couldn't find leading '{' in name\n", p_Name));
754 l_Return = NDIS_STATUS_RESOURCES;
755 goto cleanup;
757 ++l_UsableName;
760 //==================================
761 // Allocate pool for TAP device name
762 //==================================
764 if ((p_Extension->m_TapName = l_TapString.Buffer =
765 MemAlloc (NAME_BUFFER_SIZE, TRUE)) == NULL)
767 DEBUGP (("[%s] couldn't alloc TAP name buffer\n", p_Name));
768 l_Return = NDIS_STATUS_RESOURCES;
769 goto cleanup;
772 //================================================
773 // Allocate pool for TAP symbolic link name buffer
774 //================================================
776 if ((l_LinkString.Buffer =
777 MemAlloc (NAME_BUFFER_SIZE, TRUE)) == NULL)
779 DEBUGP (("[%s] couldn't alloc TAP symbolic link name buffer\n",
780 p_Name));
781 l_Return = NDIS_STATUS_RESOURCES;
782 goto cleanup;
785 //=======================================================
786 // Set TAP device name
787 //=======================================================
789 l_Status = RtlStringCchPrintfExA
790 (l_TapString.Buffer,
791 l_TapString.MaximumLength,
792 NULL,
793 NULL,
794 STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,
795 "%s%s%s",
796 SYSDEVICEDIR,
797 l_UsableName,
798 TAPSUFFIX);
800 if (l_Status != STATUS_SUCCESS)
802 DEBUGP (("[%s] couldn't format TAP device name\n",
803 p_Name));
804 l_Return = NDIS_STATUS_RESOURCES;
805 goto cleanup;
807 l_TapString.Length = (USHORT) strlen (l_TapString.Buffer);
809 DEBUGP (("TAP DEV NAME: '%s'\n", l_TapString.Buffer));
811 //=======================================================
812 // Set TAP link name
813 //=======================================================
815 l_Status = RtlStringCchPrintfExA
816 (l_LinkString.Buffer,
817 l_LinkString.MaximumLength,
818 NULL,
819 NULL,
820 STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,
821 "%s%s%s",
822 USERDEVICEDIR,
823 l_UsableName,
824 TAPSUFFIX);
826 if (l_Status != STATUS_SUCCESS)
828 DEBUGP (("[%s] couldn't format TAP device symbolic link\n",
829 p_Name));
830 l_Return = NDIS_STATUS_RESOURCES;
831 goto cleanup;
833 l_LinkString.Length = (USHORT) strlen (l_LinkString.Buffer);
835 DEBUGP (("TAP LINK NAME: '%s'\n", l_LinkString.Buffer));
837 //==================================================
838 // Convert strings to unicode
839 //==================================================
840 if (RtlAnsiStringToUnicodeString (&l_TapUnicode, &l_TapString, TRUE) !=
841 STATUS_SUCCESS)
843 DEBUGP (("[%s] couldn't alloc TAP unicode name buffer\n",
844 p_Name));
845 l_Return = NDIS_STATUS_RESOURCES;
846 goto cleanup;
848 l_FreeTapUnicode = TRUE;
850 if (RtlAnsiStringToUnicodeString
851 (&p_Extension->m_UnicodeLinkName, &l_LinkString, TRUE)
852 != STATUS_SUCCESS)
854 DEBUGP
855 (("[%s] Couldn't allocate unicode string for symbolic link name\n",
856 p_Name));
857 l_Return = NDIS_STATUS_RESOURCES;
858 goto cleanup;
860 p_Extension->m_CreatedUnicodeLinkName = TRUE;
862 //==================================================
863 // Create new TAP device with symbolic
864 // link and associate with adapter.
865 //==================================================
867 l_Status = NdisMRegisterDevice
868 (g_NdisWrapperHandle,
869 &l_TapUnicode,
870 &p_Extension->m_UnicodeLinkName,
871 l_Dispatch,
872 &p_Extension->m_TapDevice,
873 &p_Extension->m_TapDeviceHandle
876 if (l_Status != STATUS_SUCCESS)
878 DEBUGP (("[%s] couldn't be created\n", p_Name));
879 l_Return = NDIS_STATUS_RESOURCES;
880 goto cleanup;
883 /* Set TAP device flags */
884 p_Extension->m_TapDevice->Flags |= DO_DIRECT_IO;
886 //========================================================
887 // Initialize Packet and IRP queues.
889 // The packet queue is used to buffer data which has been
890 // "transmitted" by the virtual NIC, before user space
891 // has had a chance to read it.
893 // The IRP queue is used to buffer pending I/O requests
894 // from userspace, i.e. read requests on the TAP device
895 // waiting for the system to "transmit" something through
896 // the virtual NIC.
898 // Basically, packets in the packet queue are used
899 // to satisfy IRP requests in the IRP queue.
901 // QueueLock is used to lock the packet queue used
902 // for the TAP-Win32 NIC -> User Space packet flow direction.
904 // All accesses to packet or IRP queues should be
905 // bracketed by the QueueLock spinlock,
906 // in order to be SMP-safe.
907 //========================================================
909 NdisAllocateSpinLock (&p_Extension->m_QueueLock);
910 p_Extension->m_AllocatedSpinlocks = TRUE;
912 p_Extension->m_PacketQueue = QueueInit (PACKET_QUEUE_SIZE);
913 p_Extension->m_IrpQueue = QueueInit (IRP_QUEUE_SIZE);
915 if (!p_Extension->m_PacketQueue
916 || !p_Extension->m_IrpQueue)
918 DEBUGP (("[%s] couldn't alloc TAP queues\n", p_Name));
919 l_Return = NDIS_STATUS_RESOURCES;
920 goto cleanup;
923 //========================
924 // Finalize initialization
925 //========================
927 p_Extension->m_TapIsRunning = TRUE;
929 DEBUGP (("[%s] successfully created TAP device [%s]\n", p_Name,
930 p_Extension->m_TapName));
932 cleanup:
933 if (l_FreeTapUnicode)
934 RtlFreeUnicodeString (&l_TapUnicode);
935 if (l_LinkString.Buffer)
936 MemFree (l_LinkString.Buffer, NAME_BUFFER_SIZE);
937 if (l_Dispatch)
938 MemFree (l_Dispatch, SIZEOF_DISPATCH);
940 if (l_Return != NDIS_STATUS_SUCCESS)
941 TapDeviceFreeResources (p_Extension);
943 return l_Return;
945 #undef SIZEOF_DISPATCH
947 //========================================================
948 // Adapter Control
949 //========================================================
950 NDIS_STATUS
951 AdapterReset (OUT PBOOLEAN p_AddressingReset, IN NDIS_HANDLE p_AdapterContext)
953 TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
954 DEBUGP (("[%s] is resetting\n", NAME (l_Adapter)));
955 return NDIS_STATUS_SUCCESS;
958 NDIS_STATUS AdapterReceive
959 (OUT PNDIS_PACKET p_Packet,
960 OUT PUINT p_Transferred,
961 IN NDIS_HANDLE p_AdapterContext,
962 IN NDIS_HANDLE p_ReceiveContext,
963 IN UINT p_Offset,
964 IN UINT p_ToTransfer)
966 return NDIS_STATUS_SUCCESS;
969 //==============================================================
970 // Adapter Option Query/Modification
971 //==============================================================
972 NDIS_STATUS AdapterQuery
973 (IN NDIS_HANDLE p_AdapterContext,
974 IN NDIS_OID p_OID,
975 IN PVOID p_Buffer,
976 IN ULONG p_BufferLength,
977 OUT PULONG p_BytesWritten, OUT PULONG p_BytesNeeded)
979 TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
980 TapAdapterQuery l_Query, *l_QueryPtr = &l_Query;
981 NDIS_STATUS l_Status = NDIS_STATUS_SUCCESS;
982 UINT l_QueryLength = 4;
983 BOOLEAN lock_succeeded;
985 NdisZeroMemory (&l_Query, sizeof (l_Query));
987 switch (p_OID)
989 //===================================================================
990 // Vendor & Driver version Info
991 //===================================================================
992 case OID_GEN_VENDOR_DESCRIPTION:
993 l_QueryPtr = (TapAdapterQueryPointer) PRODUCT_STRING;
994 l_QueryLength = strlen (PRODUCT_STRING) + 1;
995 break;
997 case OID_GEN_VENDOR_ID:
998 l_Query.m_Long = 0xffffff;
999 break;
1001 case OID_GEN_DRIVER_VERSION:
1002 l_Query.m_Short =
1003 (((USHORT) TAP_NDIS_MAJOR_VERSION) << 8 | (USHORT)
1004 TAP_NDIS_MINOR_VERSION);
1005 l_QueryLength = sizeof (unsigned short);
1006 break;
1008 case OID_GEN_VENDOR_DRIVER_VERSION:
1009 l_Query.m_Long =
1010 (((USHORT) TAP_DRIVER_MAJOR_VERSION) << 8 | (USHORT)
1011 TAP_DRIVER_MINOR_VERSION);
1012 break;
1014 //=================================================================
1015 // Statistics
1016 //=================================================================
1017 case OID_GEN_RCV_NO_BUFFER:
1018 l_Query.m_Long = 0;
1019 break;
1021 case OID_802_3_RCV_ERROR_ALIGNMENT:
1022 l_Query.m_Long = 0;
1023 break;
1025 case OID_802_3_XMIT_ONE_COLLISION:
1026 l_Query.m_Long = 0;
1027 break;
1029 case OID_802_3_XMIT_MORE_COLLISIONS:
1030 l_Query.m_Long = 0;
1031 break;
1033 case OID_GEN_XMIT_OK:
1034 l_Query.m_Long = l_Adapter->m_Tx;
1035 break;
1037 case OID_GEN_RCV_OK:
1038 l_Query.m_Long = l_Adapter->m_Rx;
1039 break;
1041 case OID_GEN_XMIT_ERROR:
1042 l_Query.m_Long = l_Adapter->m_TxErr;
1043 break;
1045 case OID_GEN_RCV_ERROR:
1046 l_Query.m_Long = l_Adapter->m_RxErr;
1047 break;
1049 //===================================================================
1050 // Device & Protocol Options
1051 //===================================================================
1052 case OID_GEN_SUPPORTED_LIST:
1053 l_QueryPtr = (TapAdapterQueryPointer) g_SupportedOIDList;
1054 l_QueryLength = sizeof (g_SupportedOIDList);
1055 break;
1057 case OID_GEN_MAC_OPTIONS:
1058 // This MUST be here !!!
1059 l_Query.m_Long = (NDIS_MAC_OPTION_RECEIVE_SERIALIZED
1060 | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA
1061 | NDIS_MAC_OPTION_NO_LOOPBACK
1062 | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND);
1064 break;
1066 case OID_GEN_CURRENT_PACKET_FILTER:
1067 l_Query.m_Long =
1068 (NDIS_PACKET_TYPE_ALL_LOCAL |
1069 NDIS_PACKET_TYPE_BROADCAST |
1070 NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_FUNCTIONAL);
1072 break;
1074 case OID_GEN_PROTOCOL_OPTIONS:
1075 l_Query.m_Long = 0;
1076 break;
1078 //==================================================================
1079 // Device Info
1080 //==================================================================
1081 case OID_GEN_MEDIA_CONNECT_STATUS:
1082 l_Query.m_Long = l_Adapter->m_MediaState
1083 ? NdisMediaStateConnected : NdisMediaStateDisconnected;
1084 break;
1086 case OID_GEN_HARDWARE_STATUS:
1087 l_Query.m_HardwareStatus = NdisHardwareStatusReady;
1088 l_QueryLength = sizeof (NDIS_HARDWARE_STATUS);
1089 break;
1091 case OID_GEN_MEDIA_SUPPORTED:
1092 case OID_GEN_MEDIA_IN_USE:
1093 l_Query.m_Medium = l_Adapter->m_Medium;
1094 l_QueryLength = sizeof (NDIS_MEDIUM);
1095 break;
1097 case OID_GEN_PHYSICAL_MEDIUM:
1098 l_Query.m_PhysicalMedium = NdisPhysicalMediumUnspecified;
1099 l_QueryLength = sizeof (NDIS_PHYSICAL_MEDIUM);
1100 break;
1102 case OID_GEN_LINK_SPEED:
1103 l_Query.m_Long = 100000; // rate / 100 bps
1104 break;
1106 case OID_802_3_PERMANENT_ADDRESS:
1107 case OID_802_3_CURRENT_ADDRESS:
1108 COPY_MAC (l_Query.m_MacAddress, l_Adapter->m_MAC);
1109 l_QueryLength = sizeof (MACADDR);
1110 break;
1112 //==================================================================
1113 // Limits
1114 //==================================================================
1116 case OID_GEN_MAXIMUM_SEND_PACKETS:
1117 l_Query.m_Long = 1;
1118 break;
1120 case OID_802_3_MAXIMUM_LIST_SIZE:
1121 l_Query.m_Long = NIC_MAX_MCAST_LIST;
1122 break;
1124 case OID_GEN_CURRENT_LOOKAHEAD:
1125 l_Query.m_Long = l_Adapter->m_Lookahead;
1126 break;
1128 case OID_GEN_MAXIMUM_LOOKAHEAD:
1129 case OID_GEN_MAXIMUM_TOTAL_SIZE:
1130 case OID_GEN_RECEIVE_BUFFER_SPACE:
1131 case OID_GEN_RECEIVE_BLOCK_SIZE:
1132 l_Query.m_Long = DEFAULT_PACKET_LOOKAHEAD;
1133 break;
1135 case OID_GEN_MAXIMUM_FRAME_SIZE:
1136 case OID_GEN_TRANSMIT_BLOCK_SIZE:
1137 case OID_GEN_TRANSMIT_BUFFER_SPACE:
1138 l_Query.m_Long = l_Adapter->m_MTU;
1139 break;
1141 case OID_PNP_CAPABILITIES:
1144 PNDIS_PNP_CAPABILITIES pPNPCapabilities;
1145 PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct;
1147 if (p_BufferLength >= sizeof (NDIS_PNP_CAPABILITIES))
1149 pPNPCapabilities = (PNDIS_PNP_CAPABILITIES) (p_Buffer);
1152 // Setting up the buffer to be returned
1153 // to the Protocol above the Passthru miniport
1155 pPMstruct = &pPNPCapabilities->WakeUpCapabilities;
1156 pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
1157 pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;
1158 pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
1160 l_QueryLength = sizeof (NDIS_PNP_CAPABILITIES);
1162 while (FALSE);
1163 break;
1164 case OID_PNP_QUERY_POWER:
1165 break;
1167 // Required OIDs that we don't support
1169 case OID_GEN_SUPPORTED_GUIDS:
1170 case OID_GEN_MEDIA_CAPABILITIES:
1171 case OID_TCP_TASK_OFFLOAD:
1172 case OID_FFP_SUPPORT:
1173 l_Status = NDIS_STATUS_INVALID_OID;
1174 break;
1176 // Optional stats OIDs
1178 case OID_GEN_DIRECTED_BYTES_XMIT:
1179 case OID_GEN_DIRECTED_FRAMES_XMIT:
1180 case OID_GEN_MULTICAST_BYTES_XMIT:
1181 case OID_GEN_MULTICAST_FRAMES_XMIT:
1182 case OID_GEN_BROADCAST_BYTES_XMIT:
1183 case OID_GEN_BROADCAST_FRAMES_XMIT:
1184 case OID_GEN_DIRECTED_BYTES_RCV:
1185 case OID_GEN_DIRECTED_FRAMES_RCV:
1186 case OID_GEN_MULTICAST_BYTES_RCV:
1187 case OID_GEN_MULTICAST_FRAMES_RCV:
1188 case OID_GEN_BROADCAST_BYTES_RCV:
1189 case OID_GEN_BROADCAST_FRAMES_RCV:
1190 l_Status = NDIS_STATUS_INVALID_OID;
1191 break;
1193 //===================================================================
1194 // Not Handled
1195 //===================================================================
1196 default:
1197 DEBUGP (("[%s] Unhandled OID %lx\n", NAME (l_Adapter), p_OID));
1198 l_Status = NDIS_STATUS_INVALID_OID;
1199 break;
1202 if (l_Status != NDIS_STATUS_SUCCESS)
1204 else if (l_QueryLength > p_BufferLength)
1206 l_Status = NDIS_STATUS_INVALID_LENGTH;
1207 *p_BytesNeeded = l_QueryLength;
1209 else
1210 NdisMoveMemory (p_Buffer, (PVOID) l_QueryPtr,
1211 (*p_BytesWritten = l_QueryLength));
1213 return l_Status;
1216 NDIS_STATUS AdapterModify
1217 (IN NDIS_HANDLE p_AdapterContext,
1218 IN NDIS_OID p_OID,
1219 IN PVOID p_Buffer,
1220 IN ULONG p_BufferLength,
1221 OUT PULONG p_BytesRead,
1222 OUT PULONG p_BytesNeeded)
1224 TapAdapterQueryPointer l_Query = (TapAdapterQueryPointer) p_Buffer;
1225 TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
1226 NDIS_STATUS l_Status = NDIS_STATUS_INVALID_OID;
1227 ULONG l_Long;
1229 switch (p_OID)
1231 //==================================================================
1232 // Device Info
1233 //==================================================================
1234 case OID_802_3_MULTICAST_LIST:
1235 DEBUGP (("[%s] Setting [OID_802_3_MULTICAST_LIST]\n",
1236 NAME (l_Adapter)));
1238 *p_BytesNeeded = sizeof (ETH_ADDR);
1239 *p_BytesRead = p_BufferLength;
1241 if (p_BufferLength % sizeof (ETH_ADDR))
1242 l_Status = NDIS_STATUS_INVALID_LENGTH;
1243 else if (p_BufferLength > sizeof (MC_LIST))
1245 l_Status = NDIS_STATUS_MULTICAST_FULL;
1246 *p_BytesNeeded = sizeof (MC_LIST);
1248 else
1250 NdisAcquireSpinLock (&l_Adapter->m_MCLock);
1252 NdisZeroMemory(&l_Adapter->m_MCList, sizeof (MC_LIST));
1254 NdisMoveMemory(&l_Adapter->m_MCList,
1255 p_Buffer,
1256 p_BufferLength);
1258 l_Adapter->m_MCListSize = p_BufferLength / sizeof (ETH_ADDR);
1260 NdisReleaseSpinLock (&l_Adapter->m_MCLock);
1262 l_Status = NDIS_STATUS_SUCCESS;
1264 break;
1266 case OID_GEN_CURRENT_PACKET_FILTER:
1267 l_Status = NDIS_STATUS_INVALID_LENGTH;
1268 *p_BytesNeeded = 4;
1270 if (p_BufferLength >= sizeof (ULONG))
1272 DEBUGP
1273 (("[%s] Setting [OID_GEN_CURRENT_PACKET_FILTER] to [0x%02lx]\n",
1274 NAME (l_Adapter), l_Query->m_Long));
1275 l_Status = NDIS_STATUS_SUCCESS;
1276 *p_BytesRead = sizeof (ULONG);
1278 break;
1280 case OID_GEN_CURRENT_LOOKAHEAD:
1281 if (p_BufferLength < sizeof (ULONG))
1283 l_Status = NDIS_STATUS_INVALID_LENGTH;
1284 *p_BytesNeeded = 4;
1286 else if (l_Query->m_Long > DEFAULT_PACKET_LOOKAHEAD
1287 || l_Query->m_Long <= 0)
1289 l_Status = NDIS_STATUS_INVALID_DATA;
1291 else
1293 DEBUGP (("[%s] Setting [OID_GEN_CURRENT_LOOKAHEAD] to [%d]\n",
1294 NAME (l_Adapter), l_Query->m_Long));
1295 l_Adapter->m_Lookahead = l_Query->m_Long;
1296 l_Status = NDIS_STATUS_SUCCESS;
1297 *p_BytesRead = sizeof (ULONG);
1299 break;
1301 case OID_GEN_NETWORK_LAYER_ADDRESSES:
1302 l_Status = NDIS_STATUS_SUCCESS;
1303 *p_BytesRead = *p_BytesNeeded = 0;
1304 break;
1306 case OID_GEN_TRANSPORT_HEADER_OFFSET:
1307 l_Status = NDIS_STATUS_SUCCESS;
1308 *p_BytesRead = *p_BytesNeeded = 0;
1309 break;
1311 case OID_PNP_SET_POWER:
1314 NDIS_DEVICE_POWER_STATE NewDeviceState;
1316 NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE) p_Buffer);
1318 switch (NewDeviceState)
1320 case NdisDeviceStateD0:
1321 l_Adapter->m_DeviceState = '0';
1322 break;
1323 case NdisDeviceStateD1:
1324 l_Adapter->m_DeviceState = '1';
1325 break;
1326 case NdisDeviceStateD2:
1327 l_Adapter->m_DeviceState = '2';
1328 break;
1329 case NdisDeviceStateD3:
1330 l_Adapter->m_DeviceState = '3';
1331 break;
1332 default:
1333 l_Adapter->m_DeviceState = '?';
1334 break;
1337 l_Status = NDIS_STATUS_FAILURE;
1340 // Check for invalid length
1342 if (p_BufferLength < sizeof (NDIS_DEVICE_POWER_STATE))
1344 l_Status = NDIS_STATUS_INVALID_LENGTH;
1345 break;
1348 if (NewDeviceState > NdisDeviceStateD0)
1350 l_Adapter->m_InterfaceIsRunning = FALSE;
1351 DEBUGP (("[%s] Power management device state OFF\n",
1352 NAME (l_Adapter)));
1354 else
1356 l_Adapter->m_InterfaceIsRunning = TRUE;
1357 DEBUGP (("[%s] Power management device state ON\n",
1358 NAME (l_Adapter)));
1361 l_Status = NDIS_STATUS_SUCCESS;
1363 while (FALSE);
1365 if (l_Status == NDIS_STATUS_SUCCESS)
1367 *p_BytesRead = sizeof (NDIS_DEVICE_POWER_STATE);
1368 *p_BytesNeeded = 0;
1370 else
1372 *p_BytesRead = 0;
1373 *p_BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE);
1375 break;
1377 case OID_PNP_REMOVE_WAKE_UP_PATTERN:
1378 case OID_PNP_ADD_WAKE_UP_PATTERN:
1379 l_Status = NDIS_STATUS_SUCCESS;
1380 *p_BytesRead = *p_BytesNeeded = 0;
1381 break;
1383 default:
1384 DEBUGP (("[%s] Can't set value for OID %lx\n", NAME (l_Adapter),
1385 p_OID));
1386 l_Status = NDIS_STATUS_INVALID_OID;
1387 *p_BytesRead = *p_BytesNeeded = 0;
1388 break;
1391 return l_Status;
1394 //====================================================================
1395 // Adapter Transmission
1396 //====================================================================
1397 NDIS_STATUS
1398 AdapterTransmit (IN NDIS_HANDLE p_AdapterContext,
1399 IN PNDIS_PACKET p_Packet,
1400 IN UINT p_Flags)
1402 TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
1403 ULONG l_Index = 0, l_BufferLength = 0, l_PacketLength = 0;
1404 PIRP l_IRP;
1405 TapPacketPointer l_PacketBuffer;
1406 PNDIS_BUFFER l_NDIS_Buffer;
1407 PUCHAR l_Buffer;
1408 PVOID result;
1410 NdisQueryPacket (p_Packet, NULL, NULL, &l_NDIS_Buffer, &l_PacketLength);
1412 //====================================================
1413 // Here we abandon the transmission attempt if any of
1414 // the parameters is wrong or memory allocation fails
1415 // but we do not indicate failure. The packet is
1416 // silently dropped.
1417 //====================================================
1419 if (l_PacketLength < ETHERNET_HEADER_SIZE || l_PacketLength > 65535)
1420 goto exit_fail;
1421 else if (!l_Adapter->m_Extension.m_TapOpens || !l_Adapter->m_MediaState)
1422 goto exit_success; // Nothing is bound to the TAP device
1424 if (NdisAllocateMemoryWithTag (&l_PacketBuffer,
1425 TAP_PACKET_SIZE (l_PacketLength),
1426 '5PAT') != NDIS_STATUS_SUCCESS)
1427 goto exit_no_resources;
1429 if (l_PacketBuffer == NULL)
1430 goto exit_no_resources;
1432 l_PacketBuffer->m_SizeFlags = (l_PacketLength & TP_SIZE_MASK);
1434 //===========================
1435 // Reassemble packet contents
1436 //===========================
1438 __try
1440 l_Index = 0;
1441 while (l_NDIS_Buffer && l_Index < l_PacketLength)
1443 ULONG newlen;
1444 NdisQueryBuffer (l_NDIS_Buffer, (PVOID *) & l_Buffer,
1445 &l_BufferLength);
1446 newlen = l_Index + l_BufferLength;
1447 if (newlen > l_PacketLength)
1449 NOTE_ERROR ();
1450 goto no_queue; /* overflow */
1452 NdisMoveMemory (l_PacketBuffer->m_Data + l_Index, l_Buffer,
1453 l_BufferLength);
1454 l_Index = newlen;
1455 NdisGetNextBuffer (l_NDIS_Buffer, &l_NDIS_Buffer);
1457 if (l_Index != l_PacketLength)
1459 NOTE_ERROR ();
1460 goto no_queue; /* underflow */
1463 DUMP_PACKET ("AdapterTransmit", l_PacketBuffer->m_Data, l_PacketLength);
1465 //=====================================================
1466 // If IPv4 packet, check whether or not packet
1467 // was truncated.
1468 //=====================================================
1469 #if PACKET_TRUNCATION_CHECK
1470 IPv4PacketSizeVerify (l_PacketBuffer->m_Data, l_PacketLength, FALSE, "TX", &l_Adapter->m_TxTrunc);
1471 #endif
1473 //=====================================================
1474 // Are we running in DHCP server masquerade mode?
1476 // If so, catch both DHCP requests and ARP queries
1477 // to resolve the address of our virtual DHCP server.
1478 //=====================================================
1479 if (l_Adapter->m_dhcp_enabled)
1481 const ETH_HEADER *eth = (ETH_HEADER *) l_PacketBuffer->m_Data;
1482 const IPHDR *ip = (IPHDR *) (l_PacketBuffer->m_Data + sizeof (ETH_HEADER));
1483 const UDPHDR *udp = (UDPHDR *) (l_PacketBuffer->m_Data + sizeof (ETH_HEADER) + sizeof (IPHDR));
1485 // ARP packet?
1486 if (l_PacketLength == sizeof (ARP_PACKET)
1487 && eth->proto == htons (ETH_P_ARP)
1488 && l_Adapter->m_dhcp_server_arp)
1490 if (ProcessARP (l_Adapter,
1491 (PARP_PACKET) l_PacketBuffer->m_Data,
1492 l_Adapter->m_dhcp_addr,
1493 l_Adapter->m_dhcp_server_ip,
1495 l_Adapter->m_dhcp_server_mac))
1496 goto no_queue;
1499 // DHCP packet?
1500 else if (l_PacketLength >= sizeof (ETH_HEADER) + sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP)
1501 && eth->proto == htons (ETH_P_IP)
1502 && ip->version_len == 0x45 // IPv4, 20 byte header
1503 && ip->protocol == IPPROTO_UDP
1504 && udp->dest == htons (BOOTPS_PORT))
1506 const DHCP *dhcp = (DHCP *) (l_PacketBuffer->m_Data
1507 + sizeof (ETH_HEADER)
1508 + sizeof (IPHDR)
1509 + sizeof (UDPHDR));
1511 const int optlen = l_PacketLength
1512 - sizeof (ETH_HEADER)
1513 - sizeof (IPHDR)
1514 - sizeof (UDPHDR)
1515 - sizeof (DHCP);
1517 if (optlen > 0) // we must have at least one DHCP option
1519 if (ProcessDHCP (l_Adapter, eth, ip, udp, dhcp, optlen))
1520 goto no_queue;
1522 else
1523 goto no_queue;
1527 //===============================================
1528 // In Point-To-Point mode, check to see whether
1529 // packet is ARP or IPv4 (if neither, then drop).
1530 //===============================================
1531 if (l_Adapter->m_tun)
1533 ETH_HEADER *e;
1535 if (l_PacketLength < ETHERNET_HEADER_SIZE)
1536 goto no_queue;
1538 e = (ETH_HEADER *) l_PacketBuffer->m_Data;
1540 switch (ntohs (e->proto))
1542 case ETH_P_ARP:
1544 // Make sure that packet is the
1545 // right size for ARP.
1546 if (l_PacketLength != sizeof (ARP_PACKET))
1547 goto no_queue;
1549 ProcessARP (l_Adapter,
1550 (PARP_PACKET) l_PacketBuffer->m_Data,
1551 l_Adapter->m_localIP,
1552 l_Adapter->m_remoteNetwork,
1553 l_Adapter->m_remoteNetmask,
1554 l_Adapter->m_TapToUser.dest);
1556 default:
1557 goto no_queue;
1559 case ETH_P_IP:
1561 // Make sure that packet is large
1562 // enough to be IPv4.
1563 if (l_PacketLength
1564 < ETHERNET_HEADER_SIZE + IP_HEADER_SIZE)
1565 goto no_queue;
1567 // Only accept directed packets,
1568 // not broadcasts.
1569 if (memcmp (e, &l_Adapter->m_TapToUser, ETHERNET_HEADER_SIZE))
1570 goto no_queue;
1572 // Packet looks like IPv4, queue it.
1573 l_PacketBuffer->m_SizeFlags |= TP_TUN;
1577 //===============================================
1578 // Push packet onto queue to wait for read from
1579 // userspace.
1580 //===============================================
1582 NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
1584 result = NULL;
1585 if (IS_UP (l_Adapter))
1586 result = QueuePush (l_Adapter->m_Extension.m_PacketQueue, l_PacketBuffer);
1588 NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
1590 if ((TapPacketPointer) result != l_PacketBuffer)
1592 // adapter receive overrun
1593 INCREMENT_STAT (l_Adapter->m_TxErr);
1594 goto no_queue;
1596 else
1598 INCREMENT_STAT (l_Adapter->m_Tx);
1601 //============================================================
1602 // Cycle through IRPs and packets, try to satisfy each pending
1603 // IRP with a queued packet.
1604 //============================================================
1605 while (TRUE)
1607 l_IRP = NULL;
1608 l_PacketBuffer = NULL;
1610 NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
1612 if (IS_UP (l_Adapter)
1613 && QueueCount (l_Adapter->m_Extension.m_PacketQueue)
1614 && QueueCount (l_Adapter->m_Extension.m_IrpQueue))
1616 l_IRP = (PIRP) QueuePop (l_Adapter->m_Extension.m_IrpQueue);
1617 l_PacketBuffer = (TapPacketPointer)
1618 QueuePop (l_Adapter->m_Extension.m_PacketQueue);
1621 NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
1623 MYASSERT ((l_IRP != NULL) + (l_PacketBuffer != NULL) != 1);
1625 if (l_IRP && l_PacketBuffer)
1627 CompleteIRP (l_IRP,
1628 l_PacketBuffer,
1629 IO_NETWORK_INCREMENT);
1631 else
1632 break;
1635 __except (EXCEPTION_EXECUTE_HANDLER)
1639 return NDIS_STATUS_SUCCESS;
1641 no_queue:
1642 NdisFreeMemory (l_PacketBuffer,
1643 TAP_PACKET_SIZE (l_PacketLength),
1646 exit_success:
1647 return NDIS_STATUS_SUCCESS;
1649 exit_fail:
1650 return NDIS_STATUS_FAILURE;
1652 exit_no_resources:
1653 return NDIS_STATUS_RESOURCES;
1656 //======================================================================
1657 // Hooks for catching TAP device IRP's.
1658 //======================================================================
1660 NTSTATUS
1661 TapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject, IN PIRP p_IRP)
1663 TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject);
1664 PIO_STACK_LOCATION l_IrpSp;
1665 NTSTATUS l_Status = STATUS_SUCCESS;
1666 BOOLEAN accessible;
1668 l_IrpSp = IoGetCurrentIrpStackLocation (p_IRP);
1670 p_IRP->IoStatus.Status = STATUS_SUCCESS;
1671 p_IRP->IoStatus.Information = 0;
1673 if (!l_Adapter || l_Adapter->m_Extension.m_Halt)
1675 DEBUGP (("TapDeviceHook called when TAP device is halted, MajorFunction=%d\n",
1676 (int)l_IrpSp->MajorFunction));
1678 if (l_IrpSp->MajorFunction == IRP_MJ_CLOSE)
1680 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1681 return STATUS_SUCCESS;
1683 else
1685 p_IRP->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
1686 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1687 return STATUS_NO_SUCH_DEVICE;
1691 switch (l_IrpSp->MajorFunction)
1693 //===========================================================
1694 // Ioctl call handlers
1695 //===========================================================
1696 case IRP_MJ_DEVICE_CONTROL:
1698 switch (l_IrpSp->Parameters.DeviceIoControl.IoControlCode)
1700 case TAP_IOCTL_GET_MAC:
1702 if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
1703 >= sizeof (MACADDR))
1705 COPY_MAC (p_IRP->AssociatedIrp.SystemBuffer,
1706 l_Adapter->m_MAC);
1707 p_IRP->IoStatus.Information = sizeof (MACADDR);
1709 else
1711 NOTE_ERROR ();
1712 p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
1714 break;
1716 case TAP_IOCTL_GET_VERSION:
1718 const ULONG size = sizeof (ULONG) * 3;
1719 if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
1720 >= size)
1722 ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0]
1723 = TAP_DRIVER_MAJOR_VERSION;
1724 ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[1]
1725 = TAP_DRIVER_MINOR_VERSION;
1726 ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[2]
1727 #if DBG
1728 = 1;
1729 #else
1730 = 0;
1731 #endif
1732 p_IRP->IoStatus.Information = size;
1734 else
1736 NOTE_ERROR ();
1737 p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
1740 break;
1742 case TAP_IOCTL_GET_MTU:
1744 const ULONG size = sizeof (ULONG) * 1;
1745 if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
1746 >= size)
1748 ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0]
1749 = l_Adapter->m_MTU;
1750 p_IRP->IoStatus.Information = size;
1752 else
1754 NOTE_ERROR ();
1755 p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
1758 break;
1760 case TAP_IOCTL_GET_INFO:
1762 char state[16];
1763 if (l_Adapter->m_InterfaceIsRunning)
1764 state[0] = 'A';
1765 else
1766 state[0] = 'a';
1767 if (l_Adapter->m_Extension.m_TapIsRunning)
1768 state[1] = 'T';
1769 else
1770 state[1] = 't';
1771 state[2] = l_Adapter->m_DeviceState;
1772 if (l_Adapter->m_MediaStateAlwaysConnected)
1773 state[3] = 'C';
1774 else
1775 state[3] = 'c';
1776 state[4] = '\0';
1778 p_IRP->IoStatus.Status = l_Status = RtlStringCchPrintfExA (
1779 ((LPTSTR) (p_IRP->AssociatedIrp.SystemBuffer)),
1780 l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
1781 NULL,
1782 NULL,
1783 STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,
1784 #if PACKET_TRUNCATION_CHECK
1785 "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d,%d] Rx=[%d,%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d]",
1786 #else
1787 "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d] Rx=[%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d]",
1788 #endif
1789 state,
1790 g_LastErrorFilename,
1791 g_LastErrorLineNumber,
1792 (int)l_Adapter->m_Extension.m_NumTapOpens,
1793 (int)l_Adapter->m_Tx,
1794 (int)l_Adapter->m_TxErr,
1795 #if PACKET_TRUNCATION_CHECK
1796 (int)l_Adapter->m_TxTrunc,
1797 #endif
1798 (int)l_Adapter->m_Rx,
1799 (int)l_Adapter->m_RxErr,
1800 #if PACKET_TRUNCATION_CHECK
1801 (int)l_Adapter->m_RxTrunc,
1802 #endif
1803 (int)l_Adapter->m_Extension.m_IrpQueue->size,
1804 (int)l_Adapter->m_Extension.m_IrpQueue->max_size,
1805 (int)IRP_QUEUE_SIZE,
1806 (int)l_Adapter->m_Extension.m_PacketQueue->size,
1807 (int)l_Adapter->m_Extension.m_PacketQueue->max_size,
1808 (int)PACKET_QUEUE_SIZE
1811 p_IRP->IoStatus.Information
1812 = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1814 break;
1817 #if DBG
1818 case TAP_IOCTL_GET_LOG_LINE:
1820 if (GetDebugLine ((LPTSTR)p_IRP->AssociatedIrp.SystemBuffer,
1821 l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength))
1822 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
1823 else
1824 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
1826 p_IRP->IoStatus.Information
1827 = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1829 break;
1831 #endif
1833 case TAP_IOCTL_CONFIG_TUN:
1835 if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
1836 (sizeof (IPADDR) * 3))
1838 MACADDR dest;
1840 l_Adapter->m_tun = FALSE;
1842 GenerateRelatedMAC (dest, l_Adapter->m_MAC, 1);
1844 l_Adapter->m_localIP = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0];
1845 l_Adapter->m_remoteNetwork = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1];
1846 l_Adapter->m_remoteNetmask = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[2];
1848 // sanity check on network/netmask
1849 if ((l_Adapter->m_remoteNetwork & l_Adapter->m_remoteNetmask) != l_Adapter->m_remoteNetwork)
1851 NOTE_ERROR ();
1852 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1853 break;
1856 COPY_MAC (l_Adapter->m_TapToUser.src, l_Adapter->m_MAC);
1857 COPY_MAC (l_Adapter->m_TapToUser.dest, dest);
1858 COPY_MAC (l_Adapter->m_UserToTap.src, dest);
1859 COPY_MAC (l_Adapter->m_UserToTap.dest, l_Adapter->m_MAC);
1861 l_Adapter->m_TapToUser.proto = l_Adapter->m_UserToTap.proto = htons (ETH_P_IP);
1863 l_Adapter->m_tun = TRUE;
1865 CheckIfDhcpAndTunMode (l_Adapter);
1867 p_IRP->IoStatus.Information = 1; // Simple boolean value
1869 else
1871 NOTE_ERROR ();
1872 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1875 break;
1878 case TAP_IOCTL_CONFIG_POINT_TO_POINT: // Obsoleted by TAP_IOCTL_CONFIG_TUN
1880 if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
1881 (sizeof (IPADDR) * 2))
1883 MACADDR dest;
1885 l_Adapter->m_tun = FALSE;
1887 GenerateRelatedMAC (dest, l_Adapter->m_MAC, 1);
1889 l_Adapter->m_localIP = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0];
1890 l_Adapter->m_remoteNetwork = ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1];
1891 l_Adapter->m_remoteNetmask = ~0;
1893 COPY_MAC (l_Adapter->m_TapToUser.src, l_Adapter->m_MAC);
1894 COPY_MAC (l_Adapter->m_TapToUser.dest, dest);
1895 COPY_MAC (l_Adapter->m_UserToTap.src, dest);
1896 COPY_MAC (l_Adapter->m_UserToTap.dest, l_Adapter->m_MAC);
1898 l_Adapter->m_TapToUser.proto = l_Adapter->m_UserToTap.proto = htons (ETH_P_IP);
1900 l_Adapter->m_tun = TRUE;
1902 CheckIfDhcpAndTunMode (l_Adapter);
1904 p_IRP->IoStatus.Information = 1; // Simple boolean value
1906 else
1908 NOTE_ERROR ();
1909 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1912 break;
1915 case TAP_IOCTL_SET_MEDIA_STATUS:
1917 if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
1918 (sizeof (ULONG) * 1))
1920 ULONG parm = ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0];
1921 SetMediaStatus (l_Adapter, (BOOLEAN) parm);
1922 p_IRP->IoStatus.Information = 1;
1924 else
1926 NOTE_ERROR ();
1927 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1929 break;
1932 case TAP_IOCTL_CONFIG_DHCP_MASQ:
1934 if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
1935 (sizeof (IPADDR) * 4))
1937 l_Adapter->m_dhcp_enabled = FALSE;
1938 l_Adapter->m_dhcp_server_arp = FALSE;
1939 l_Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
1941 // Adapter IP addr / netmask
1942 l_Adapter->m_dhcp_addr =
1943 ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0];
1944 l_Adapter->m_dhcp_netmask =
1945 ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1];
1947 // IP addr of DHCP masq server
1948 l_Adapter->m_dhcp_server_ip =
1949 ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[2];
1951 // Lease time in seconds
1952 l_Adapter->m_dhcp_lease_time =
1953 ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[3];
1955 GenerateRelatedMAC (l_Adapter->m_dhcp_server_mac, l_Adapter->m_MAC, 2);
1957 l_Adapter->m_dhcp_enabled = TRUE;
1958 l_Adapter->m_dhcp_server_arp = TRUE;
1960 CheckIfDhcpAndTunMode (l_Adapter);
1962 p_IRP->IoStatus.Information = 1; // Simple boolean value
1964 else
1966 NOTE_ERROR ();
1967 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1970 break;
1973 case TAP_IOCTL_CONFIG_DHCP_SET_OPT:
1975 if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength <=
1976 DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE
1977 && l_Adapter->m_dhcp_enabled)
1979 l_Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
1981 NdisMoveMemory (l_Adapter->m_dhcp_user_supplied_options_buffer,
1982 p_IRP->AssociatedIrp.SystemBuffer,
1983 l_IrpSp->Parameters.DeviceIoControl.InputBufferLength);
1985 l_Adapter->m_dhcp_user_supplied_options_buffer_len =
1986 l_IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1988 p_IRP->IoStatus.Information = 1; // Simple boolean value
1990 else
1992 NOTE_ERROR ();
1993 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1996 break;
1999 default:
2001 NOTE_ERROR ();
2002 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
2003 break;
2007 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2008 break;
2011 //===========================================================
2012 // User mode thread issued a read request on the tap device
2013 // If there are packets waiting to be read, then the request
2014 // will be satisfied here. If not, then the request will be
2015 // queued and satisfied by any packet that is not used to
2016 // satisfy requests ahead of it.
2017 //===========================================================
2018 case IRP_MJ_READ:
2020 TapPacketPointer l_PacketBuffer;
2021 BOOLEAN pending = FALSE;
2023 // Save IRP-accessible copy of buffer length
2024 p_IRP->IoStatus.Information = l_IrpSp->Parameters.Read.Length;
2026 if (p_IRP->MdlAddress == NULL)
2028 DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_READ\n",
2029 NAME (l_Adapter)));
2030 NOTE_ERROR ();
2031 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
2032 p_IRP->IoStatus.Information = 0;
2033 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2034 break;
2036 else if ((p_IRP->AssociatedIrp.SystemBuffer =
2037 MmGetSystemAddressForMdlSafe
2038 (p_IRP->MdlAddress, NormalPagePriority)) == NULL)
2040 DEBUGP (("[%s] Could not map address in IRP_MJ_READ\n",
2041 NAME (l_Adapter)));
2042 NOTE_ERROR ();
2043 p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES;
2044 p_IRP->IoStatus.Information = 0;
2045 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2046 break;
2048 else if (!l_Adapter->m_InterfaceIsRunning)
2050 DEBUGP (("[%s] Interface is down in IRP_MJ_READ\n",
2051 NAME (l_Adapter)));
2052 NOTE_ERROR ();
2053 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2054 p_IRP->IoStatus.Information = 0;
2055 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2056 break;
2059 //==================================
2060 // Can we provide immediate service?
2061 //==================================
2063 l_PacketBuffer = NULL;
2065 NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
2067 if (IS_UP (l_Adapter)
2068 && QueueCount (l_Adapter->m_Extension.m_PacketQueue)
2069 && QueueCount (l_Adapter->m_Extension.m_IrpQueue) == 0)
2071 l_PacketBuffer = (TapPacketPointer)
2072 QueuePop (l_Adapter->m_Extension.m_PacketQueue);
2075 NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
2077 if (l_PacketBuffer)
2079 l_Status = CompleteIRP (p_IRP,
2080 l_PacketBuffer,
2081 IO_NO_INCREMENT);
2082 break;
2085 //=============================
2086 // Attempt to pend read request
2087 //=============================
2089 NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
2091 if (IS_UP (l_Adapter)
2092 && QueuePush (l_Adapter->m_Extension.m_IrpQueue, p_IRP) == (PIRP) p_IRP)
2094 IoSetCancelRoutine (p_IRP, CancelIRPCallback);
2095 l_Status = STATUS_PENDING;
2096 IoMarkIrpPending (p_IRP);
2097 pending = TRUE;
2100 NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
2102 if (pending)
2103 break;
2105 // Can't queue anymore IRP's
2106 DEBUGP (("[%s] TAP [%s] read IRP overrun\n",
2107 NAME (l_Adapter), l_Adapter->m_Extension.m_TapName));
2108 NOTE_ERROR ();
2109 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2110 p_IRP->IoStatus.Information = 0;
2111 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2112 break;
2115 //==============================================================
2116 // User mode issued a WriteFile request on the TAP file handle.
2117 // The request will always get satisfied here. The call may
2118 // fail if there are too many pending packets (queue full).
2119 //==============================================================
2120 case IRP_MJ_WRITE:
2122 if (p_IRP->MdlAddress == NULL)
2124 DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n",
2125 NAME (l_Adapter)));
2126 NOTE_ERROR ();
2127 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
2128 p_IRP->IoStatus.Information = 0;
2130 else if ((p_IRP->AssociatedIrp.SystemBuffer =
2131 MmGetSystemAddressForMdlSafe
2132 (p_IRP->MdlAddress, NormalPagePriority)) == NULL)
2134 DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n",
2135 NAME (l_Adapter)));
2136 NOTE_ERROR ();
2137 p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES;
2138 p_IRP->IoStatus.Information = 0;
2140 else if (!l_Adapter->m_InterfaceIsRunning)
2142 DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n",
2143 NAME (l_Adapter)));
2144 NOTE_ERROR ();
2145 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2146 p_IRP->IoStatus.Information = 0;
2148 else if (!l_Adapter->m_tun && ((l_IrpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE))
2150 __try
2152 p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length;
2154 DUMP_PACKET ("IRP_MJ_WRITE ETH",
2155 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2156 l_IrpSp->Parameters.Write.Length);
2158 //=====================================================
2159 // If IPv4 packet, check whether or not packet
2160 // was truncated.
2161 //=====================================================
2162 #if PACKET_TRUNCATION_CHECK
2163 IPv4PacketSizeVerify ((unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2164 l_IrpSp->Parameters.Write.Length,
2165 FALSE,
2166 "RX",
2167 &l_Adapter->m_RxTrunc);
2168 #endif
2170 NdisMEthIndicateReceive
2171 (l_Adapter->m_MiniportAdapterHandle,
2172 (NDIS_HANDLE) l_Adapter,
2173 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2174 ETHERNET_HEADER_SIZE,
2175 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer + ETHERNET_HEADER_SIZE,
2176 l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE,
2177 l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE);
2179 NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle);
2181 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2183 __except (EXCEPTION_EXECUTE_HANDLER)
2185 DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE\n",
2186 NAME (l_Adapter)));
2187 NOTE_ERROR ();
2188 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2189 p_IRP->IoStatus.Information = 0;
2192 else if (l_Adapter->m_tun && ((l_IrpSp->Parameters.Write.Length) >= IP_HEADER_SIZE))
2194 __try
2196 p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length;
2198 DUMP_PACKET2 ("IRP_MJ_WRITE P2P",
2199 &l_Adapter->m_UserToTap,
2200 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2201 l_IrpSp->Parameters.Write.Length);
2203 //=====================================================
2204 // If IPv4 packet, check whether or not packet
2205 // was truncated.
2206 //=====================================================
2207 #if PACKET_TRUNCATION_CHECK
2208 IPv4PacketSizeVerify ((unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2209 l_IrpSp->Parameters.Write.Length,
2210 TRUE,
2211 "RX",
2212 &l_Adapter->m_RxTrunc);
2213 #endif
2215 NdisMEthIndicateReceive
2216 (l_Adapter->m_MiniportAdapterHandle,
2217 (NDIS_HANDLE) l_Adapter,
2218 (unsigned char *) &l_Adapter->m_UserToTap,
2219 sizeof (l_Adapter->m_UserToTap),
2220 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2221 l_IrpSp->Parameters.Write.Length,
2222 l_IrpSp->Parameters.Write.Length);
2224 NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle);
2226 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2228 __except (EXCEPTION_EXECUTE_HANDLER)
2230 DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE (P2P)\n",
2231 NAME (l_Adapter)));
2232 NOTE_ERROR ();
2233 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2234 p_IRP->IoStatus.Information = 0;
2237 else
2239 DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n",
2240 NAME (l_Adapter),
2241 l_IrpSp->Parameters.Write.Length));
2242 NOTE_ERROR ();
2243 p_IRP->IoStatus.Information = 0; // ETHERNET_HEADER_SIZE;
2244 p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
2247 if (l_Status == STATUS_SUCCESS)
2248 INCREMENT_STAT (l_Adapter->m_Rx);
2249 else
2250 INCREMENT_STAT (l_Adapter->m_RxErr);
2252 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2253 break;
2256 //--------------------------------------------------------------
2257 // User mode thread has called CreateFile() on the tap device
2258 //--------------------------------------------------------------
2259 case IRP_MJ_CREATE:
2261 BOOLEAN succeeded = FALSE;
2262 BOOLEAN mutex_succeeded;
2264 DEBUGP
2265 (("[%s] [TAP] release [%d.%d] open request (m_TapOpens=%d)\n",
2266 NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION,
2267 TAP_DRIVER_MINOR_VERSION, l_Adapter->m_Extension.m_TapOpens));
2269 ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded);
2270 if (mutex_succeeded)
2272 if (l_Adapter->m_Extension.m_TapIsRunning && !l_Adapter->m_Extension.m_TapOpens)
2274 ResetTapAdapterState (l_Adapter);
2275 l_Adapter->m_Extension.m_TapOpens = 1;
2276 succeeded = TRUE;
2279 if (succeeded)
2281 INCREMENT_STAT (l_Adapter->m_Extension.m_NumTapOpens);
2282 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2283 p_IRP->IoStatus.Information = 0;
2285 else
2287 DEBUGP (("[%s] TAP is presently unavailable (m_TapOpens=%d)\n",
2288 NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
2289 NOTE_ERROR ();
2290 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2291 p_IRP->IoStatus.Information = 0;
2294 RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex);
2296 else
2298 DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
2299 NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
2300 NOTE_ERROR ();
2301 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2302 p_IRP->IoStatus.Information = 0;
2305 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2306 break;
2309 //-----------------------------------------------------------
2310 // User mode thread called CloseHandle() on the tap device
2311 //-----------------------------------------------------------
2312 case IRP_MJ_CLOSE:
2314 BOOLEAN mutex_succeeded;
2316 DEBUGP (("[%s] [TAP] release [%d.%d] close/cleanup request\n",
2317 NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION,
2318 TAP_DRIVER_MINOR_VERSION));
2320 ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded);
2321 if (mutex_succeeded)
2323 l_Adapter->m_Extension.m_TapOpens = 0;
2324 ResetTapAdapterState (l_Adapter);
2325 FlushQueues (&l_Adapter->m_Extension);
2326 SetMediaStatus (l_Adapter, FALSE);
2327 RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex);
2329 else
2331 DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
2332 NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
2333 NOTE_ERROR ();
2334 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2335 p_IRP->IoStatus.Information = 0;
2338 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2339 break;
2342 //------------------
2343 // Strange Request
2344 //------------------
2345 default:
2347 //NOTE_ERROR ();
2348 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2349 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2350 break;
2354 return l_Status;
2357 //=============================================================
2358 // CompleteIRP is normally called with an adapter -> userspace
2359 // network packet and an IRP (Pending I/O request) from userspace.
2361 // The IRP will normally represent a queued overlapped read
2362 // operation from userspace that is in a wait state.
2364 // Use the ethernet packet to satisfy the IRP.
2365 //=============================================================
2367 NTSTATUS
2368 CompleteIRP (IN PIRP p_IRP,
2369 IN TapPacketPointer p_PacketBuffer,
2370 IN CCHAR PriorityBoost)
2372 NTSTATUS l_Status = STATUS_UNSUCCESSFUL;
2374 int offset;
2375 int len;
2377 MYASSERT (p_IRP);
2378 MYASSERT (p_PacketBuffer);
2380 IoSetCancelRoutine (p_IRP, NULL); // Disable cancel routine
2382 //-------------------------------------------
2383 // While p_PacketBuffer always contains a
2384 // full ethernet packet, including the
2385 // ethernet header, in point-to-point mode,
2386 // we only want to return the IPv4
2387 // component.
2388 //-------------------------------------------
2390 if (p_PacketBuffer->m_SizeFlags & TP_TUN)
2392 offset = ETHERNET_HEADER_SIZE;
2393 len = (int) (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK) - ETHERNET_HEADER_SIZE;
2395 else
2397 offset = 0;
2398 len = (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK);
2401 if (len < 0 || (int) p_IRP->IoStatus.Information < len)
2403 p_IRP->IoStatus.Information = 0;
2404 p_IRP->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
2405 NOTE_ERROR ();
2407 else
2409 p_IRP->IoStatus.Information = len;
2410 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2412 __try
2414 NdisMoveMemory (p_IRP->AssociatedIrp.SystemBuffer,
2415 p_PacketBuffer->m_Data + offset,
2416 len);
2418 __except (EXCEPTION_EXECUTE_HANDLER)
2420 NOTE_ERROR ();
2421 p_IRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
2422 p_IRP->IoStatus.Information = 0;
2426 __try
2428 NdisFreeMemory (p_PacketBuffer,
2429 TAP_PACKET_SIZE (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK),
2432 __except (EXCEPTION_EXECUTE_HANDLER)
2436 if (l_Status == STATUS_SUCCESS)
2438 IoCompleteRequest (p_IRP, PriorityBoost);
2440 else
2441 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2443 return l_Status;
2446 //==============================================
2447 // IRPs get cancelled for a number of reasons.
2449 // The TAP device could be closed by userspace
2450 // when there are still pending read operations.
2452 // The user could disable the TAP adapter in the
2453 // network connections control panel, while the
2454 // device is still open by a process.
2455 //==============================================
2456 VOID
2457 CancelIRPCallback (IN PDEVICE_OBJECT p_DeviceObject,
2458 IN PIRP p_IRP)
2460 TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject);
2461 CancelIRP (l_Adapter ? &l_Adapter->m_Extension : NULL, p_IRP, TRUE);
2464 VOID
2465 CancelIRP (TapExtensionPointer p_Extension,
2466 IN PIRP p_IRP,
2467 BOOLEAN callback)
2469 BOOLEAN exists = FALSE;
2471 MYASSERT (p_IRP);
2473 if (p_Extension)
2475 NdisAcquireSpinLock (&p_Extension->m_QueueLock);
2476 exists = (QueueExtract (p_Extension->m_IrpQueue, p_IRP) == p_IRP);
2477 NdisReleaseSpinLock (&p_Extension->m_QueueLock);
2479 else
2480 exists = TRUE;
2482 if (exists)
2484 IoSetCancelRoutine (p_IRP, NULL);
2485 p_IRP->IoStatus.Status = STATUS_CANCELLED;
2486 p_IRP->IoStatus.Information = 0;
2489 if (callback)
2490 IoReleaseCancelSpinLock (p_IRP->CancelIrql);
2492 if (exists)
2493 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2496 //====================================
2497 // Exhaust packet and IRP queues.
2498 //====================================
2499 VOID
2500 FlushQueues (TapExtensionPointer p_Extension)
2502 PIRP l_IRP;
2503 TapPacketPointer l_PacketBuffer;
2504 int n_IRP=0, n_Packet=0;
2506 MYASSERT (p_Extension);
2507 MYASSERT (p_Extension->m_TapDevice);
2509 while (TRUE)
2511 NdisAcquireSpinLock (&p_Extension->m_QueueLock);
2512 l_IRP = QueuePop (p_Extension->m_IrpQueue);
2513 NdisReleaseSpinLock (&p_Extension->m_QueueLock);
2514 if (l_IRP)
2516 ++n_IRP;
2517 CancelIRP (NULL, l_IRP, FALSE);
2519 else
2520 break;
2523 while (TRUE)
2525 NdisAcquireSpinLock (&p_Extension->m_QueueLock);
2526 l_PacketBuffer = QueuePop (p_Extension->m_PacketQueue);
2527 NdisReleaseSpinLock (&p_Extension->m_QueueLock);
2528 if (l_PacketBuffer)
2530 ++n_Packet;
2531 MemFree (l_PacketBuffer, TAP_PACKET_SIZE (l_PacketBuffer->m_SizeFlags & TP_SIZE_MASK));
2533 else
2534 break;
2537 DEBUGP ((
2538 "[%s] [TAP] FlushQueues n_IRP=[%d,%d,%d] n_Packet=[%d,%d,%d]\n",
2539 p_Extension->m_TapName,
2540 n_IRP,
2541 p_Extension->m_IrpQueue->max_size,
2542 IRP_QUEUE_SIZE,
2543 n_Packet,
2544 p_Extension->m_PacketQueue->max_size,
2545 PACKET_QUEUE_SIZE
2549 //===================================================
2550 // Tell Windows whether the TAP device should be
2551 // considered "connected" or "disconnected".
2552 //===================================================
2553 VOID
2554 SetMediaStatus (TapAdapterPointer p_Adapter, BOOLEAN state)
2556 if (p_Adapter->m_MediaState != state && !p_Adapter->m_MediaStateAlwaysConnected)
2558 if (state)
2559 NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle,
2560 NDIS_STATUS_MEDIA_CONNECT, NULL, 0);
2561 else
2562 NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle,
2563 NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0);
2565 NdisMIndicateStatusComplete (p_Adapter->m_MiniportAdapterHandle);
2566 p_Adapter->m_MediaState = state;
2571 //======================================================
2572 // If DHCP mode is used together with tun
2573 // mode, consider the fact that the P2P remote subnet
2574 // might enclose the DHCP masq server address.
2575 //======================================================
2576 VOID
2577 CheckIfDhcpAndTunMode (TapAdapterPointer p_Adapter)
2579 if (p_Adapter->m_tun && p_Adapter->m_dhcp_enabled)
2581 if ((p_Adapter->m_dhcp_server_ip & p_Adapter->m_remoteNetmask) == p_Adapter->m_remoteNetwork)
2583 COPY_MAC (p_Adapter->m_dhcp_server_mac, p_Adapter->m_TapToUser.dest);
2584 p_Adapter->m_dhcp_server_arp = FALSE;
2589 //===================================================
2590 // Generate an ARP reply message for specific kinds
2591 // ARP queries.
2592 //===================================================
2593 BOOLEAN
2594 ProcessARP (TapAdapterPointer p_Adapter,
2595 const PARP_PACKET src,
2596 const IPADDR adapter_ip,
2597 const IPADDR ip_network,
2598 const IPADDR ip_netmask,
2599 const MACADDR mac)
2601 //-----------------------------------------------
2602 // Is this the kind of packet we are looking for?
2603 //-----------------------------------------------
2604 if (src->m_Proto == htons (ETH_P_ARP)
2605 && MAC_EQUAL (src->m_MAC_Source, p_Adapter->m_MAC)
2606 && MAC_EQUAL (src->m_ARP_MAC_Source, p_Adapter->m_MAC)
2607 && MAC_EQUAL (src->m_MAC_Destination, p_Adapter->m_MAC_Broadcast)
2608 && src->m_ARP_Operation == htons (ARP_REQUEST)
2609 && src->m_MAC_AddressType == htons (MAC_ADDR_TYPE)
2610 && src->m_MAC_AddressSize == sizeof (MACADDR)
2611 && src->m_PROTO_AddressType == htons (ETH_P_IP)
2612 && src->m_PROTO_AddressSize == sizeof (IPADDR)
2613 && src->m_ARP_IP_Source == adapter_ip
2614 && (src->m_ARP_IP_Destination & ip_netmask) == ip_network
2615 && src->m_ARP_IP_Destination != adapter_ip)
2617 ARP_PACKET *arp = (ARP_PACKET *) MemAlloc (sizeof (ARP_PACKET), TRUE);
2618 if (arp)
2620 //----------------------------------------------
2621 // Initialize ARP reply fields
2622 //----------------------------------------------
2623 arp->m_Proto = htons (ETH_P_ARP);
2624 arp->m_MAC_AddressType = htons (MAC_ADDR_TYPE);
2625 arp->m_PROTO_AddressType = htons (ETH_P_IP);
2626 arp->m_MAC_AddressSize = sizeof (MACADDR);
2627 arp->m_PROTO_AddressSize = sizeof (IPADDR);
2628 arp->m_ARP_Operation = htons (ARP_REPLY);
2630 //----------------------------------------------
2631 // ARP addresses
2632 //----------------------------------------------
2633 COPY_MAC (arp->m_MAC_Source, mac);
2634 COPY_MAC (arp->m_MAC_Destination, p_Adapter->m_MAC);
2635 COPY_MAC (arp->m_ARP_MAC_Source, mac);
2636 COPY_MAC (arp->m_ARP_MAC_Destination, p_Adapter->m_MAC);
2637 arp->m_ARP_IP_Source = src->m_ARP_IP_Destination;
2638 arp->m_ARP_IP_Destination = adapter_ip;
2640 DUMP_PACKET ("ProcessARP",
2641 (unsigned char *) arp,
2642 sizeof (ARP_PACKET));
2644 InjectPacket (p_Adapter, (UCHAR *) arp, sizeof (ARP_PACKET));
2646 MemFree (arp, sizeof (ARP_PACKET));
2649 return TRUE;
2651 else
2652 return FALSE;
2655 //===============================================================
2656 // Used in cases where internally generated packets such as
2657 // ARP or DHCP replies must be returned to the kernel, to be
2658 // seen as an incoming packet "arriving" on the interface.
2659 //===============================================================
2661 VOID
2662 InjectPacket (TapAdapterPointer p_Adapter,
2663 UCHAR *packet,
2664 const unsigned int len)
2666 MYASSERT (len >= ETHERNET_HEADER_SIZE);
2668 __try
2670 //------------------------------------------------------------
2671 // NdisMEthIndicateReceive and NdisMEthIndicateReceiveComplete
2672 // could potentially be called reentrantly both here and in
2673 // TapDeviceHook/IRP_MJ_WRITE.
2675 // The DDK docs imply that this is okay.
2676 //------------------------------------------------------------
2677 NdisMEthIndicateReceive
2678 (p_Adapter->m_MiniportAdapterHandle,
2679 (NDIS_HANDLE) p_Adapter,
2680 packet,
2681 ETHERNET_HEADER_SIZE,
2682 packet + ETHERNET_HEADER_SIZE,
2683 len - ETHERNET_HEADER_SIZE,
2684 len - ETHERNET_HEADER_SIZE);
2686 NdisMEthIndicateReceiveComplete (p_Adapter->m_MiniportAdapterHandle);
2688 __except (EXCEPTION_EXECUTE_HANDLER)
2690 DEBUGP (("[%s] NdisMEthIndicateReceive failed in InjectPacket\n",
2691 NAME (p_Adapter)));
2692 NOTE_ERROR ();
2696 //===================================================================
2697 // Go back to default TAP mode from Point-To-Point mode.
2698 // Also reset (i.e. disable) DHCP Masq mode.
2699 //===================================================================
2700 VOID ResetTapAdapterState (TapAdapterPointer p_Adapter)
2702 // Point-To-Point
2703 p_Adapter->m_tun = FALSE;
2704 p_Adapter->m_localIP = 0;
2705 p_Adapter->m_remoteNetwork = 0;
2706 p_Adapter->m_remoteNetmask = 0;
2707 NdisZeroMemory (&p_Adapter->m_TapToUser, sizeof (p_Adapter->m_TapToUser));
2708 NdisZeroMemory (&p_Adapter->m_UserToTap, sizeof (p_Adapter->m_UserToTap));
2710 // DHCP Masq
2711 p_Adapter->m_dhcp_enabled = FALSE;
2712 p_Adapter->m_dhcp_server_arp = FALSE;
2713 p_Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
2714 p_Adapter->m_dhcp_addr = 0;
2715 p_Adapter->m_dhcp_netmask = 0;
2716 p_Adapter->m_dhcp_server_ip = 0;
2717 p_Adapter->m_dhcp_lease_time = 0;
2718 p_Adapter->m_dhcp_received_discover = FALSE;
2719 p_Adapter->m_dhcp_bad_requests = 0;
2720 NdisZeroMemory (p_Adapter->m_dhcp_server_mac, sizeof (MACADDR));
2723 #if ENABLE_NONADMIN
2725 //===================================================================
2726 // Set TAP device handle to be accessible without admin privileges.
2727 //===================================================================
2728 VOID AllowNonAdmin (TapExtensionPointer p_Extension)
2730 NTSTATUS stat;
2731 SECURITY_DESCRIPTOR sd;
2732 OBJECT_ATTRIBUTES oa;
2733 IO_STATUS_BLOCK isb;
2734 HANDLE hand = NULL;
2736 NdisZeroMemory (&sd, sizeof (sd));
2737 NdisZeroMemory (&oa, sizeof (oa));
2738 NdisZeroMemory (&isb, sizeof (isb));
2740 if (!p_Extension->m_CreatedUnicodeLinkName)
2742 DEBUGP (("[TAP] AllowNonAdmin: UnicodeLinkName is uninitialized\n"));
2743 NOTE_ERROR ();
2744 return;
2747 stat = RtlCreateSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
2748 if (stat != STATUS_SUCCESS)
2750 DEBUGP (("[TAP] AllowNonAdmin: RtlCreateSecurityDescriptor failed\n"));
2751 NOTE_ERROR ();
2752 return;
2755 InitializeObjectAttributes (
2756 &oa,
2757 &p_Extension->m_UnicodeLinkName,
2758 OBJ_KERNEL_HANDLE,
2759 NULL,
2760 NULL
2763 stat = ZwOpenFile (
2764 &hand,
2765 WRITE_DAC,
2766 &oa,
2767 &isb,
2771 if (stat != STATUS_SUCCESS)
2773 DEBUGP (("[TAP] AllowNonAdmin: ZwOpenFile failed, status=0x%08x\n", (unsigned int)stat));
2774 NOTE_ERROR ();
2775 return;
2778 stat = ZwSetSecurityObject (hand, DACL_SECURITY_INFORMATION, &sd);
2779 if (stat != STATUS_SUCCESS)
2781 DEBUGP (("[TAP] AllowNonAdmin: ZwSetSecurityObject failed\n"));
2782 NOTE_ERROR ();
2783 return;
2786 stat = ZwClose (hand);
2787 if (stat != STATUS_SUCCESS)
2789 DEBUGP (("[TAP] AllowNonAdmin: ZwClose failed\n"));
2790 NOTE_ERROR ();
2791 return;
2794 DEBUGP (("[TAP] AllowNonAdmin: SUCCEEDED\n"));
2797 #endif
2799 #if PACKET_TRUNCATION_CHECK
2801 VOID
2802 IPv4PacketSizeVerify (const UCHAR *data, ULONG length, BOOLEAN tun, const char *prefix, LONG *counter)
2804 const IPHDR *ip;
2805 int len = length;
2807 if (tun)
2809 ip = (IPHDR *) data;
2811 else
2813 if (length >= sizeof (ETH_HEADER))
2815 const ETH_HEADER *eth = (ETH_HEADER *) data;
2817 if (eth->proto != htons (ETH_P_IP))
2818 return;
2820 ip = (IPHDR *) (data + sizeof (ETH_HEADER));
2821 len -= sizeof (ETH_HEADER);
2823 else
2824 return;
2827 if (len >= sizeof (IPHDR))
2829 const int totlen = ntohs (ip->tot_len);
2831 DEBUGP (("[TAP] IPv4PacketSizeVerify %s len=%d totlen=%d\n", prefix, len, totlen));
2833 if (len != totlen)
2834 ++(*counter);
2838 #endif
2840 //======================================================================
2841 // End of Source
2842 //======================================================================