VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxTAP/tapdrvr.c@ 772

Last change on this file since 772 was 555, checked in by vboxsync, 18 years ago

TAP interface update (TAP_IOCTL_TRANSFER_ETHPACKETS)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 77.5 KB
Line 
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.
6 *
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).
10 *
11 * All other source code is Copyright (C) 2002-2005 OpenVPN Solutions LLC,
12 * and is released under the GPL version 2 (see below).
13 *
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.
17 *
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.
22 *
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
27 */
28
29//======================================================
30// This driver is designed to work on Win 2000 or higher
31// versions of Windows.
32//
33// It is SMP-safe and handles NDIS 5 power management.
34//
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 ioctl.
39//======================================================
40
41#define NDIS_MINIPORT_DRIVER
42#define BINARY_COMPATIBLE 0
43#define NDIS50_MINIPORT 1
44#define NDIS_WDM 0
45#define NDIS50 1
46#define NTSTRSAFE_LIB
47
48// Debug info output
49#define ALSO_DBGPRINT 1
50#define DEBUGP_AT_DISPATCH 0
51
52#include <ndis.h>
53#include <ntstrsafe.h>
54
55#include "lock.h"
56#include "constants.h"
57#include "common.h"
58#include "proto.h"
59#include "error.h"
60#include "endian.h"
61#include "dhcp.h"
62#include "types.h"
63#include "prototypes.h"
64
65#include "mem.c"
66#include "macinfo.c"
67#include "error.c"
68#include "dhcp.c"
69#include "instance.c"
70
71#ifdef VBOX
72#include <VBox/tapwin32.h>
73#endif
74
75#define IS_UP(ta) \
76 ((ta)->m_InterfaceIsRunning && (ta)->m_Extension.m_TapIsRunning)
77
78#define INCREMENT_STAT(s) ++(s)
79
80#define NAME_BUFFER_SIZE 80
81
82//========================================================
83// Globals
84//========================================================
85
86NDIS_HANDLE g_NdisWrapperHandle;
87
88const UINT g_SupportedOIDList[] = {
89 OID_GEN_HARDWARE_STATUS,
90 OID_GEN_MEDIA_SUPPORTED,
91 OID_GEN_MEDIA_IN_USE,
92 OID_GEN_MAXIMUM_LOOKAHEAD,
93 OID_GEN_MAC_OPTIONS,
94 OID_GEN_LINK_SPEED,
95 OID_GEN_TRANSMIT_BLOCK_SIZE,
96 OID_GEN_RECEIVE_BLOCK_SIZE,
97 OID_GEN_VENDOR_DESCRIPTION,
98 OID_GEN_DRIVER_VERSION,
99 OID_GEN_XMIT_OK,
100 OID_GEN_RCV_OK,
101 OID_GEN_XMIT_ERROR,
102 OID_GEN_RCV_ERROR,
103 OID_802_3_PERMANENT_ADDRESS,
104 OID_802_3_CURRENT_ADDRESS,
105 OID_GEN_RCV_NO_BUFFER,
106 OID_802_3_RCV_ERROR_ALIGNMENT,
107 OID_802_3_XMIT_ONE_COLLISION,
108 OID_802_3_XMIT_MORE_COLLISIONS,
109 OID_802_3_MULTICAST_LIST,
110 OID_802_3_MAXIMUM_LIST_SIZE,
111 OID_GEN_VENDOR_ID,
112 OID_GEN_CURRENT_LOOKAHEAD,
113 OID_GEN_CURRENT_PACKET_FILTER,
114 OID_GEN_PROTOCOL_OPTIONS,
115 OID_GEN_MAXIMUM_TOTAL_SIZE,
116 OID_GEN_TRANSMIT_BUFFER_SPACE,
117 OID_GEN_RECEIVE_BUFFER_SPACE,
118 OID_GEN_MAXIMUM_FRAME_SIZE,
119 OID_GEN_VENDOR_DRIVER_VERSION,
120 OID_GEN_MAXIMUM_SEND_PACKETS,
121 OID_GEN_MEDIA_CONNECT_STATUS,
122 OID_GEN_SUPPORTED_LIST
123};
124
125//============================================================
126// Driver Entry
127//============================================================
128#pragma NDIS_INIT_FUNCTION (DriverEntry)
129
130NTSTATUS
131DriverEntry (IN PDRIVER_OBJECT p_DriverObject,
132 IN PUNICODE_STRING p_RegistryPath)
133{
134 NDIS_STATUS l_Status = NDIS_STATUS_FAILURE;
135 NDIS_MINIPORT_CHARACTERISTICS *l_Properties = NULL;
136
137 //========================================================
138 // Notify NDIS that a new miniport driver is initializing.
139 //========================================================
140
141 NdisMInitializeWrapper (&g_NdisWrapperHandle,
142 p_DriverObject,
143 p_RegistryPath, NULL);
144
145 //======================
146 // Global initialization
147 //======================
148
149#if DBG
150 MyDebugInit (10000); // Allocate debugging text space
151#endif
152
153 if (!InitInstanceList ())
154 {
155 DEBUGP (("[TAP] Allocation failed for adapter instance list\n"));
156 goto cleanup;
157 }
158
159 //=======================================
160 // Set and register miniport entry points
161 //=======================================
162
163 l_Properties = MemAlloc (sizeof (NDIS_MINIPORT_CHARACTERISTICS), TRUE);
164
165 if (l_Properties == NULL)
166 {
167 DEBUGP (("[TAP] Allocation failed for miniport entry points\n"));
168 goto cleanup;
169 }
170
171 l_Properties->MajorNdisVersion = TAP_NDIS_MAJOR_VERSION;
172 l_Properties->MinorNdisVersion = TAP_NDIS_MINOR_VERSION;
173 l_Properties->InitializeHandler = AdapterCreate;
174 l_Properties->HaltHandler = AdapterHalt;
175 l_Properties->ResetHandler = AdapterReset; /* DISPATCH_LEVEL */
176 l_Properties->TransferDataHandler = AdapterReceive; /* DISPATCH_LEVEL */
177 l_Properties->SendHandler = AdapterTransmit; /* DISPATCH_LEVEL */
178 l_Properties->QueryInformationHandler = AdapterQuery; /* DISPATCH_LEVEL */
179 l_Properties->SetInformationHandler = AdapterModify; /* DISPATCH_LEVEL */
180
181 switch (l_Status =
182 NdisMRegisterMiniport (g_NdisWrapperHandle, l_Properties,
183 sizeof (NDIS_MINIPORT_CHARACTERISTICS)))
184 {
185 case NDIS_STATUS_SUCCESS:
186 {
187 DEBUGP (("[TAP] version [%d.%d] %s %s registered miniport successfully\n",
188 TAP_DRIVER_MAJOR_VERSION,
189 TAP_DRIVER_MINOR_VERSION,
190 __DATE__,
191 __TIME__));
192 DEBUGP (("Registry Path: '%S'\n", p_RegistryPath->Buffer));
193 break;
194 }
195
196 case NDIS_STATUS_BAD_CHARACTERISTICS:
197 {
198 DEBUGP (("[TAP] Miniport characteristics were badly defined\n"));
199 NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
200 break;
201 }
202
203 case NDIS_STATUS_BAD_VERSION:
204 {
205 DEBUGP
206 (("[TAP] NDIS Version is wrong for the given characteristics\n"));
207 NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
208 break;
209 }
210
211 case NDIS_STATUS_RESOURCES:
212 {
213 DEBUGP (("[TAP] Insufficient resources\n"));
214 NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
215 break;
216 }
217
218 default:
219 case NDIS_STATUS_FAILURE:
220 {
221 DEBUGP (("[TAP] Unknown fatal registration error\n"));
222 NdisTerminateWrapper (g_NdisWrapperHandle, NULL);
223 break;
224 }
225 }
226
227 cleanup:
228 if (l_Properties)
229 MemFree (l_Properties, sizeof (NDIS_MINIPORT_CHARACTERISTICS));
230
231 if (l_Status == NDIS_STATUS_SUCCESS)
232 NdisMRegisterUnloadHandler (g_NdisWrapperHandle, TapDriverUnload);
233 else
234 TapDriverUnload (p_DriverObject);
235
236 return l_Status;
237}
238
239//============================================================
240// Driver Unload
241//============================================================
242VOID
243TapDriverUnload (IN PDRIVER_OBJECT p_DriverObject)
244{
245 DEBUGP (("[TAP] version [%d.%d] %s %s unloaded, instances=%d, imbs=%d\n",
246 TAP_DRIVER_MAJOR_VERSION,
247 TAP_DRIVER_MINOR_VERSION,
248 __DATE__,
249 __TIME__,
250 NInstances(),
251 InstanceMaxBucketSize()));
252
253 FreeInstanceList ();
254
255 //==============================
256 // Free debugging text space
257 //==============================
258#if DBG
259 MyDebugFree ();
260#endif
261}
262
263//==========================================================
264// Adapter Initialization
265//==========================================================
266NDIS_STATUS AdapterCreate
267 (OUT PNDIS_STATUS p_ErrorStatus,
268 OUT PUINT p_MediaIndex,
269 IN PNDIS_MEDIUM p_Media,
270 IN UINT p_MediaCount,
271 IN NDIS_HANDLE p_AdapterHandle,
272 IN NDIS_HANDLE p_ConfigurationHandle)
273{
274 TapAdapterPointer l_Adapter = NULL;
275
276 NDIS_MEDIUM l_PreferredMedium = NdisMedium802_3; // Ethernet
277 BOOLEAN l_MacFromRegistry = FALSE;
278 UINT l_Index;
279 NDIS_STATUS status;
280
281 //====================================
282 // Make sure adapter type is supported
283 //====================================
284
285 for (l_Index = 0;
286 l_Index < p_MediaCount && p_Media[l_Index] != l_PreferredMedium;
287 ++l_Index);
288
289 if (l_Index == p_MediaCount)
290 {
291 DEBUGP (("[TAP] Unsupported adapter type [wanted: %d]\n",
292 l_PreferredMedium));
293 return NDIS_STATUS_UNSUPPORTED_MEDIA;
294 }
295
296 *p_MediaIndex = l_Index;
297
298 //=========================================
299 // Allocate memory for TapAdapter structure
300 //=========================================
301
302 l_Adapter = MemAlloc (sizeof (TapAdapter), TRUE);
303
304 if (l_Adapter == NULL)
305 {
306 DEBUGP (("[TAP] Couldn't allocate adapter memory\n"));
307 return NDIS_STATUS_RESOURCES;
308 }
309
310 //==========================================
311 // Inform the NDIS library about significant
312 // features of our virtual NIC.
313 //==========================================
314
315 NdisMSetAttributesEx
316 (p_AdapterHandle,
317 (NDIS_HANDLE) l_Adapter,
318 16,
319 NDIS_ATTRIBUTE_DESERIALIZE
320 | NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT
321 | NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT
322 | NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
323 NdisInterfaceInternal);
324
325 //=====================================
326 // Initialize simple Adapter parameters
327 //=====================================
328
329 l_Adapter->m_Lookahead = DEFAULT_PACKET_LOOKAHEAD;
330 l_Adapter->m_Medium = l_PreferredMedium;
331 l_Adapter->m_DeviceState = '?';
332 l_Adapter->m_MiniportAdapterHandle = p_AdapterHandle;
333
334 //==================================
335 // Allocate spinlock for controlling
336 // access to multicast address list.
337 //==================================
338 NdisAllocateSpinLock (&l_Adapter->m_MCLock);
339 l_Adapter->m_MCLockAllocated = TRUE;
340
341 //====================================================
342 // Register a shutdown handler which will be called
343 // on system restart/shutdown to halt our virtual NIC.
344 //====================================================
345
346 NdisMRegisterAdapterShutdownHandler (p_AdapterHandle, l_Adapter,
347 AdapterHalt);
348 l_Adapter->m_RegisteredAdapterShutdownHandler = TRUE;
349
350 //============================================
351 // Get parameters from registry which were set
352 // in the adapter advanced properties dialog.
353 //============================================
354 {
355 NDIS_STATUS status;
356 NDIS_HANDLE configHandle;
357 NDIS_CONFIGURATION_PARAMETER *parm;
358
359 // set defaults in case our registry query fails
360 l_Adapter->m_MTU = ETHERNET_MTU;
361 l_Adapter->m_MediaStateAlwaysConnected = FALSE;
362 l_Adapter->m_MediaState = FALSE;
363
364 NdisOpenConfiguration (&status, &configHandle, p_ConfigurationHandle);
365 if (status != NDIS_STATUS_SUCCESS)
366 {
367 DEBUGP (("[TAP] Couldn't open adapter registry\n"));
368 AdapterFreeResources (l_Adapter);
369 return status;
370 }
371
372 //====================================
373 // Allocate and construct adapter name
374 //====================================
375 {
376 NDIS_STRING key = NDIS_STRING_CONST("MiniportName");
377 NdisReadConfiguration (&status, &parm, configHandle, &key, NdisParameterString);
378 if (status == NDIS_STATUS_SUCCESS)
379 {
380 if (parm->ParameterType == NdisParameterString)
381 {
382 DEBUGP (("[TAP] NdisReadConfiguration (MiniportName=%s)\n", parm->ParameterData.StringData.Buffer));
383
384 if (RtlUnicodeStringToAnsiString (
385 &l_Adapter->m_NameAnsi,
386 &parm->ParameterData.StringData,
387 TRUE) != STATUS_SUCCESS)
388 {
389 DEBUGP (("[TAP] RtlUnicodeStringToAnsiString MiniportName failed\n"));
390 status = NDIS_STATUS_RESOURCES;
391 }
392 }
393 } else {
394 /* "MiniportName" is available only XP and above. Not on Windows 2000. */
395 NDIS_STRING key = NDIS_STRING_CONST("NdisVersion");
396 NdisReadConfiguration (&status, &parm, configHandle, &key, NdisParameterInteger);
397 if (status == NDIS_STATUS_SUCCESS)
398 {
399 if (parm->ParameterData.IntegerData == 0x50000)
400 {
401 /* Fallback for Windows 2000 with NDIS version 5.00.00
402 Don't use this on Vista, 'NDIS_MINIPORT_BLOCK' was changed! */
403 DEBUGP (("[TAP] NdisReadConfiguration NdisVersion (Int=%X)\n", parm->ParameterData.IntegerData));
404 if (RtlUnicodeStringToAnsiString (
405 &l_Adapter->m_NameAnsi,
406 &((PNDIS_MINIPORT_BLOCK) p_AdapterHandle)->MiniportName,
407 TRUE) != STATUS_SUCCESS)
408 {
409 DEBUGP (("[TAP] RtlUnicodeStringToAnsiString MiniportName (W2K) failed\n"));
410 status = NDIS_STATUS_RESOURCES;
411 }
412 }
413 }
414 }
415 }
416
417 /* Can't continue without name (see macro 'NAME') */
418 if (status != NDIS_STATUS_SUCCESS || !l_Adapter->m_NameAnsi.Buffer)
419 {
420 NdisCloseConfiguration (configHandle);
421 AdapterFreeResources (l_Adapter);
422 return NDIS_STATUS_RESOURCES;
423 }
424
425 /* Read MTU setting from registry */
426 {
427 NDIS_STRING key = NDIS_STRING_CONST("MTU");
428 NdisReadConfiguration (&status, &parm, configHandle,
429 &key, NdisParameterInteger);
430 if (status == NDIS_STATUS_SUCCESS)
431 {
432 if (parm->ParameterType == NdisParameterInteger)
433 {
434 int mtu = parm->ParameterData.IntegerData;
435 if (mtu < MINIMUM_MTU)
436 mtu = MINIMUM_MTU;
437 if (mtu > MAXIMUM_MTU)
438 mtu = MAXIMUM_MTU;
439 l_Adapter->m_MTU = mtu;
440 }
441 }
442 }
443
444 /* Read Media Status setting from registry */
445 {
446 NDIS_STRING key = NDIS_STRING_CONST("MediaStatus");
447 NdisReadConfiguration (&status, &parm, configHandle,
448 &key, NdisParameterInteger);
449 if (status == NDIS_STATUS_SUCCESS)
450 {
451 if (parm->ParameterType == NdisParameterInteger)
452 {
453 if (parm->ParameterData.IntegerData)
454 {
455 l_Adapter->m_MediaStateAlwaysConnected = TRUE;
456 l_Adapter->m_MediaState = TRUE;
457 }
458 }
459 }
460 }
461
462 /* Read optional MAC setting from registry */
463 {
464 NDIS_STRING key = NDIS_STRING_CONST("MAC");
465 ANSI_STRING mac_string;
466 NdisReadConfiguration (&status, &parm, configHandle,
467 &key, NdisParameterString);
468 if (status == NDIS_STATUS_SUCCESS)
469 {
470 if (parm->ParameterType == NdisParameterString)
471 {
472 if (RtlUnicodeStringToAnsiString (&mac_string, &parm->ParameterData.StringData, TRUE) == STATUS_SUCCESS)
473 {
474 l_MacFromRegistry = ParseMAC (l_Adapter->m_MAC, mac_string.Buffer);
475 RtlFreeAnsiString (&mac_string);
476 }
477 }
478 }
479 }
480
481 NdisCloseConfiguration (configHandle);
482
483 DEBUGP (("[%s] MTU=%d\n", NAME (l_Adapter), l_Adapter->m_MTU));
484 }
485
486 //==================================
487 // Store and update MAC address info
488 //==================================
489
490 if (!l_MacFromRegistry)
491 GenerateRandomMac (l_Adapter->m_MAC, NAME (l_Adapter));
492
493 DEBUGP (("[%s] Using MAC %x:%x:%x:%x:%x:%x\n",
494 NAME (l_Adapter),
495 l_Adapter->m_MAC[0], l_Adapter->m_MAC[1], l_Adapter->m_MAC[2],
496 l_Adapter->m_MAC[3], l_Adapter->m_MAC[4], l_Adapter->m_MAC[5]));
497
498 //==================
499 // Set broadcast MAC
500 //==================
501 {
502 int i;
503 for (i = 0; i < sizeof (MACADDR); ++i)
504 l_Adapter->m_MAC_Broadcast[i] = 0xFF;
505 }
506
507 //====================================
508 // Initialize TAP device
509 //====================================
510 {
511 NDIS_STATUS tap_status;
512 tap_status = CreateTapDevice (&l_Adapter->m_Extension, NAME (l_Adapter));
513 if (tap_status != NDIS_STATUS_SUCCESS)
514 {
515 AdapterFreeResources (l_Adapter);
516 return tap_status;
517 }
518 }
519
520 if (!AddAdapterToInstanceList (l_Adapter))
521 {
522 NOTE_ERROR ();
523 TapDeviceFreeResources (&l_Adapter->m_Extension);
524 AdapterFreeResources (l_Adapter);
525 return NDIS_STATUS_RESOURCES;
526 }
527
528 l_Adapter->m_InterfaceIsRunning = TRUE;
529
530 return NDIS_STATUS_SUCCESS;
531}
532
533VOID
534AdapterHalt (IN NDIS_HANDLE p_AdapterContext)
535{
536 BOOLEAN status;
537
538 TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
539
540 NOTE_ERROR ();
541
542 l_Adapter->m_InterfaceIsRunning = FALSE;
543
544 DEBUGP (("[%s] is being halted\n", NAME (l_Adapter)));
545
546 DestroyTapDevice (&l_Adapter->m_Extension);
547
548 // Free resources
549 DEBUGP (("[%s] Freeing Resources\n", NAME (l_Adapter)));
550 AdapterFreeResources (l_Adapter);
551
552 status = RemoveAdapterFromInstanceList (l_Adapter);
553 DEBUGP (("[TAP] RemoveAdapterFromInstanceList returned %d\n", (int) status));
554
555 DEBUGP (("[TAP] version [%d.%d] %s %s AdapterHalt returning\n",
556 TAP_DRIVER_MAJOR_VERSION,
557 TAP_DRIVER_MINOR_VERSION,
558 __DATE__,
559 __TIME__));
560}
561
562VOID
563AdapterFreeResources (TapAdapterPointer p_Adapter)
564{
565 MYASSERT (!p_Adapter->m_CalledAdapterFreeResources);
566 p_Adapter->m_CalledAdapterFreeResources = TRUE;
567
568 if (p_Adapter->m_NameAnsi.Buffer)
569 RtlFreeAnsiString (&p_Adapter->m_NameAnsi);
570
571 if (p_Adapter->m_RegisteredAdapterShutdownHandler)
572 NdisMDeregisterAdapterShutdownHandler (p_Adapter->m_MiniportAdapterHandle);
573
574 if (p_Adapter->m_MCLockAllocated)
575 NdisFreeSpinLock (&l_Adapter->m_MCLock);
576}
577
578VOID
579DestroyTapDevice (TapExtensionPointer p_Extension)
580{
581 DEBUGP (("[%s] Destroying tap device\n", p_Extension->m_TapName));
582
583 //======================================
584 // Let clients know we are shutting down
585 //======================================
586 p_Extension->m_TapIsRunning = FALSE;
587 p_Extension->m_TapOpens = 0;
588 p_Extension->m_Halt = TRUE;
589
590 //=====================================
591 // If we are concurrently executing in
592 // TapDeviceHook or AdapterTransmit,
593 // give those calls time to finish.
594 // Note that we must be running at IRQL
595 // < DISPATCH_LEVEL in order to call
596 // NdisMSleep.
597 //=====================================
598 NdisMSleep (500000);
599
600 //===========================================================
601 // Exhaust IRP and packet queues. Any pending IRPs will
602 // be cancelled, causing user-space to get this error
603 // on overlapped reads:
604 // The I/O operation has been aborted because of either a
605 // thread exit or an application request. (code=995)
606 // It's important that user-space close the device handle
607 // when this code is returned, so that when we finally
608 // do a NdisMDeregisterDevice, the device reference count
609 // is 0. Otherwise the driver will not unload even if the
610 // the last adapter has been halted.
611 //===========================================================
612 FlushQueues (p_Extension);
613 NdisMSleep (500000); // give user space time to respond to IRP cancel
614
615 TapDeviceFreeResources (p_Extension);
616}
617
618VOID
619TapDeviceFreeResources (TapExtensionPointer p_Extension)
620{
621 MYASSERT (p_Extension);
622 MYASSERT (!p_Extension->m_CalledTapDeviceFreeResources);
623 p_Extension->m_CalledTapDeviceFreeResources = TRUE;
624
625 if (p_Extension->m_PacketQueue)
626 QueueFree (p_Extension->m_PacketQueue);
627 if (p_Extension->m_IrpQueue)
628 QueueFree (p_Extension->m_IrpQueue);
629
630 if (p_Extension->m_CreatedUnicodeLinkName)
631 RtlFreeUnicodeString (&p_Extension->m_UnicodeLinkName);
632
633 //==========================================================
634 // According to DDK docs, the device is not actually deleted
635 // until its reference count falls to zero. That means we
636 // still need to gracefully fail TapDeviceHook requests
637 // after this point, otherwise ugly things would happen if
638 // the device was disabled (e.g. in the network connections
639 // control panel) while a userspace app still held an open
640 // file handle to it.
641 //==========================================================
642
643 if (p_Extension->m_TapDevice)
644 {
645 BOOLEAN status;
646 status = (NdisMDeregisterDevice (p_Extension->m_TapDeviceHandle)
647 == NDIS_STATUS_SUCCESS);
648 DEBUGP (("[TAP] Deregistering TAP device, status=%d\n", (int)status));
649 }
650
651 if (p_Extension->m_TapName)
652 MemFree (p_Extension->m_TapName, NAME_BUFFER_SIZE);
653
654 if (p_Extension->m_AllocatedSpinlocks)
655 NdisFreeSpinLock (&p_Extension->m_QueueLock);
656}
657
658//========================================================================
659// Tap Device Initialization
660//========================================================================
661
662NDIS_STATUS
663CreateTapDevice (TapExtensionPointer p_Extension, const char *p_Name)
664{
665# define SIZEOF_DISPATCH (sizeof(PDRIVER_DISPATCH) * (IRP_MJ_MAXIMUM_FUNCTION + 1))
666 PDRIVER_DISPATCH *l_Dispatch = NULL;
667 ANSI_STRING l_TapString, l_LinkString;
668 UNICODE_STRING l_TapUnicode;
669 BOOLEAN l_FreeTapUnicode = FALSE;
670 NTSTATUS l_Status, l_Return = NDIS_STATUS_SUCCESS;
671 const char *l_UsableName;
672
673 DEBUGP (("[TAP] version [%d.%d] creating tap device: %s\n",
674 TAP_DRIVER_MAJOR_VERSION,
675 TAP_DRIVER_MINOR_VERSION,
676 p_Name));
677
678 NdisZeroMemory (p_Extension, sizeof (TapExtension));
679
680 INIT_MUTEX (&p_Extension->m_OpenCloseMutex);
681
682 l_LinkString.Buffer = NULL;
683 l_TapString.Buffer = NULL;
684
685 l_TapString.MaximumLength = l_LinkString.MaximumLength = NAME_BUFFER_SIZE;
686
687 //=======================================
688 // Set TAP device entry points
689 //=======================================
690
691 if ((l_Dispatch = MemAlloc (SIZEOF_DISPATCH, TRUE)) == NULL)
692 {
693 DEBUGP (("[%s] couldn't alloc TAP dispatch table\n", p_Name));
694 l_Return = NDIS_STATUS_RESOURCES;
695 goto cleanup;
696 }
697
698 l_Dispatch[IRP_MJ_DEVICE_CONTROL] = TapDeviceHook;
699 l_Dispatch[IRP_MJ_READ] = TapDeviceHook;
700 l_Dispatch[IRP_MJ_WRITE] = TapDeviceHook;
701 l_Dispatch[IRP_MJ_CREATE] = TapDeviceHook;
702 l_Dispatch[IRP_MJ_CLOSE] = TapDeviceHook;
703
704 //==================================
705 // Find the beginning of the GUID
706 //==================================
707 l_UsableName = p_Name;
708 while (*l_UsableName != '{')
709 {
710 if (*l_UsableName == '\0')
711 {
712 DEBUGP (("[%s] couldn't find leading '{' in name\n", p_Name));
713 l_Return = NDIS_STATUS_RESOURCES;
714 goto cleanup;
715 }
716 ++l_UsableName;
717 }
718
719 //==================================
720 // Allocate pool for TAP device name
721 //==================================
722
723 if ((p_Extension->m_TapName = l_TapString.Buffer =
724 MemAlloc (NAME_BUFFER_SIZE, TRUE)) == NULL)
725 {
726 DEBUGP (("[%s] couldn't alloc TAP name buffer\n", p_Name));
727 l_Return = NDIS_STATUS_RESOURCES;
728 goto cleanup;
729 }
730
731 //================================================
732 // Allocate pool for TAP symbolic link name buffer
733 //================================================
734
735 if ((l_LinkString.Buffer =
736 MemAlloc (NAME_BUFFER_SIZE, TRUE)) == NULL)
737 {
738 DEBUGP (("[%s] couldn't alloc TAP symbolic link name buffer\n",
739 p_Name));
740 l_Return = NDIS_STATUS_RESOURCES;
741 goto cleanup;
742 }
743
744 //=======================================================
745 // Set TAP device name
746 //=======================================================
747
748 l_Status = RtlStringCchPrintfExA
749 (l_TapString.Buffer,
750 l_TapString.MaximumLength,
751 NULL,
752 NULL,
753 STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,
754 "%s%s%s",
755 SYSDEVICEDIR,
756 l_UsableName,
757 TAPSUFFIX);
758
759 if (l_Status != STATUS_SUCCESS)
760 {
761 DEBUGP (("[%s] couldn't format TAP device name\n",
762 p_Name));
763 l_Return = NDIS_STATUS_RESOURCES;
764 goto cleanup;
765 }
766 l_TapString.Length = (USHORT) strlen (l_TapString.Buffer);
767
768 DEBUGP (("TAP DEV NAME: '%s'\n", l_TapString.Buffer));
769
770 //=======================================================
771 // Set TAP link name
772 //=======================================================
773
774 l_Status = RtlStringCchPrintfExA
775 (l_LinkString.Buffer,
776 l_LinkString.MaximumLength,
777 NULL,
778 NULL,
779 STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,
780 "%s%s%s",
781 USERDEVICEDIR,
782 l_UsableName,
783 TAPSUFFIX);
784
785 if (l_Status != STATUS_SUCCESS)
786 {
787 DEBUGP (("[%s] couldn't format TAP device symbolic link\n",
788 p_Name));
789 l_Return = NDIS_STATUS_RESOURCES;
790 goto cleanup;
791 }
792 l_LinkString.Length = (USHORT) strlen (l_LinkString.Buffer);
793
794 DEBUGP (("TAP LINK NAME: '%s'\n", l_LinkString.Buffer));
795
796 //==================================================
797 // Convert strings to unicode
798 //==================================================
799 if (RtlAnsiStringToUnicodeString (&l_TapUnicode, &l_TapString, TRUE) !=
800 STATUS_SUCCESS)
801 {
802 DEBUGP (("[%s] couldn't alloc TAP unicode name buffer\n",
803 p_Name));
804 l_Return = NDIS_STATUS_RESOURCES;
805 goto cleanup;
806 }
807 l_FreeTapUnicode = TRUE;
808
809 if (RtlAnsiStringToUnicodeString
810 (&p_Extension->m_UnicodeLinkName, &l_LinkString, TRUE)
811 != STATUS_SUCCESS)
812 {
813 DEBUGP
814 (("[%s] Couldn't allocate unicode string for symbolic link name\n",
815 p_Name));
816 l_Return = NDIS_STATUS_RESOURCES;
817 goto cleanup;
818 }
819 p_Extension->m_CreatedUnicodeLinkName = TRUE;
820
821 //==================================================
822 // Create new TAP device with symbolic
823 // link and associate with adapter.
824 //==================================================
825
826 l_Status = NdisMRegisterDevice
827 (g_NdisWrapperHandle,
828 &l_TapUnicode,
829 &p_Extension->m_UnicodeLinkName,
830 l_Dispatch,
831 &p_Extension->m_TapDevice,
832 &p_Extension->m_TapDeviceHandle
833 );
834
835 if (l_Status != STATUS_SUCCESS)
836 {
837 DEBUGP (("[%s] couldn't be created\n", p_Name));
838 l_Return = NDIS_STATUS_RESOURCES;
839 goto cleanup;
840 }
841
842 /* Set TAP device flags */
843 p_Extension->m_TapDevice->Flags |= DO_DIRECT_IO;
844
845 //========================================================
846 // Initialize Packet and IRP queues.
847 //
848 // The packet queue is used to buffer data which has been
849 // "transmitted" by the virtual NIC, before user space
850 // has had a chance to read it.
851 //
852 // The IRP queue is used to buffer pending I/O requests
853 // from userspace, i.e. read requests on the TAP device
854 // waiting for the system to "transmit" something through
855 // the virtual NIC.
856 //
857 // Basically, packets in the packet queue are used
858 // to satisfy IRP requests in the IRP queue.
859 //
860 // QueueLock is used to lock the packet queue used
861 // for the TAP-Win32 NIC -> User Space packet flow direction.
862 //
863 // All accesses to packet or IRP queues should be
864 // bracketed by the QueueLock spinlock,
865 // in order to be SMP-safe.
866 //========================================================
867
868 NdisAllocateSpinLock (&p_Extension->m_QueueLock);
869 p_Extension->m_AllocatedSpinlocks = TRUE;
870
871 p_Extension->m_PacketQueue = QueueInit (PACKET_QUEUE_SIZE);
872 p_Extension->m_IrpQueue = QueueInit (IRP_QUEUE_SIZE);
873
874 if (!p_Extension->m_PacketQueue
875 || !p_Extension->m_IrpQueue)
876 {
877 DEBUGP (("[%s] couldn't alloc TAP queues\n", p_Name));
878 l_Return = NDIS_STATUS_RESOURCES;
879 goto cleanup;
880 }
881
882 //========================
883 // Finalize initialization
884 //========================
885
886 p_Extension->m_TapIsRunning = TRUE;
887
888 DEBUGP (("[%s] successfully created TAP device [%s]\n", p_Name,
889 p_Extension->m_TapName));
890
891 cleanup:
892 if (l_FreeTapUnicode)
893 RtlFreeUnicodeString (&l_TapUnicode);
894 if (l_LinkString.Buffer)
895 MemFree (l_LinkString.Buffer, NAME_BUFFER_SIZE);
896 if (l_Dispatch)
897 MemFree (l_Dispatch, SIZEOF_DISPATCH);
898
899 if (l_Return != NDIS_STATUS_SUCCESS)
900 TapDeviceFreeResources (p_Extension);
901
902 return l_Return;
903}
904#undef SIZEOF_DISPATCH
905
906//========================================================
907// Adapter Control
908//========================================================
909NDIS_STATUS
910AdapterReset (OUT PBOOLEAN p_AddressingReset, IN NDIS_HANDLE p_AdapterContext)
911{
912 TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
913 DEBUGP (("[%s] is resetting\n", NAME (l_Adapter)));
914 return NDIS_STATUS_SUCCESS;
915}
916
917NDIS_STATUS AdapterReceive
918 (OUT PNDIS_PACKET p_Packet,
919 OUT PUINT p_Transferred,
920 IN NDIS_HANDLE p_AdapterContext,
921 IN NDIS_HANDLE p_ReceiveContext,
922 IN UINT p_Offset,
923 IN UINT p_ToTransfer)
924{
925 DEBUGP(("AdapterReceive %08x size=%x\n", p_Packet, p_ToTransfer));
926 return NDIS_STATUS_SUCCESS;
927}
928
929//==============================================================
930// Adapter Option Query/Modification
931//==============================================================
932NDIS_STATUS AdapterQuery
933(IN NDIS_HANDLE p_AdapterContext,
934 IN NDIS_OID p_OID,
935 IN PVOID p_Buffer,
936 IN ULONG p_BufferLength,
937 OUT PULONG p_BytesWritten, OUT PULONG p_BytesNeeded)
938{
939 TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
940 TapAdapterQuery l_Query, *l_QueryPtr = &l_Query;
941 NDIS_STATUS l_Status = NDIS_STATUS_SUCCESS;
942 UINT l_QueryLength = 4;
943 BOOLEAN lock_succeeded;
944
945 NdisZeroMemory (&l_Query, sizeof (l_Query));
946
947 switch (p_OID)
948 {
949 //===================================================================
950 // Vendor & Driver version Info
951 //===================================================================
952 case OID_GEN_VENDOR_DESCRIPTION:
953 l_QueryPtr = (TapAdapterQueryPointer) PRODUCT_STRING;
954 l_QueryLength = strlen (PRODUCT_STRING) + 1;
955 break;
956
957 case OID_GEN_VENDOR_ID:
958 l_Query.m_Long = 0xffffff;
959 break;
960
961 case OID_GEN_DRIVER_VERSION:
962 l_Query.m_Short =
963 (((USHORT) TAP_NDIS_MAJOR_VERSION) << 8 | (USHORT)
964 TAP_NDIS_MINOR_VERSION);
965 l_QueryLength = sizeof (unsigned short);
966 break;
967
968 case OID_GEN_VENDOR_DRIVER_VERSION:
969 l_Query.m_Long =
970 (((USHORT) TAP_DRIVER_MAJOR_VERSION) << 8 | (USHORT)
971 TAP_DRIVER_MINOR_VERSION);
972 break;
973
974 //=================================================================
975 // Statistics
976 //=================================================================
977 case OID_GEN_RCV_NO_BUFFER:
978 l_Query.m_Long = 0;
979 break;
980
981 case OID_802_3_RCV_ERROR_ALIGNMENT:
982 l_Query.m_Long = 0;
983 break;
984
985 case OID_802_3_XMIT_ONE_COLLISION:
986 l_Query.m_Long = 0;
987 break;
988
989 case OID_802_3_XMIT_MORE_COLLISIONS:
990 l_Query.m_Long = 0;
991 break;
992
993 case OID_GEN_XMIT_OK:
994 l_Query.m_Long = l_Adapter->m_Tx;
995 break;
996
997 case OID_GEN_RCV_OK:
998 l_Query.m_Long = l_Adapter->m_Rx;
999 break;
1000
1001 case OID_GEN_XMIT_ERROR:
1002 l_Query.m_Long = l_Adapter->m_TxErr;
1003 break;
1004
1005 case OID_GEN_RCV_ERROR:
1006 l_Query.m_Long = l_Adapter->m_RxErr;
1007 break;
1008
1009 //===================================================================
1010 // Device & Protocol Options
1011 //===================================================================
1012 case OID_GEN_SUPPORTED_LIST:
1013 l_QueryPtr = (TapAdapterQueryPointer) g_SupportedOIDList;
1014 l_QueryLength = sizeof (g_SupportedOIDList);
1015 break;
1016
1017 case OID_GEN_MAC_OPTIONS:
1018 // This MUST be here !!!
1019 l_Query.m_Long = (NDIS_MAC_OPTION_RECEIVE_SERIALIZED
1020 | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA
1021 | NDIS_MAC_OPTION_NO_LOOPBACK
1022 | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND);
1023
1024 break;
1025
1026 case OID_GEN_CURRENT_PACKET_FILTER:
1027 l_Query.m_Long =
1028 (NDIS_PACKET_TYPE_ALL_LOCAL |
1029 NDIS_PACKET_TYPE_BROADCAST |
1030 NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_FUNCTIONAL);
1031
1032 break;
1033
1034 case OID_GEN_PROTOCOL_OPTIONS:
1035 l_Query.m_Long = 0;
1036 break;
1037
1038 //==================================================================
1039 // Device Info
1040 //==================================================================
1041 case OID_GEN_MEDIA_CONNECT_STATUS:
1042 l_Query.m_Long = l_Adapter->m_MediaState
1043 ? NdisMediaStateConnected : NdisMediaStateDisconnected;
1044 break;
1045
1046 case OID_GEN_HARDWARE_STATUS:
1047 l_Query.m_HardwareStatus = NdisHardwareStatusReady;
1048 l_QueryLength = sizeof (NDIS_HARDWARE_STATUS);
1049 break;
1050
1051 case OID_GEN_MEDIA_SUPPORTED:
1052 case OID_GEN_MEDIA_IN_USE:
1053 l_Query.m_Medium = l_Adapter->m_Medium;
1054 l_QueryLength = sizeof (NDIS_MEDIUM);
1055 break;
1056
1057 case OID_GEN_PHYSICAL_MEDIUM:
1058 l_Query.m_PhysicalMedium = NdisPhysicalMediumUnspecified;
1059 l_QueryLength = sizeof (NDIS_PHYSICAL_MEDIUM);
1060 break;
1061
1062 case OID_GEN_LINK_SPEED:
1063 l_Query.m_Long = 100000;
1064 break;
1065
1066 case OID_802_3_PERMANENT_ADDRESS:
1067 case OID_802_3_CURRENT_ADDRESS:
1068 COPY_MAC (l_Query.m_MacAddress, l_Adapter->m_MAC);
1069 l_QueryLength = sizeof (MACADDR);
1070 break;
1071
1072 //==================================================================
1073 // Limits
1074 //==================================================================
1075
1076 case OID_GEN_MAXIMUM_SEND_PACKETS:
1077 l_Query.m_Long = 1;
1078 break;
1079
1080 case OID_802_3_MAXIMUM_LIST_SIZE:
1081 l_Query.m_Long = NIC_MAX_MCAST_LIST;
1082 break;
1083
1084 case OID_GEN_CURRENT_LOOKAHEAD:
1085 l_Query.m_Long = l_Adapter->m_Lookahead;
1086 break;
1087
1088 case OID_GEN_MAXIMUM_LOOKAHEAD:
1089 case OID_GEN_MAXIMUM_TOTAL_SIZE:
1090 case OID_GEN_RECEIVE_BUFFER_SPACE:
1091 case OID_GEN_RECEIVE_BLOCK_SIZE:
1092 l_Query.m_Long = DEFAULT_PACKET_LOOKAHEAD;
1093 break;
1094
1095 case OID_GEN_MAXIMUM_FRAME_SIZE:
1096 case OID_GEN_TRANSMIT_BLOCK_SIZE:
1097 case OID_GEN_TRANSMIT_BUFFER_SPACE:
1098 l_Query.m_Long = l_Adapter->m_MTU;
1099 break;
1100
1101 case OID_PNP_CAPABILITIES:
1102 do
1103 {
1104 PNDIS_PNP_CAPABILITIES pPNPCapabilities;
1105 PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct;
1106
1107 if (p_BufferLength >= sizeof (NDIS_PNP_CAPABILITIES))
1108 {
1109 pPNPCapabilities = (PNDIS_PNP_CAPABILITIES) (p_Buffer);
1110
1111 //
1112 // Setting up the buffer to be returned
1113 // to the Protocol above the Passthru miniport
1114 //
1115 pPMstruct = &pPNPCapabilities->WakeUpCapabilities;
1116 pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
1117 pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;
1118 pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
1119 }
1120 l_QueryLength = sizeof (NDIS_PNP_CAPABILITIES);
1121 }
1122 while (FALSE);
1123 break;
1124 case OID_PNP_QUERY_POWER:
1125 break;
1126
1127 // Required OIDs that we don't support
1128
1129 case OID_GEN_SUPPORTED_GUIDS:
1130 case OID_GEN_MEDIA_CAPABILITIES:
1131 case OID_TCP_TASK_OFFLOAD:
1132 case OID_FFP_SUPPORT:
1133 l_Status = NDIS_STATUS_INVALID_OID;
1134 break;
1135
1136 // Optional stats OIDs
1137
1138 case OID_GEN_DIRECTED_BYTES_XMIT:
1139 case OID_GEN_DIRECTED_FRAMES_XMIT:
1140 case OID_GEN_MULTICAST_BYTES_XMIT:
1141 case OID_GEN_MULTICAST_FRAMES_XMIT:
1142 case OID_GEN_BROADCAST_BYTES_XMIT:
1143 case OID_GEN_BROADCAST_FRAMES_XMIT:
1144 case OID_GEN_DIRECTED_BYTES_RCV:
1145 case OID_GEN_DIRECTED_FRAMES_RCV:
1146 case OID_GEN_MULTICAST_BYTES_RCV:
1147 case OID_GEN_MULTICAST_FRAMES_RCV:
1148 case OID_GEN_BROADCAST_BYTES_RCV:
1149 case OID_GEN_BROADCAST_FRAMES_RCV:
1150 l_Status = NDIS_STATUS_INVALID_OID;
1151 break;
1152
1153 //===================================================================
1154 // Not Handled
1155 //===================================================================
1156 default:
1157 DEBUGP (("[%s] Unhandled OID %lx\n", NAME (l_Adapter), p_OID));
1158 l_Status = NDIS_STATUS_INVALID_OID;
1159 break;
1160 }
1161
1162 if (l_Status != NDIS_STATUS_SUCCESS)
1163 ;
1164 else if (l_QueryLength > p_BufferLength)
1165 {
1166 l_Status = NDIS_STATUS_INVALID_LENGTH;
1167 *p_BytesNeeded = l_QueryLength;
1168 }
1169 else
1170 NdisMoveMemory (p_Buffer, (PVOID) l_QueryPtr,
1171 (*p_BytesWritten = l_QueryLength));
1172
1173 return l_Status;
1174}
1175
1176NDIS_STATUS AdapterModify
1177(IN NDIS_HANDLE p_AdapterContext,
1178 IN NDIS_OID p_OID,
1179 IN PVOID p_Buffer,
1180 IN ULONG p_BufferLength,
1181 OUT PULONG p_BytesRead,
1182 OUT PULONG p_BytesNeeded)
1183{
1184 TapAdapterQueryPointer l_Query = (TapAdapterQueryPointer) p_Buffer;
1185 TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
1186 NDIS_STATUS l_Status = NDIS_STATUS_INVALID_OID;
1187 ULONG l_Long;
1188
1189 switch (p_OID)
1190 {
1191 //==================================================================
1192 // Device Info
1193 //==================================================================
1194 case OID_802_3_MULTICAST_LIST:
1195 DEBUGP (("[%s] Setting [OID_802_3_MULTICAST_LIST]\n",
1196 NAME (l_Adapter)));
1197
1198 *p_BytesNeeded = sizeof (ETH_ADDR);
1199 *p_BytesRead = p_BufferLength;
1200
1201 if (p_BufferLength % sizeof (ETH_ADDR))
1202 l_Status = NDIS_STATUS_INVALID_LENGTH;
1203 else if (p_BufferLength > sizeof (MC_LIST))
1204 {
1205 l_Status = NDIS_STATUS_MULTICAST_FULL;
1206 *p_BytesNeeded = sizeof (MC_LIST);
1207 }
1208 else
1209 {
1210 NdisAcquireSpinLock (&l_Adapter->m_MCLock);
1211
1212 NdisZeroMemory(&l_Adapter->m_MCList, sizeof (MC_LIST));
1213
1214 NdisMoveMemory(&l_Adapter->m_MCList,
1215 p_Buffer,
1216 p_BufferLength);
1217
1218 l_Adapter->m_MCListSize = p_BufferLength / sizeof (ETH_ADDR);
1219
1220 NdisReleaseSpinLock (&l_Adapter->m_MCLock);
1221
1222 l_Status = NDIS_STATUS_SUCCESS;
1223 }
1224 break;
1225
1226 case OID_GEN_CURRENT_PACKET_FILTER:
1227 l_Status = NDIS_STATUS_INVALID_LENGTH;
1228 *p_BytesNeeded = 4;
1229
1230 if (p_BufferLength >= sizeof (ULONG))
1231 {
1232 DEBUGP
1233 (("[%s] Setting [OID_GEN_CURRENT_PACKET_FILTER] to [0x%02lx]\n",
1234 NAME (l_Adapter), l_Query->m_Long));
1235 l_Status = NDIS_STATUS_SUCCESS;
1236 *p_BytesRead = sizeof (ULONG);
1237 }
1238 break;
1239
1240 case OID_GEN_CURRENT_LOOKAHEAD:
1241 if (p_BufferLength < sizeof (ULONG))
1242 {
1243 l_Status = NDIS_STATUS_INVALID_LENGTH;
1244 *p_BytesNeeded = 4;
1245 }
1246 else if (l_Query->m_Long > DEFAULT_PACKET_LOOKAHEAD
1247 || l_Query->m_Long <= 0)
1248 {
1249 l_Status = NDIS_STATUS_INVALID_DATA;
1250 }
1251 else
1252 {
1253 DEBUGP (("[%s] Setting [OID_GEN_CURRENT_LOOKAHEAD] to [%d]\n",
1254 NAME (l_Adapter), l_Query->m_Long));
1255 l_Adapter->m_Lookahead = l_Query->m_Long;
1256 l_Status = NDIS_STATUS_SUCCESS;
1257 *p_BytesRead = sizeof (ULONG);
1258 }
1259 break;
1260
1261 case OID_GEN_NETWORK_LAYER_ADDRESSES:
1262 l_Status = NDIS_STATUS_SUCCESS;
1263 *p_BytesRead = *p_BytesNeeded = 0;
1264 break;
1265
1266 case OID_GEN_TRANSPORT_HEADER_OFFSET:
1267 l_Status = NDIS_STATUS_SUCCESS;
1268 *p_BytesRead = *p_BytesNeeded = 0;
1269 break;
1270
1271 case OID_PNP_SET_POWER:
1272 do
1273 {
1274 NDIS_DEVICE_POWER_STATE NewDeviceState;
1275
1276 NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE) p_Buffer);
1277
1278 switch (NewDeviceState)
1279 {
1280 case NdisDeviceStateD0:
1281 l_Adapter->m_DeviceState = '0';
1282 break;
1283 case NdisDeviceStateD1:
1284 l_Adapter->m_DeviceState = '1';
1285 break;
1286 case NdisDeviceStateD2:
1287 l_Adapter->m_DeviceState = '2';
1288 break;
1289 case NdisDeviceStateD3:
1290 l_Adapter->m_DeviceState = '3';
1291 break;
1292 default:
1293 l_Adapter->m_DeviceState = '?';
1294 break;
1295 }
1296
1297 l_Status = NDIS_STATUS_FAILURE;
1298
1299 //
1300 // Check for invalid length
1301 //
1302 if (p_BufferLength < sizeof (NDIS_DEVICE_POWER_STATE))
1303 {
1304 l_Status = NDIS_STATUS_INVALID_LENGTH;
1305 break;
1306 }
1307
1308 if (NewDeviceState > NdisDeviceStateD0)
1309 {
1310 l_Adapter->m_InterfaceIsRunning = FALSE;
1311 DEBUGP (("[%s] Power management device state OFF\n",
1312 NAME (l_Adapter)));
1313 }
1314 else
1315 {
1316 l_Adapter->m_InterfaceIsRunning = TRUE;
1317 DEBUGP (("[%s] Power management device state ON\n",
1318 NAME (l_Adapter)));
1319 }
1320
1321 l_Status = NDIS_STATUS_SUCCESS;
1322 }
1323 while (FALSE);
1324
1325 if (l_Status == NDIS_STATUS_SUCCESS)
1326 {
1327 *p_BytesRead = sizeof (NDIS_DEVICE_POWER_STATE);
1328 *p_BytesNeeded = 0;
1329 }
1330 else
1331 {
1332 *p_BytesRead = 0;
1333 *p_BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE);
1334 }
1335 break;
1336
1337 case OID_PNP_REMOVE_WAKE_UP_PATTERN:
1338 case OID_PNP_ADD_WAKE_UP_PATTERN:
1339 l_Status = NDIS_STATUS_SUCCESS;
1340 *p_BytesRead = *p_BytesNeeded = 0;
1341 break;
1342
1343 default:
1344 DEBUGP (("[%s] Can't set value for OID %lx\n", NAME (l_Adapter),
1345 p_OID));
1346 l_Status = NDIS_STATUS_INVALID_OID;
1347 *p_BytesRead = *p_BytesNeeded = 0;
1348 break;
1349 }
1350
1351 return l_Status;
1352}
1353
1354//====================================================================
1355// Adapter Transmission
1356//====================================================================
1357NDIS_STATUS
1358AdapterTransmit (IN NDIS_HANDLE p_AdapterContext,
1359 IN PNDIS_PACKET p_Packet,
1360 IN UINT p_Flags)
1361{
1362 TapAdapterPointer l_Adapter = (TapAdapterPointer) p_AdapterContext;
1363 ULONG l_Index = 0, l_BufferLength = 0, l_PacketLength = 0;
1364 PIRP l_IRP;
1365 TapPacketPointer l_PacketBuffer;
1366 PNDIS_BUFFER l_NDIS_Buffer;
1367 PUCHAR l_Buffer;
1368 PVOID result;
1369
1370 NdisQueryPacket (p_Packet, NULL, NULL, &l_NDIS_Buffer, &l_PacketLength);
1371
1372//// DEBUGP(("AdapterTransmit %08x size=%x\n", l_NDIS_Buffer, l_PacketLength));
1373
1374 //====================================================
1375 // Here we abandon the transmission attempt if any of
1376 // the parameters is wrong or memory allocation fails
1377 // but we do not indicate failure. The packet is
1378 // silently dropped.
1379 //====================================================
1380
1381 if (l_PacketLength < ETHERNET_HEADER_SIZE || l_PacketLength > 65535)
1382 goto exit_fail;
1383 else if (!l_Adapter->m_Extension.m_TapOpens || !l_Adapter->m_MediaState)
1384 goto exit_success; // Nothing is bound to the TAP device
1385
1386 if (NdisAllocateMemoryWithTag (&l_PacketBuffer,
1387 TAP_PACKET_SIZE (l_PacketLength),
1388 '5PAT') != NDIS_STATUS_SUCCESS)
1389 goto exit_no_resources;
1390
1391 if (l_PacketBuffer == NULL)
1392 goto exit_no_resources;
1393
1394 l_PacketBuffer->m_SizeFlags = (l_PacketLength & TP_SIZE_MASK);
1395
1396 //===========================
1397 // Reassemble packet contents
1398 //===========================
1399
1400 __try
1401 {
1402 for (l_Index = 0; l_NDIS_Buffer && l_Index < l_PacketLength;
1403 l_Index += l_BufferLength)
1404 {
1405 NdisQueryBuffer (l_NDIS_Buffer, (PVOID *) & l_Buffer,
1406 &l_BufferLength);
1407 NdisMoveMemory (l_PacketBuffer->m_Data + l_Index, l_Buffer,
1408 l_BufferLength);
1409 NdisGetNextBuffer (l_NDIS_Buffer, &l_NDIS_Buffer);
1410 }
1411
1412 DUMP_PACKET ("AdapterTransmit", l_PacketBuffer->m_Data, l_PacketLength);
1413
1414 //=====================================================
1415 // Are we running in DHCP server masquerade mode?
1416 //
1417 // If so, catch both DHCP requests and ARP queries
1418 // to resolve the address of our virtual DHCP server.
1419 //=====================================================
1420 if (l_Adapter->m_dhcp_enabled)
1421 {
1422 const ETH_HEADER *eth = (ETH_HEADER *) l_PacketBuffer->m_Data;
1423 const IPHDR *ip = (IPHDR *) (l_PacketBuffer->m_Data + sizeof (ETH_HEADER));
1424 const UDPHDR *udp = (UDPHDR *) (l_PacketBuffer->m_Data + sizeof (ETH_HEADER) + sizeof (IPHDR));
1425
1426 // ARP packet?
1427 if (l_PacketLength == sizeof (ARP_PACKET)
1428 && eth->proto == htons (ETH_P_ARP)
1429 && l_Adapter->m_dhcp_server_arp)
1430 {
1431 if (ProcessARP (l_Adapter,
1432 (PARP_PACKET) l_PacketBuffer->m_Data,
1433 l_Adapter->m_dhcp_addr,
1434 l_Adapter->m_dhcp_server_ip,
1435 l_Adapter->m_dhcp_server_mac))
1436 goto no_queue;
1437 }
1438
1439 // DHCP packet?
1440 else if (l_PacketLength >= sizeof (ETH_HEADER) + sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP)
1441 && eth->proto == htons (ETH_P_IP)
1442 && ip->version_len == 0x45 // IPv4, 20 byte header
1443 && ip->protocol == IPPROTO_UDP
1444 && udp->dest == htons (BOOTPS_PORT))
1445 {
1446 const DHCP *dhcp = (DHCP *) (l_PacketBuffer->m_Data
1447 + sizeof (ETH_HEADER)
1448 + sizeof (IPHDR)
1449 + sizeof (UDPHDR));
1450
1451 const int optlen = l_PacketLength
1452 - sizeof (ETH_HEADER)
1453 - sizeof (IPHDR)
1454 - sizeof (UDPHDR)
1455 - sizeof (DHCP);
1456
1457 if (optlen > 0) // we must have at least one DHCP option
1458 {
1459 if (ProcessDHCP (l_Adapter, eth, ip, udp, dhcp, optlen))
1460 goto no_queue;
1461 }
1462 else
1463 goto no_queue;
1464 }
1465 }
1466
1467 //===============================================
1468 // In Point-To-Point mode, check to see whether
1469 // packet is ARP or IPv4 (if neither, then drop).
1470 //===============================================
1471 if (l_Adapter->m_PointToPoint)
1472 {
1473 ETH_HEADER *e;
1474
1475 if (l_PacketLength < ETHERNET_HEADER_SIZE)
1476 goto no_queue;
1477
1478 e = (ETH_HEADER *) l_PacketBuffer->m_Data;
1479
1480 switch (ntohs (e->proto))
1481 {
1482 case ETH_P_ARP:
1483
1484 // Make sure that packet is the
1485 // right size for ARP.
1486 if (l_PacketLength != sizeof (ARP_PACKET))
1487 goto no_queue;
1488
1489 ProcessARP (l_Adapter,
1490 (PARP_PACKET) l_PacketBuffer->m_Data,
1491 l_Adapter->m_localIP,
1492 l_Adapter->m_remoteIP,
1493 l_Adapter->m_TapToUser.dest);
1494
1495 default:
1496 goto no_queue;
1497
1498 case ETH_P_IP:
1499
1500 // Make sure that packet is large
1501 // enough to be IPv4.
1502 if (l_PacketLength
1503 < ETHERNET_HEADER_SIZE + IP_HEADER_SIZE)
1504 goto no_queue;
1505
1506 // Only accept directed packets,
1507 // not broadcasts.
1508 if (memcmp (e, &l_Adapter->m_TapToUser, ETHERNET_HEADER_SIZE))
1509 goto no_queue;
1510
1511 // Packet looks like IPv4, queue it.
1512 l_PacketBuffer->m_SizeFlags |= TP_POINT_TO_POINT;
1513 }
1514 }
1515
1516 //===============================================
1517 // Push packet onto queue to wait for read from
1518 // userspace.
1519 //===============================================
1520
1521 NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
1522
1523 result = NULL;
1524 if (IS_UP (l_Adapter))
1525 result = QueuePush (l_Adapter->m_Extension.m_PacketQueue, l_PacketBuffer);
1526
1527 NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
1528
1529 if ((TapPacketPointer) result != l_PacketBuffer)
1530 {
1531 // adapter receive overrun
1532 INCREMENT_STAT (l_Adapter->m_TxErr);
1533 goto no_queue;
1534 }
1535 else
1536 {
1537 INCREMENT_STAT (l_Adapter->m_Tx);
1538 }
1539
1540 //============================================================
1541 // Cycle through IRPs and packets, try to satisfy each pending
1542 // IRP with a queued packet.
1543 //============================================================
1544 while (TRUE)
1545 {
1546 l_IRP = NULL;
1547 l_PacketBuffer = NULL;
1548
1549 NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
1550
1551 if (IS_UP (l_Adapter)
1552 && QueueCount (l_Adapter->m_Extension.m_PacketQueue)
1553 && QueueCount (l_Adapter->m_Extension.m_IrpQueue))
1554 {
1555 l_IRP = (PIRP) QueuePop (l_Adapter->m_Extension.m_IrpQueue);
1556 l_PacketBuffer = (TapPacketPointer)
1557 QueuePop (l_Adapter->m_Extension.m_PacketQueue);
1558 }
1559
1560 NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
1561
1562 MYASSERT ((l_IRP != NULL) + (l_PacketBuffer != NULL) != 1);
1563
1564 if (l_IRP && l_PacketBuffer)
1565 {
1566 CompleteIRP (l_IRP,
1567 l_PacketBuffer,
1568 IO_NETWORK_INCREMENT);
1569 }
1570 else
1571 break;
1572 }
1573 }
1574 __except (EXCEPTION_EXECUTE_HANDLER)
1575 {
1576 }
1577
1578 return NDIS_STATUS_SUCCESS;
1579
1580 no_queue:
1581 NdisFreeMemory (l_PacketBuffer,
1582 TAP_PACKET_SIZE (l_PacketLength),
1583 0);
1584
1585 exit_success:
1586 return NDIS_STATUS_SUCCESS;
1587
1588 exit_fail:
1589 return NDIS_STATUS_FAILURE;
1590
1591 exit_no_resources:
1592 return NDIS_STATUS_RESOURCES;
1593}
1594
1595//======================================================================
1596// Hooks for catching TAP device IRP's.
1597//======================================================================
1598
1599NTSTATUS
1600TapDeviceHook (IN PDEVICE_OBJECT p_DeviceObject, IN PIRP p_IRP)
1601{
1602 TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject);
1603 PIO_STACK_LOCATION l_IrpSp;
1604 NTSTATUS l_Status = STATUS_SUCCESS;
1605 BOOLEAN accessible;
1606
1607 l_IrpSp = IoGetCurrentIrpStackLocation (p_IRP);
1608
1609 p_IRP->IoStatus.Status = STATUS_SUCCESS;
1610 p_IRP->IoStatus.Information = 0;
1611
1612 if (!l_Adapter || l_Adapter->m_Extension.m_Halt)
1613 {
1614 DEBUGP (("TapDeviceHook called when TAP device is halted, MajorFunction=%d\n",
1615 (int)l_IrpSp->MajorFunction));
1616
1617 if (l_IrpSp->MajorFunction == IRP_MJ_CLOSE)
1618 {
1619 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1620 return STATUS_SUCCESS;
1621 }
1622 else
1623 {
1624 p_IRP->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
1625 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1626 return STATUS_NO_SUCH_DEVICE;
1627 }
1628 }
1629
1630 switch (l_IrpSp->MajorFunction)
1631 {
1632 //===========================================================
1633 // Ioctl call handlers
1634 //===========================================================
1635 case IRP_MJ_DEVICE_CONTROL:
1636 {
1637 switch (l_IrpSp->Parameters.DeviceIoControl.IoControlCode)
1638 {
1639 case TAP_IOCTL_GET_MAC:
1640 {
1641 if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
1642 >= sizeof (MACADDR))
1643 {
1644 COPY_MAC (p_IRP->AssociatedIrp.SystemBuffer,
1645 l_Adapter->m_MAC);
1646 p_IRP->IoStatus.Information = sizeof (MACADDR);
1647 }
1648 else
1649 {
1650 NOTE_ERROR ();
1651 p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
1652 }
1653 break;
1654 }
1655 case TAP_IOCTL_GET_VERSION:
1656 {
1657 const ULONG size = sizeof (ULONG) * 3;
1658 if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
1659 >= size)
1660 {
1661 ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0]
1662 = TAP_DRIVER_MAJOR_VERSION;
1663 ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[1]
1664 = TAP_DRIVER_MINOR_VERSION;
1665 ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[2]
1666#if DBG
1667 = 1;
1668#else
1669 = 0;
1670#endif
1671 p_IRP->IoStatus.Information = size;
1672 }
1673 else
1674 {
1675 NOTE_ERROR ();
1676 p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
1677 }
1678
1679 break;
1680 }
1681 case TAP_IOCTL_GET_MTU:
1682 {
1683 const ULONG size = sizeof (ULONG) * 1;
1684 if (l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength
1685 >= size)
1686 {
1687 ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0]
1688 = l_Adapter->m_MTU;
1689 p_IRP->IoStatus.Information = size;
1690 }
1691 else
1692 {
1693 NOTE_ERROR ();
1694 p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
1695 }
1696
1697 break;
1698 }
1699 case TAP_IOCTL_GET_INFO:
1700 {
1701 char state[16];
1702 if (l_Adapter->m_InterfaceIsRunning)
1703 state[0] = 'A';
1704 else
1705 state[0] = 'a';
1706 if (l_Adapter->m_Extension.m_TapIsRunning)
1707 state[1] = 'T';
1708 else
1709 state[1] = 't';
1710 state[2] = l_Adapter->m_DeviceState;
1711 if (l_Adapter->m_MediaStateAlwaysConnected)
1712 state[3] = 'C';
1713 else
1714 state[3] = 'c';
1715 state[4] = '\0';
1716
1717 p_IRP->IoStatus.Status = l_Status = RtlStringCchPrintfExA (
1718 ((LPTSTR) (p_IRP->AssociatedIrp.SystemBuffer)),
1719 l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
1720 NULL,
1721 NULL,
1722 STRSAFE_FILL_BEHIND_NULL | STRSAFE_IGNORE_NULLS,
1723 "State=%s Err=[%s/%d] #O=%d Tx=[%d,%d] Rx=[%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d]",
1724 state,
1725 g_LastErrorFilename,
1726 g_LastErrorLineNumber,
1727 (int)l_Adapter->m_Extension.m_NumTapOpens,
1728 (int)l_Adapter->m_Tx,
1729 (int)l_Adapter->m_TxErr,
1730 (int)l_Adapter->m_Rx,
1731 (int)l_Adapter->m_RxErr,
1732 (int)l_Adapter->m_Extension.m_IrpQueue->size,
1733 (int)l_Adapter->m_Extension.m_IrpQueue->max_size,
1734 (int)IRP_QUEUE_SIZE,
1735 (int)l_Adapter->m_Extension.m_PacketQueue->size,
1736 (int)l_Adapter->m_Extension.m_PacketQueue->max_size,
1737 (int)PACKET_QUEUE_SIZE
1738 );
1739
1740 p_IRP->IoStatus.Information
1741 = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1742
1743 break;
1744 }
1745
1746#if DBG
1747 case TAP_IOCTL_GET_LOG_LINE:
1748 {
1749 if (GetDebugLine ((LPTSTR)p_IRP->AssociatedIrp.SystemBuffer,
1750 l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength))
1751 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
1752 else
1753 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
1754
1755 p_IRP->IoStatus.Information
1756 = l_IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1757
1758 break;
1759 }
1760#endif
1761
1762 case TAP_IOCTL_CONFIG_POINT_TO_POINT:
1763 {
1764 if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
1765 (sizeof (IPADDR) * 2))
1766 {
1767 MACADDR dest;
1768
1769 l_Adapter->m_PointToPoint = FALSE;
1770
1771 GenerateRelatedMAC (dest, l_Adapter->m_MAC, 1);
1772
1773 l_Adapter->m_localIP =
1774 ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0];
1775 l_Adapter->m_remoteIP =
1776 ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1];
1777
1778 COPY_MAC (l_Adapter->m_TapToUser.src, l_Adapter->m_MAC);
1779 COPY_MAC (l_Adapter->m_TapToUser.dest, dest);
1780 COPY_MAC (l_Adapter->m_UserToTap.src, dest);
1781 COPY_MAC (l_Adapter->m_UserToTap.dest, l_Adapter->m_MAC);
1782
1783 l_Adapter->m_TapToUser.proto = l_Adapter->m_UserToTap.proto = htons (ETH_P_IP);
1784
1785 l_Adapter->m_PointToPoint = TRUE;
1786
1787 CheckIfDhcpAndPointToPointMode (l_Adapter);
1788
1789 p_IRP->IoStatus.Information = 1; // Simple boolean value
1790 }
1791 else
1792 {
1793 NOTE_ERROR ();
1794 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1795 }
1796
1797 break;
1798 }
1799
1800 case TAP_IOCTL_SET_MEDIA_STATUS:
1801 {
1802 if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
1803 (sizeof (ULONG) * 1))
1804 {
1805 ULONG parm = ((PULONG) (p_IRP->AssociatedIrp.SystemBuffer))[0];
1806 SetMediaStatus (l_Adapter, (BOOLEAN) parm);
1807 p_IRP->IoStatus.Information = 1;
1808 }
1809 else
1810 {
1811 NOTE_ERROR ();
1812 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1813 }
1814 break;
1815 }
1816
1817 case TAP_IOCTL_CONFIG_DHCP_MASQ:
1818 {
1819 if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
1820 (sizeof (IPADDR) * 4))
1821 {
1822 l_Adapter->m_dhcp_enabled = FALSE;
1823 l_Adapter->m_dhcp_server_arp = FALSE;
1824 l_Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
1825
1826 // Adapter IP addr / netmask
1827 l_Adapter->m_dhcp_addr =
1828 ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[0];
1829 l_Adapter->m_dhcp_netmask =
1830 ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[1];
1831
1832 // IP addr of DHCP masq server
1833 l_Adapter->m_dhcp_server_ip =
1834 ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[2];
1835
1836 // Lease time in seconds
1837 l_Adapter->m_dhcp_lease_time =
1838 ((IPADDR*) (p_IRP->AssociatedIrp.SystemBuffer))[3];
1839
1840 GenerateRelatedMAC (l_Adapter->m_dhcp_server_mac, l_Adapter->m_MAC, 2);
1841
1842 l_Adapter->m_dhcp_enabled = TRUE;
1843 l_Adapter->m_dhcp_server_arp = TRUE;
1844
1845 CheckIfDhcpAndPointToPointMode (l_Adapter);
1846
1847 p_IRP->IoStatus.Information = 1; // Simple boolean value
1848 }
1849 else
1850 {
1851 NOTE_ERROR ();
1852 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1853 }
1854
1855 break;
1856 }
1857
1858 case TAP_IOCTL_CONFIG_DHCP_SET_OPT:
1859 {
1860 if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength <=
1861 DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE
1862 && l_Adapter->m_dhcp_enabled)
1863 {
1864 l_Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
1865
1866 NdisMoveMemory (l_Adapter->m_dhcp_user_supplied_options_buffer,
1867 p_IRP->AssociatedIrp.SystemBuffer,
1868 l_IrpSp->Parameters.DeviceIoControl.InputBufferLength);
1869
1870 l_Adapter->m_dhcp_user_supplied_options_buffer_len =
1871 l_IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1872
1873 p_IRP->IoStatus.Information = 1; // Simple boolean value
1874 }
1875 else
1876 {
1877 NOTE_ERROR ();
1878 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1879 }
1880
1881 break;
1882 }
1883
1884#ifdef VBOX
1885 case TAP_IOCTL_TRANSFER_ETHPACKETS:
1886 {
1887 PTAP_SCATTER_GATHER_LIST pList;
1888 ULONG i;
1889 PMDL pMdlBuf = NULL;
1890
1891 if (l_IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(TAP_SCATTER_GATHER_LIST))
1892 {
1893 NOTE_ERROR ();
1894 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1895 break;
1896 }
1897 pList = (PTAP_SCATTER_GATHER_LIST)p_IRP->AssociatedIrp.SystemBuffer;
1898
1899 /* Sanity checks */
1900 if ( pList->cPackets > TAP_SCATTER_GATHER_MAX_PACKETS
1901 || l_IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(TAP_SCATTER_GATHER_LIST) + (pList->cPackets-1)*sizeof(TAP_SCATTER_GATHER_ITEM)
1902 )
1903 {
1904 NOTE_ERROR ();
1905 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1906 break;
1907 }
1908
1909 __try
1910 {
1911 /* Send all packets. */
1912 for (i=0;i<pList->cPackets;i++)
1913 {
1914 char *pBuffer;
1915
1916 DUMP_PACKET ("IRP_MJ_WRITE ETH", (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer, l_IrpSp->Parameters.Write.Length);
1917
1918 pMdlBuf = IoAllocateMdl(pList->aPacket[i].pPacket, pList->aPacket[i].cb, FALSE, FALSE, NULL);
1919 if (!pMdlBuf)
1920 {
1921 p_IRP->IoStatus.Status = l_Status = STATUS_NO_MEMORY;
1922 break;
1923 }
1924
1925 /* Exceptions caught by top _try _except block */
1926 /** @todo really necessary to lock the pages?? */
1927 MmProbeAndLockPages(pMdlBuf, KernelMode, IoModifyAccess);
1928
1929 pBuffer = MmGetSystemAddressForMdlSafe(pMdlBuf, NormalPagePriority);
1930 if (!pBuffer)
1931 {
1932 MmUnlockPages(pMdlBuf);
1933 IoFreeMdl(pMdlBuf);
1934 p_IRP->IoStatus.Status = l_Status = STATUS_NO_MEMORY;
1935 break;
1936 }
1937
1938 NdisMEthIndicateReceive(l_Adapter->m_MiniportAdapterHandle, (NDIS_HANDLE) l_Adapter,
1939 pBuffer,
1940 ETHERNET_HEADER_SIZE,
1941 pBuffer + ETHERNET_HEADER_SIZE,
1942 pList->aPacket[i].cb - ETHERNET_HEADER_SIZE,
1943 pList->aPacket[i].cb - ETHERNET_HEADER_SIZE);
1944
1945 NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle);
1946
1947 MmUnlockPages(pMdlBuf);
1948 IoFreeMdl(pMdlBuf);
1949 pMdlBuf = NULL;
1950
1951 }
1952 p_IRP->IoStatus.Information = 1; // Simple boolean value
1953 }
1954 __except (EXCEPTION_EXECUTE_HANDLER)
1955 {
1956 DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE\n",
1957 NAME (l_Adapter)));
1958 NOTE_ERROR ();
1959 if (pMdlBuf)
1960 IoFreeMdl(pMdlBuf);
1961
1962 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
1963 break;
1964 }
1965 break;
1966 }
1967#endif
1968
1969 default:
1970 {
1971 NOTE_ERROR ();
1972 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1973 break;
1974 }
1975 }
1976
1977 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1978 break;
1979 }
1980
1981 //===========================================================
1982 // User mode thread issued a read request on the tap device
1983 // If there are packets waiting to be read, then the request
1984 // will be satisfied here. If not, then the request will be
1985 // queued and satisfied by any packet that is not used to
1986 // satisfy requests ahead of it.
1987 //===========================================================
1988 case IRP_MJ_READ:
1989 {
1990 TapPacketPointer l_PacketBuffer;
1991 BOOLEAN pending = FALSE;
1992
1993 // Save IRP-accessible copy of buffer length
1994 p_IRP->IoStatus.Information = l_IrpSp->Parameters.Read.Length;
1995
1996 if (p_IRP->MdlAddress == NULL)
1997 {
1998 DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_READ\n",
1999 NAME (l_Adapter)));
2000 NOTE_ERROR ();
2001 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
2002 p_IRP->IoStatus.Information = 0;
2003 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2004 break;
2005 }
2006 else if ((p_IRP->AssociatedIrp.SystemBuffer =
2007 MmGetSystemAddressForMdlSafe
2008 (p_IRP->MdlAddress, NormalPagePriority)) == NULL)
2009 {
2010 DEBUGP (("[%s] Could not map address in IRP_MJ_READ\n",
2011 NAME (l_Adapter)));
2012 NOTE_ERROR ();
2013 p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES;
2014 p_IRP->IoStatus.Information = 0;
2015 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2016 break;
2017 }
2018 else if (!l_Adapter->m_InterfaceIsRunning)
2019 {
2020 DEBUGP (("[%s] Interface is down in IRP_MJ_READ\n",
2021 NAME (l_Adapter)));
2022 NOTE_ERROR ();
2023 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2024 p_IRP->IoStatus.Information = 0;
2025 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2026 break;
2027 }
2028
2029 //==================================
2030 // Can we provide immediate service?
2031 //==================================
2032
2033 l_PacketBuffer = NULL;
2034
2035 NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
2036
2037 if (IS_UP (l_Adapter)
2038 && QueueCount (l_Adapter->m_Extension.m_PacketQueue)
2039 && QueueCount (l_Adapter->m_Extension.m_IrpQueue) == 0)
2040 {
2041 l_PacketBuffer = (TapPacketPointer)
2042 QueuePop (l_Adapter->m_Extension.m_PacketQueue);
2043 }
2044
2045 NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
2046
2047 if (l_PacketBuffer)
2048 {
2049 l_Status = CompleteIRP (p_IRP,
2050 l_PacketBuffer,
2051 IO_NO_INCREMENT);
2052 break;
2053 }
2054
2055 //=============================
2056 // Attempt to pend read request
2057 //=============================
2058
2059 NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
2060
2061 if (IS_UP (l_Adapter)
2062 && QueuePush (l_Adapter->m_Extension.m_IrpQueue, p_IRP) == (PIRP) p_IRP)
2063 {
2064 IoSetCancelRoutine (p_IRP, CancelIRPCallback);
2065 l_Status = STATUS_PENDING;
2066 IoMarkIrpPending (p_IRP);
2067 pending = TRUE;
2068 }
2069
2070 NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
2071
2072 if (pending)
2073 break;
2074
2075 // Can't queue anymore IRP's
2076 DEBUGP (("[%s] TAP [%s] read IRP overrun\n",
2077 NAME (l_Adapter), l_Adapter->m_Extension.m_TapName));
2078 NOTE_ERROR ();
2079 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2080 p_IRP->IoStatus.Information = 0;
2081 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2082 break;
2083 }
2084
2085 //==============================================================
2086 // User mode issued a WriteFile request on the TAP file handle.
2087 // The request will always get satisfied here. The call may
2088 // fail if there are too many pending packets (queue full).
2089 //==============================================================
2090 case IRP_MJ_WRITE:
2091 {
2092 if (p_IRP->MdlAddress == NULL)
2093 {
2094 DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n",
2095 NAME (l_Adapter)));
2096 NOTE_ERROR ();
2097 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
2098 p_IRP->IoStatus.Information = 0;
2099 }
2100 else if ((p_IRP->AssociatedIrp.SystemBuffer =
2101 MmGetSystemAddressForMdlSafe
2102 (p_IRP->MdlAddress, NormalPagePriority)) == NULL)
2103 {
2104 DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n",
2105 NAME (l_Adapter)));
2106 NOTE_ERROR ();
2107 p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES;
2108 p_IRP->IoStatus.Information = 0;
2109 }
2110 else if (!l_Adapter->m_InterfaceIsRunning)
2111 {
2112 DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n",
2113 NAME (l_Adapter)));
2114 NOTE_ERROR ();
2115 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2116 p_IRP->IoStatus.Information = 0;
2117 }
2118 else if (!l_Adapter->m_PointToPoint && ((l_IrpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE))
2119 {
2120 __try
2121 {
2122 p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length;
2123
2124 ////DEBUGP(("IRP_MJ_WRITE %08x %x\n", p_IRP->AssociatedIrp.SystemBuffer, l_IrpSp->Parameters.Write.Length));
2125
2126 DUMP_PACKET ("IRP_MJ_WRITE ETH",
2127 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2128 l_IrpSp->Parameters.Write.Length);
2129
2130 NdisMEthIndicateReceive
2131 (l_Adapter->m_MiniportAdapterHandle,
2132 (NDIS_HANDLE) l_Adapter,
2133 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2134 ETHERNET_HEADER_SIZE,
2135 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer + ETHERNET_HEADER_SIZE,
2136 l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE,
2137 l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE);
2138
2139 NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle);
2140
2141 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2142 }
2143 __except (EXCEPTION_EXECUTE_HANDLER)
2144 {
2145 DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE\n",
2146 NAME (l_Adapter)));
2147 NOTE_ERROR ();
2148 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2149 p_IRP->IoStatus.Information = 0;
2150 }
2151 }
2152 else if (l_Adapter->m_PointToPoint && ((l_IrpSp->Parameters.Write.Length) >= IP_HEADER_SIZE))
2153 {
2154 __try
2155 {
2156 p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length;
2157
2158 DUMP_PACKET2 ("IRP_MJ_WRITE P2P",
2159 &l_Adapter->m_UserToTap,
2160 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2161 l_IrpSp->Parameters.Write.Length);
2162
2163 NdisMEthIndicateReceive
2164 (l_Adapter->m_MiniportAdapterHandle,
2165 (NDIS_HANDLE) l_Adapter,
2166 (unsigned char *) &l_Adapter->m_UserToTap,
2167 sizeof (l_Adapter->m_UserToTap),
2168 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2169 l_IrpSp->Parameters.Write.Length,
2170 l_IrpSp->Parameters.Write.Length);
2171
2172 NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle);
2173
2174 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2175 }
2176 __except (EXCEPTION_EXECUTE_HANDLER)
2177 {
2178 DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE (P2P)\n",
2179 NAME (l_Adapter)));
2180 NOTE_ERROR ();
2181 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2182 p_IRP->IoStatus.Information = 0;
2183 }
2184 }
2185 else
2186 {
2187 DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n",
2188 NAME (l_Adapter),
2189 l_IrpSp->Parameters.Write.Length));
2190 NOTE_ERROR ();
2191 p_IRP->IoStatus.Information = 0; // ETHERNET_HEADER_SIZE;
2192 p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
2193 }
2194
2195 if (l_Status == STATUS_SUCCESS)
2196 INCREMENT_STAT (l_Adapter->m_Rx);
2197 else
2198 INCREMENT_STAT (l_Adapter->m_RxErr);
2199
2200 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2201 break;
2202 }
2203
2204 //--------------------------------------------------------------
2205 // User mode thread has called CreateFile() on the tap device
2206 //--------------------------------------------------------------
2207 case IRP_MJ_CREATE:
2208 {
2209 BOOLEAN succeeded = FALSE;
2210 BOOLEAN mutex_succeeded;
2211
2212 DEBUGP
2213 (("[%s] [TAP] release [%d.%d] open request (m_TapOpens=%d)\n",
2214 NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION,
2215 TAP_DRIVER_MINOR_VERSION, l_Adapter->m_Extension.m_TapOpens));
2216
2217 ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded);
2218 if (mutex_succeeded)
2219 {
2220 if (l_Adapter->m_Extension.m_TapIsRunning && !l_Adapter->m_Extension.m_TapOpens)
2221 {
2222 ResetTapAdapterState (l_Adapter);
2223 l_Adapter->m_Extension.m_TapOpens = 1;
2224 succeeded = TRUE;
2225 }
2226
2227 if (succeeded)
2228 {
2229 INCREMENT_STAT (l_Adapter->m_Extension.m_NumTapOpens);
2230 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2231 p_IRP->IoStatus.Information = 0;
2232 }
2233 else
2234 {
2235 DEBUGP (("[%s] TAP is presently unavailable (m_TapOpens=%d)\n",
2236 NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
2237 NOTE_ERROR ();
2238 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2239 p_IRP->IoStatus.Information = 0;
2240 }
2241
2242 RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex);
2243 }
2244 else
2245 {
2246 DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
2247 NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
2248 NOTE_ERROR ();
2249 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2250 p_IRP->IoStatus.Information = 0;
2251 }
2252
2253 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2254 break;
2255 }
2256
2257 //-----------------------------------------------------------
2258 // User mode thread called CloseHandle() on the tap device
2259 //-----------------------------------------------------------
2260 case IRP_MJ_CLOSE:
2261 {
2262 BOOLEAN mutex_succeeded;
2263
2264 DEBUGP (("[%s] [TAP] release [%d.%d] close/cleanup request\n",
2265 NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION,
2266 TAP_DRIVER_MINOR_VERSION));
2267
2268 ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded);
2269 if (mutex_succeeded)
2270 {
2271 l_Adapter->m_Extension.m_TapOpens = 0;
2272 ResetTapAdapterState (l_Adapter);
2273 FlushQueues (&l_Adapter->m_Extension);
2274 SetMediaStatus (l_Adapter, FALSE);
2275 RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex);
2276 }
2277 else
2278 {
2279 DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
2280 NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
2281 NOTE_ERROR ();
2282 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2283 p_IRP->IoStatus.Information = 0;
2284 }
2285
2286 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2287 break;
2288 }
2289
2290 //------------------
2291 // Strange Request
2292 //------------------
2293 default:
2294 {
2295 //NOTE_ERROR ();
2296 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2297 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2298 break;
2299 }
2300 }
2301
2302 return l_Status;
2303}
2304
2305//=============================================================
2306// CompleteIRP is normally called with an adapter -> userspace
2307// network packet and an IRP (Pending I/O request) from userspace.
2308//
2309// The IRP will normally represent a queued overlapped read
2310// operation from userspace that is in a wait state.
2311//
2312// Use the ethernet packet to satisfy the IRP.
2313//=============================================================
2314
2315NTSTATUS
2316CompleteIRP (IN PIRP p_IRP,
2317 IN TapPacketPointer p_PacketBuffer,
2318 IN CCHAR PriorityBoost)
2319{
2320 NTSTATUS l_Status = STATUS_UNSUCCESSFUL;
2321
2322 int offset;
2323 int len;
2324
2325 MYASSERT (p_IRP);
2326 MYASSERT (p_PacketBuffer);
2327
2328 IoSetCancelRoutine (p_IRP, NULL); // Disable cancel routine
2329
2330 //-------------------------------------------
2331 // While p_PacketBuffer always contains a
2332 // full ethernet packet, including the
2333 // ethernet header, in point-to-point mode,
2334 // we only want to return the IPv4
2335 // component.
2336 //-------------------------------------------
2337
2338 if (p_PacketBuffer->m_SizeFlags & TP_POINT_TO_POINT)
2339 {
2340 offset = ETHERNET_HEADER_SIZE;
2341 len = (int) (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK) - ETHERNET_HEADER_SIZE;
2342 }
2343 else
2344 {
2345 offset = 0;
2346 len = (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK);
2347 }
2348
2349 if (len < 0 || (int) p_IRP->IoStatus.Information < len)
2350 {
2351 p_IRP->IoStatus.Information = 0;
2352 p_IRP->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
2353 NOTE_ERROR ();
2354 }
2355 else
2356 {
2357 p_IRP->IoStatus.Information = len;
2358 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2359
2360 __try
2361 {
2362 NdisMoveMemory (p_IRP->AssociatedIrp.SystemBuffer,
2363 p_PacketBuffer->m_Data + offset,
2364 len);
2365 }
2366 __except (EXCEPTION_EXECUTE_HANDLER)
2367 {
2368 NOTE_ERROR ();
2369 p_IRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
2370 p_IRP->IoStatus.Information = 0;
2371 }
2372 }
2373
2374 __try
2375 {
2376 NdisFreeMemory (p_PacketBuffer,
2377 TAP_PACKET_SIZE (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK),
2378 0);
2379 }
2380 __except (EXCEPTION_EXECUTE_HANDLER)
2381 {
2382 }
2383
2384 if (l_Status == STATUS_SUCCESS)
2385 {
2386 IoCompleteRequest (p_IRP, PriorityBoost);
2387 }
2388 else
2389 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2390
2391 return l_Status;
2392}
2393
2394//==============================================
2395// IRPs get cancelled for a number of reasons.
2396//
2397// The TAP device could be closed by userspace
2398// when there are still pending read operations.
2399//
2400// The user could disable the TAP adapter in the
2401// network connections control panel, while the
2402// device is still open by a process.
2403//==============================================
2404VOID
2405CancelIRPCallback (IN PDEVICE_OBJECT p_DeviceObject,
2406 IN PIRP p_IRP)
2407{
2408 TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject);
2409 CancelIRP (l_Adapter ? &l_Adapter->m_Extension : NULL, p_IRP, TRUE);
2410}
2411
2412VOID
2413CancelIRP (TapExtensionPointer p_Extension,
2414 IN PIRP p_IRP,
2415 BOOLEAN callback)
2416{
2417 BOOLEAN exists = FALSE;
2418
2419 MYASSERT (p_IRP);
2420
2421 if (p_Extension)
2422 {
2423 NdisAcquireSpinLock (&p_Extension->m_QueueLock);
2424 exists = (QueueExtract (p_Extension->m_IrpQueue, p_IRP) == p_IRP);
2425 NdisReleaseSpinLock (&p_Extension->m_QueueLock);
2426 }
2427 else
2428 exists = TRUE;
2429
2430 if (exists)
2431 {
2432 IoSetCancelRoutine (p_IRP, NULL);
2433 p_IRP->IoStatus.Status = STATUS_CANCELLED;
2434 p_IRP->IoStatus.Information = 0;
2435 }
2436
2437 if (callback)
2438 IoReleaseCancelSpinLock (p_IRP->CancelIrql);
2439
2440 if (exists)
2441 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2442}
2443
2444//====================================
2445// Exhaust packet and IRP queues.
2446//====================================
2447VOID
2448FlushQueues (TapExtensionPointer p_Extension)
2449{
2450 PIRP l_IRP;
2451 TapPacketPointer l_PacketBuffer;
2452 int n_IRP=0, n_Packet=0;
2453
2454 MYASSERT (p_Extension);
2455 MYASSERT (p_Extension->m_TapDevice);
2456
2457 while (TRUE)
2458 {
2459 NdisAcquireSpinLock (&p_Extension->m_QueueLock);
2460 l_IRP = QueuePop (p_Extension->m_IrpQueue);
2461 NdisReleaseSpinLock (&p_Extension->m_QueueLock);
2462 if (l_IRP)
2463 {
2464 ++n_IRP;
2465 CancelIRP (NULL, l_IRP, FALSE);
2466 }
2467 else
2468 break;
2469 }
2470
2471 while (TRUE)
2472 {
2473 NdisAcquireSpinLock (&p_Extension->m_QueueLock);
2474 l_PacketBuffer = QueuePop (p_Extension->m_PacketQueue);
2475 NdisReleaseSpinLock (&p_Extension->m_QueueLock);
2476 if (l_PacketBuffer)
2477 {
2478 ++n_Packet;
2479 MemFree (l_PacketBuffer, TAP_PACKET_SIZE (l_PacketBuffer->m_SizeFlags & TP_SIZE_MASK));
2480 }
2481 else
2482 break;
2483 }
2484
2485 DEBUGP ((
2486 "[%s] [TAP] FlushQueues n_IRP=[%d,%d,%d] n_Packet=[%d,%d,%d]\n",
2487 p_Extension->m_TapName,
2488 n_IRP,
2489 p_Extension->m_IrpQueue->max_size,
2490 IRP_QUEUE_SIZE,
2491 n_Packet,
2492 p_Extension->m_PacketQueue->max_size,
2493 PACKET_QUEUE_SIZE
2494 ));
2495}
2496
2497//===================================================
2498// Tell Windows whether the TAP device should be
2499// considered "connected" or "disconnected".
2500//===================================================
2501VOID
2502SetMediaStatus (TapAdapterPointer p_Adapter, BOOLEAN state)
2503{
2504 if (p_Adapter->m_MediaState != state && !p_Adapter->m_MediaStateAlwaysConnected)
2505 {
2506 if (state)
2507 NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle,
2508 NDIS_STATUS_MEDIA_CONNECT, NULL, 0);
2509 else
2510 NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle,
2511 NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0);
2512
2513 NdisMIndicateStatusComplete (p_Adapter->m_MiniportAdapterHandle);
2514 p_Adapter->m_MediaState = state;
2515 }
2516}
2517
2518
2519//======================================================
2520// If DHCP mode is used together with Point-to-point
2521// mode, consider the fact that the P2P remote endpoint
2522// might be equal to the DHCP masq server address.
2523//======================================================
2524VOID
2525CheckIfDhcpAndPointToPointMode (TapAdapterPointer p_Adapter)
2526{
2527 if (p_Adapter->m_PointToPoint && p_Adapter->m_dhcp_enabled)
2528 {
2529 if (p_Adapter->m_dhcp_server_ip == p_Adapter->m_remoteIP)
2530 {
2531 COPY_MAC (p_Adapter->m_dhcp_server_mac, p_Adapter->m_TapToUser.dest);
2532 p_Adapter->m_dhcp_server_arp = FALSE;
2533 }
2534 }
2535}
2536
2537//===================================================
2538// Generate an ARP reply message for specific kinds
2539// ARP queries.
2540//===================================================
2541BOOLEAN
2542ProcessARP (TapAdapterPointer p_Adapter,
2543 const PARP_PACKET src,
2544 const IPADDR adapter_ip,
2545 const IPADDR ip,
2546 const MACADDR mac)
2547{
2548 //-----------------------------------------------
2549 // Is this the kind of packet we are looking for?
2550 //-----------------------------------------------
2551 if (src->m_Proto == htons (ETH_P_ARP)
2552 && MAC_EQUAL (src->m_MAC_Source, p_Adapter->m_MAC)
2553 && MAC_EQUAL (src->m_ARP_MAC_Source, p_Adapter->m_MAC)
2554 && MAC_EQUAL (src->m_MAC_Destination, p_Adapter->m_MAC_Broadcast)
2555 && src->m_ARP_Operation == htons (ARP_REQUEST)
2556 && src->m_MAC_AddressType == htons (MAC_ADDR_TYPE)
2557 && src->m_MAC_AddressSize == sizeof (MACADDR)
2558 && src->m_PROTO_AddressType == htons (ETH_P_IP)
2559 && src->m_PROTO_AddressSize == sizeof (IPADDR)
2560 && src->m_ARP_IP_Source == adapter_ip
2561 && src->m_ARP_IP_Destination == ip)
2562 {
2563 ARP_PACKET *arp = (ARP_PACKET *) MemAlloc (sizeof (ARP_PACKET), TRUE);
2564 if (arp)
2565 {
2566 //----------------------------------------------
2567 // Initialize ARP reply fields
2568 //----------------------------------------------
2569 arp->m_Proto = htons (ETH_P_ARP);
2570 arp->m_MAC_AddressType = htons (MAC_ADDR_TYPE);
2571 arp->m_PROTO_AddressType = htons (ETH_P_IP);
2572 arp->m_MAC_AddressSize = sizeof (MACADDR);
2573 arp->m_PROTO_AddressSize = sizeof (IPADDR);
2574 arp->m_ARP_Operation = htons (ARP_REPLY);
2575
2576 //----------------------------------------------
2577 // ARP addresses
2578 //----------------------------------------------
2579 COPY_MAC (arp->m_MAC_Source, mac);
2580 COPY_MAC (arp->m_MAC_Destination, p_Adapter->m_MAC);
2581 COPY_MAC (arp->m_ARP_MAC_Source, mac);
2582 COPY_MAC (arp->m_ARP_MAC_Destination, p_Adapter->m_MAC);
2583 arp->m_ARP_IP_Source = ip;
2584 arp->m_ARP_IP_Destination = adapter_ip;
2585
2586 DUMP_PACKET ("ProcessARP",
2587 (unsigned char *) arp,
2588 sizeof (ARP_PACKET));
2589
2590 InjectPacket (p_Adapter, (UCHAR *) arp, sizeof (ARP_PACKET));
2591
2592 MemFree (arp, sizeof (ARP_PACKET));
2593 }
2594
2595 return TRUE;
2596 }
2597 else
2598 return FALSE;
2599}
2600
2601//===============================================================
2602// Used in cases where internally generated packets such as
2603// ARP or DHCP replies must be returned to the kernel, to be
2604// seen as an incoming packet "arriving" on the interface.
2605//===============================================================
2606
2607VOID
2608InjectPacket (TapAdapterPointer p_Adapter,
2609 UCHAR *packet,
2610 const unsigned int len)
2611{
2612 MYASSERT (len >= ETHERNET_HEADER_SIZE);
2613
2614 __try
2615 {
2616 //------------------------------------------------------------
2617 // NdisMEthIndicateReceive and NdisMEthIndicateReceiveComplete
2618 // could potentially be called reentrantly both here and in
2619 // TapDeviceHook/IRP_MJ_WRITE.
2620 //
2621 // The DDK docs imply that this is okay.
2622 //------------------------------------------------------------
2623 NdisMEthIndicateReceive
2624 (p_Adapter->m_MiniportAdapterHandle,
2625 (NDIS_HANDLE) p_Adapter,
2626 packet,
2627 ETHERNET_HEADER_SIZE,
2628 packet + ETHERNET_HEADER_SIZE,
2629 len - ETHERNET_HEADER_SIZE,
2630 len - ETHERNET_HEADER_SIZE);
2631
2632 NdisMEthIndicateReceiveComplete (p_Adapter->m_MiniportAdapterHandle);
2633 }
2634 __except (EXCEPTION_EXECUTE_HANDLER)
2635 {
2636 DEBUGP (("[%s] NdisMEthIndicateReceive failed in InjectPacket\n",
2637 NAME (p_Adapter)));
2638 NOTE_ERROR ();
2639 }
2640}
2641
2642//===================================================================
2643// Go back to default TAP mode from Point-To-Point mode.
2644// Also reset (i.e. disable) DHCP Masq mode.
2645//===================================================================
2646VOID ResetTapAdapterState (TapAdapterPointer p_Adapter)
2647{
2648 // Point-To-Point
2649 p_Adapter->m_PointToPoint = FALSE;
2650 p_Adapter->m_localIP = 0;
2651 p_Adapter->m_remoteIP = 0;
2652 NdisZeroMemory (&p_Adapter->m_TapToUser, sizeof (p_Adapter->m_TapToUser));
2653 NdisZeroMemory (&p_Adapter->m_UserToTap, sizeof (p_Adapter->m_UserToTap));
2654
2655 // DHCP Masq
2656 p_Adapter->m_dhcp_enabled = FALSE;
2657 p_Adapter->m_dhcp_server_arp = FALSE;
2658 p_Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
2659 p_Adapter->m_dhcp_addr = 0;
2660 p_Adapter->m_dhcp_netmask = 0;
2661 p_Adapter->m_dhcp_server_ip = 0;
2662 p_Adapter->m_dhcp_lease_time = 0;
2663 p_Adapter->m_dhcp_received_discover = FALSE;
2664 p_Adapter->m_dhcp_bad_requests = 0;
2665 NdisZeroMemory (p_Adapter->m_dhcp_server_mac, sizeof (MACADDR));
2666}
2667//======================================================================
2668// End of Source
2669//======================================================================
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette