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