VirtualBox

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

Last change on this file since 2705 was 969, checked in by vboxsync, 18 years ago

allow non admin users to open the TAP driver

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

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