VirtualBox

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

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

TAP update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 74.2 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 default:
1885 {
1886 NOTE_ERROR ();
1887 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1888 break;
1889 }
1890 }
1891
1892 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1893 break;
1894 }
1895
1896 //===========================================================
1897 // User mode thread issued a read request on the tap device
1898 // If there are packets waiting to be read, then the request
1899 // will be satisfied here. If not, then the request will be
1900 // queued and satisfied by any packet that is not used to
1901 // satisfy requests ahead of it.
1902 //===========================================================
1903 case IRP_MJ_READ:
1904 {
1905 TapPacketPointer l_PacketBuffer;
1906 BOOLEAN pending = FALSE;
1907
1908 // Save IRP-accessible copy of buffer length
1909 p_IRP->IoStatus.Information = l_IrpSp->Parameters.Read.Length;
1910
1911 if (p_IRP->MdlAddress == NULL)
1912 {
1913 DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_READ\n",
1914 NAME (l_Adapter)));
1915 NOTE_ERROR ();
1916 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
1917 p_IRP->IoStatus.Information = 0;
1918 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1919 break;
1920 }
1921 else if ((p_IRP->AssociatedIrp.SystemBuffer =
1922 MmGetSystemAddressForMdlSafe
1923 (p_IRP->MdlAddress, NormalPagePriority)) == NULL)
1924 {
1925 DEBUGP (("[%s] Could not map address in IRP_MJ_READ\n",
1926 NAME (l_Adapter)));
1927 NOTE_ERROR ();
1928 p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES;
1929 p_IRP->IoStatus.Information = 0;
1930 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1931 break;
1932 }
1933 else if (!l_Adapter->m_InterfaceIsRunning)
1934 {
1935 DEBUGP (("[%s] Interface is down in IRP_MJ_READ\n",
1936 NAME (l_Adapter)));
1937 NOTE_ERROR ();
1938 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
1939 p_IRP->IoStatus.Information = 0;
1940 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1941 break;
1942 }
1943
1944 //==================================
1945 // Can we provide immediate service?
1946 //==================================
1947
1948 l_PacketBuffer = NULL;
1949
1950 NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
1951
1952 if (IS_UP (l_Adapter)
1953 && QueueCount (l_Adapter->m_Extension.m_PacketQueue)
1954 && QueueCount (l_Adapter->m_Extension.m_IrpQueue) == 0)
1955 {
1956 l_PacketBuffer = (TapPacketPointer)
1957 QueuePop (l_Adapter->m_Extension.m_PacketQueue);
1958 }
1959
1960 NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
1961
1962 if (l_PacketBuffer)
1963 {
1964 l_Status = CompleteIRP (p_IRP,
1965 l_PacketBuffer,
1966 IO_NO_INCREMENT);
1967 break;
1968 }
1969
1970 //=============================
1971 // Attempt to pend read request
1972 //=============================
1973
1974 NdisAcquireSpinLock (&l_Adapter->m_Extension.m_QueueLock);
1975
1976 if (IS_UP (l_Adapter)
1977 && QueuePush (l_Adapter->m_Extension.m_IrpQueue, p_IRP) == (PIRP) p_IRP)
1978 {
1979 IoSetCancelRoutine (p_IRP, CancelIRPCallback);
1980 l_Status = STATUS_PENDING;
1981 IoMarkIrpPending (p_IRP);
1982 pending = TRUE;
1983 }
1984
1985 NdisReleaseSpinLock (&l_Adapter->m_Extension.m_QueueLock);
1986
1987 if (pending)
1988 break;
1989
1990 // Can't queue anymore IRP's
1991 DEBUGP (("[%s] TAP [%s] read IRP overrun\n",
1992 NAME (l_Adapter), l_Adapter->m_Extension.m_TapName));
1993 NOTE_ERROR ();
1994 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
1995 p_IRP->IoStatus.Information = 0;
1996 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
1997 break;
1998 }
1999
2000 //==============================================================
2001 // User mode issued a WriteFile request on the TAP file handle.
2002 // The request will always get satisfied here. The call may
2003 // fail if there are too many pending packets (queue full).
2004 //==============================================================
2005 case IRP_MJ_WRITE:
2006 {
2007 if (p_IRP->MdlAddress == NULL)
2008 {
2009 DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n",
2010 NAME (l_Adapter)));
2011 NOTE_ERROR ();
2012 p_IRP->IoStatus.Status = l_Status = STATUS_INVALID_PARAMETER;
2013 p_IRP->IoStatus.Information = 0;
2014 }
2015 else if ((p_IRP->AssociatedIrp.SystemBuffer =
2016 MmGetSystemAddressForMdlSafe
2017 (p_IRP->MdlAddress, NormalPagePriority)) == NULL)
2018 {
2019 DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n",
2020 NAME (l_Adapter)));
2021 NOTE_ERROR ();
2022 p_IRP->IoStatus.Status = l_Status = STATUS_INSUFFICIENT_RESOURCES;
2023 p_IRP->IoStatus.Information = 0;
2024 }
2025 else if (!l_Adapter->m_InterfaceIsRunning)
2026 {
2027 DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n",
2028 NAME (l_Adapter)));
2029 NOTE_ERROR ();
2030 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2031 p_IRP->IoStatus.Information = 0;
2032 }
2033 else if (!l_Adapter->m_PointToPoint && ((l_IrpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE))
2034 {
2035 __try
2036 {
2037 p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length;
2038
2039 ////DEBUGP(("IRP_MJ_WRITE %08x %x\n", p_IRP->AssociatedIrp.SystemBuffer, l_IrpSp->Parameters.Write.Length));
2040
2041 DUMP_PACKET ("IRP_MJ_WRITE ETH",
2042 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2043 l_IrpSp->Parameters.Write.Length);
2044
2045 NdisMEthIndicateReceive
2046 (l_Adapter->m_MiniportAdapterHandle,
2047 (NDIS_HANDLE) l_Adapter,
2048 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2049 ETHERNET_HEADER_SIZE,
2050 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer + ETHERNET_HEADER_SIZE,
2051 l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE,
2052 l_IrpSp->Parameters.Write.Length - ETHERNET_HEADER_SIZE);
2053
2054 NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle);
2055
2056 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2057 }
2058 __except (EXCEPTION_EXECUTE_HANDLER)
2059 {
2060 DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE\n",
2061 NAME (l_Adapter)));
2062 NOTE_ERROR ();
2063 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2064 p_IRP->IoStatus.Information = 0;
2065 }
2066 }
2067 else if (l_Adapter->m_PointToPoint && ((l_IrpSp->Parameters.Write.Length) >= IP_HEADER_SIZE))
2068 {
2069 __try
2070 {
2071 p_IRP->IoStatus.Information = l_IrpSp->Parameters.Write.Length;
2072
2073 DUMP_PACKET2 ("IRP_MJ_WRITE P2P",
2074 &l_Adapter->m_UserToTap,
2075 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2076 l_IrpSp->Parameters.Write.Length);
2077
2078 NdisMEthIndicateReceive
2079 (l_Adapter->m_MiniportAdapterHandle,
2080 (NDIS_HANDLE) l_Adapter,
2081 (unsigned char *) &l_Adapter->m_UserToTap,
2082 sizeof (l_Adapter->m_UserToTap),
2083 (unsigned char *) p_IRP->AssociatedIrp.SystemBuffer,
2084 l_IrpSp->Parameters.Write.Length,
2085 l_IrpSp->Parameters.Write.Length);
2086
2087 NdisMEthIndicateReceiveComplete (l_Adapter->m_MiniportAdapterHandle);
2088
2089 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2090 }
2091 __except (EXCEPTION_EXECUTE_HANDLER)
2092 {
2093 DEBUGP (("[%s] NdisMEthIndicateReceive failed in IRP_MJ_WRITE (P2P)\n",
2094 NAME (l_Adapter)));
2095 NOTE_ERROR ();
2096 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2097 p_IRP->IoStatus.Information = 0;
2098 }
2099 }
2100 else
2101 {
2102 DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n",
2103 NAME (l_Adapter),
2104 l_IrpSp->Parameters.Write.Length));
2105 NOTE_ERROR ();
2106 p_IRP->IoStatus.Information = 0; // ETHERNET_HEADER_SIZE;
2107 p_IRP->IoStatus.Status = l_Status = STATUS_BUFFER_TOO_SMALL;
2108 }
2109
2110 if (l_Status == STATUS_SUCCESS)
2111 INCREMENT_STAT (l_Adapter->m_Rx);
2112 else
2113 INCREMENT_STAT (l_Adapter->m_RxErr);
2114
2115 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2116 break;
2117 }
2118
2119 //--------------------------------------------------------------
2120 // User mode thread has called CreateFile() on the tap device
2121 //--------------------------------------------------------------
2122 case IRP_MJ_CREATE:
2123 {
2124 BOOLEAN succeeded = FALSE;
2125 BOOLEAN mutex_succeeded;
2126
2127 DEBUGP
2128 (("[%s] [TAP] release [%d.%d] open request (m_TapOpens=%d)\n",
2129 NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION,
2130 TAP_DRIVER_MINOR_VERSION, l_Adapter->m_Extension.m_TapOpens));
2131
2132 ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded);
2133 if (mutex_succeeded)
2134 {
2135 if (l_Adapter->m_Extension.m_TapIsRunning && !l_Adapter->m_Extension.m_TapOpens)
2136 {
2137 ResetTapAdapterState (l_Adapter);
2138 l_Adapter->m_Extension.m_TapOpens = 1;
2139 succeeded = TRUE;
2140 }
2141
2142 if (succeeded)
2143 {
2144 INCREMENT_STAT (l_Adapter->m_Extension.m_NumTapOpens);
2145 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2146 p_IRP->IoStatus.Information = 0;
2147 }
2148 else
2149 {
2150 DEBUGP (("[%s] TAP is presently unavailable (m_TapOpens=%d)\n",
2151 NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
2152 NOTE_ERROR ();
2153 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2154 p_IRP->IoStatus.Information = 0;
2155 }
2156
2157 RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex);
2158 }
2159 else
2160 {
2161 DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
2162 NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
2163 NOTE_ERROR ();
2164 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2165 p_IRP->IoStatus.Information = 0;
2166 }
2167
2168 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2169 break;
2170 }
2171
2172 //-----------------------------------------------------------
2173 // User mode thread called CloseHandle() on the tap device
2174 //-----------------------------------------------------------
2175 case IRP_MJ_CLOSE:
2176 {
2177 BOOLEAN mutex_succeeded;
2178
2179 DEBUGP (("[%s] [TAP] release [%d.%d] close/cleanup request\n",
2180 NAME (l_Adapter), TAP_DRIVER_MAJOR_VERSION,
2181 TAP_DRIVER_MINOR_VERSION));
2182
2183 ACQUIRE_MUTEX_ADAPTIVE (&l_Adapter->m_Extension.m_OpenCloseMutex, mutex_succeeded);
2184 if (mutex_succeeded)
2185 {
2186 l_Adapter->m_Extension.m_TapOpens = 0;
2187 ResetTapAdapterState (l_Adapter);
2188 FlushQueues (&l_Adapter->m_Extension);
2189 SetMediaStatus (l_Adapter, FALSE);
2190 RELEASE_MUTEX (&l_Adapter->m_Extension.m_OpenCloseMutex);
2191 }
2192 else
2193 {
2194 DEBUGP (("[%s] TAP is presently locked (m_TapOpens=%d)\n",
2195 NAME (l_Adapter), l_Adapter->m_Extension.m_TapOpens));
2196 NOTE_ERROR ();
2197 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2198 p_IRP->IoStatus.Information = 0;
2199 }
2200
2201 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2202 break;
2203 }
2204
2205 //------------------
2206 // Strange Request
2207 //------------------
2208 default:
2209 {
2210 //NOTE_ERROR ();
2211 p_IRP->IoStatus.Status = l_Status = STATUS_UNSUCCESSFUL;
2212 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2213 break;
2214 }
2215 }
2216
2217 return l_Status;
2218}
2219
2220//=============================================================
2221// CompleteIRP is normally called with an adapter -> userspace
2222// network packet and an IRP (Pending I/O request) from userspace.
2223//
2224// The IRP will normally represent a queued overlapped read
2225// operation from userspace that is in a wait state.
2226//
2227// Use the ethernet packet to satisfy the IRP.
2228//=============================================================
2229
2230NTSTATUS
2231CompleteIRP (IN PIRP p_IRP,
2232 IN TapPacketPointer p_PacketBuffer,
2233 IN CCHAR PriorityBoost)
2234{
2235 NTSTATUS l_Status = STATUS_UNSUCCESSFUL;
2236
2237 int offset;
2238 int len;
2239
2240 MYASSERT (p_IRP);
2241 MYASSERT (p_PacketBuffer);
2242
2243 IoSetCancelRoutine (p_IRP, NULL); // Disable cancel routine
2244
2245 //-------------------------------------------
2246 // While p_PacketBuffer always contains a
2247 // full ethernet packet, including the
2248 // ethernet header, in point-to-point mode,
2249 // we only want to return the IPv4
2250 // component.
2251 //-------------------------------------------
2252
2253 if (p_PacketBuffer->m_SizeFlags & TP_POINT_TO_POINT)
2254 {
2255 offset = ETHERNET_HEADER_SIZE;
2256 len = (int) (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK) - ETHERNET_HEADER_SIZE;
2257 }
2258 else
2259 {
2260 offset = 0;
2261 len = (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK);
2262 }
2263
2264 if (len < 0 || (int) p_IRP->IoStatus.Information < len)
2265 {
2266 p_IRP->IoStatus.Information = 0;
2267 p_IRP->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
2268 NOTE_ERROR ();
2269 }
2270 else
2271 {
2272 p_IRP->IoStatus.Information = len;
2273 p_IRP->IoStatus.Status = l_Status = STATUS_SUCCESS;
2274
2275 __try
2276 {
2277 NdisMoveMemory (p_IRP->AssociatedIrp.SystemBuffer,
2278 p_PacketBuffer->m_Data + offset,
2279 len);
2280 }
2281 __except (EXCEPTION_EXECUTE_HANDLER)
2282 {
2283 NOTE_ERROR ();
2284 p_IRP->IoStatus.Status = STATUS_UNSUCCESSFUL;
2285 p_IRP->IoStatus.Information = 0;
2286 }
2287 }
2288
2289 __try
2290 {
2291 NdisFreeMemory (p_PacketBuffer,
2292 TAP_PACKET_SIZE (p_PacketBuffer->m_SizeFlags & TP_SIZE_MASK),
2293 0);
2294 }
2295 __except (EXCEPTION_EXECUTE_HANDLER)
2296 {
2297 }
2298
2299 if (l_Status == STATUS_SUCCESS)
2300 {
2301 IoCompleteRequest (p_IRP, PriorityBoost);
2302 }
2303 else
2304 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2305
2306 return l_Status;
2307}
2308
2309//==============================================
2310// IRPs get cancelled for a number of reasons.
2311//
2312// The TAP device could be closed by userspace
2313// when there are still pending read operations.
2314//
2315// The user could disable the TAP adapter in the
2316// network connections control panel, while the
2317// device is still open by a process.
2318//==============================================
2319VOID
2320CancelIRPCallback (IN PDEVICE_OBJECT p_DeviceObject,
2321 IN PIRP p_IRP)
2322{
2323 TapAdapterPointer l_Adapter = LookupAdapterInInstanceList (p_DeviceObject);
2324 CancelIRP (l_Adapter ? &l_Adapter->m_Extension : NULL, p_IRP, TRUE);
2325}
2326
2327VOID
2328CancelIRP (TapExtensionPointer p_Extension,
2329 IN PIRP p_IRP,
2330 BOOLEAN callback)
2331{
2332 BOOLEAN exists = FALSE;
2333
2334 MYASSERT (p_IRP);
2335
2336 if (p_Extension)
2337 {
2338 NdisAcquireSpinLock (&p_Extension->m_QueueLock);
2339 exists = (QueueExtract (p_Extension->m_IrpQueue, p_IRP) == p_IRP);
2340 NdisReleaseSpinLock (&p_Extension->m_QueueLock);
2341 }
2342 else
2343 exists = TRUE;
2344
2345 if (exists)
2346 {
2347 IoSetCancelRoutine (p_IRP, NULL);
2348 p_IRP->IoStatus.Status = STATUS_CANCELLED;
2349 p_IRP->IoStatus.Information = 0;
2350 }
2351
2352 if (callback)
2353 IoReleaseCancelSpinLock (p_IRP->CancelIrql);
2354
2355 if (exists)
2356 IoCompleteRequest (p_IRP, IO_NO_INCREMENT);
2357}
2358
2359//====================================
2360// Exhaust packet and IRP queues.
2361//====================================
2362VOID
2363FlushQueues (TapExtensionPointer p_Extension)
2364{
2365 PIRP l_IRP;
2366 TapPacketPointer l_PacketBuffer;
2367 int n_IRP=0, n_Packet=0;
2368
2369 MYASSERT (p_Extension);
2370 MYASSERT (p_Extension->m_TapDevice);
2371
2372 while (TRUE)
2373 {
2374 NdisAcquireSpinLock (&p_Extension->m_QueueLock);
2375 l_IRP = QueuePop (p_Extension->m_IrpQueue);
2376 NdisReleaseSpinLock (&p_Extension->m_QueueLock);
2377 if (l_IRP)
2378 {
2379 ++n_IRP;
2380 CancelIRP (NULL, l_IRP, FALSE);
2381 }
2382 else
2383 break;
2384 }
2385
2386 while (TRUE)
2387 {
2388 NdisAcquireSpinLock (&p_Extension->m_QueueLock);
2389 l_PacketBuffer = QueuePop (p_Extension->m_PacketQueue);
2390 NdisReleaseSpinLock (&p_Extension->m_QueueLock);
2391 if (l_PacketBuffer)
2392 {
2393 ++n_Packet;
2394 MemFree (l_PacketBuffer, TAP_PACKET_SIZE (l_PacketBuffer->m_SizeFlags & TP_SIZE_MASK));
2395 }
2396 else
2397 break;
2398 }
2399
2400 DEBUGP ((
2401 "[%s] [TAP] FlushQueues n_IRP=[%d,%d,%d] n_Packet=[%d,%d,%d]\n",
2402 p_Extension->m_TapName,
2403 n_IRP,
2404 p_Extension->m_IrpQueue->max_size,
2405 IRP_QUEUE_SIZE,
2406 n_Packet,
2407 p_Extension->m_PacketQueue->max_size,
2408 PACKET_QUEUE_SIZE
2409 ));
2410}
2411
2412//===================================================
2413// Tell Windows whether the TAP device should be
2414// considered "connected" or "disconnected".
2415//===================================================
2416VOID
2417SetMediaStatus (TapAdapterPointer p_Adapter, BOOLEAN state)
2418{
2419 if (p_Adapter->m_MediaState != state && !p_Adapter->m_MediaStateAlwaysConnected)
2420 {
2421 if (state)
2422 NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle,
2423 NDIS_STATUS_MEDIA_CONNECT, NULL, 0);
2424 else
2425 NdisMIndicateStatus (p_Adapter->m_MiniportAdapterHandle,
2426 NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0);
2427
2428 NdisMIndicateStatusComplete (p_Adapter->m_MiniportAdapterHandle);
2429 p_Adapter->m_MediaState = state;
2430 }
2431}
2432
2433
2434//======================================================
2435// If DHCP mode is used together with Point-to-point
2436// mode, consider the fact that the P2P remote endpoint
2437// might be equal to the DHCP masq server address.
2438//======================================================
2439VOID
2440CheckIfDhcpAndPointToPointMode (TapAdapterPointer p_Adapter)
2441{
2442 if (p_Adapter->m_PointToPoint && p_Adapter->m_dhcp_enabled)
2443 {
2444 if (p_Adapter->m_dhcp_server_ip == p_Adapter->m_remoteIP)
2445 {
2446 COPY_MAC (p_Adapter->m_dhcp_server_mac, p_Adapter->m_TapToUser.dest);
2447 p_Adapter->m_dhcp_server_arp = FALSE;
2448 }
2449 }
2450}
2451
2452//===================================================
2453// Generate an ARP reply message for specific kinds
2454// ARP queries.
2455//===================================================
2456BOOLEAN
2457ProcessARP (TapAdapterPointer p_Adapter,
2458 const PARP_PACKET src,
2459 const IPADDR adapter_ip,
2460 const IPADDR ip,
2461 const MACADDR mac)
2462{
2463 //-----------------------------------------------
2464 // Is this the kind of packet we are looking for?
2465 //-----------------------------------------------
2466 if (src->m_Proto == htons (ETH_P_ARP)
2467 && MAC_EQUAL (src->m_MAC_Source, p_Adapter->m_MAC)
2468 && MAC_EQUAL (src->m_ARP_MAC_Source, p_Adapter->m_MAC)
2469 && MAC_EQUAL (src->m_MAC_Destination, p_Adapter->m_MAC_Broadcast)
2470 && src->m_ARP_Operation == htons (ARP_REQUEST)
2471 && src->m_MAC_AddressType == htons (MAC_ADDR_TYPE)
2472 && src->m_MAC_AddressSize == sizeof (MACADDR)
2473 && src->m_PROTO_AddressType == htons (ETH_P_IP)
2474 && src->m_PROTO_AddressSize == sizeof (IPADDR)
2475 && src->m_ARP_IP_Source == adapter_ip
2476 && src->m_ARP_IP_Destination == ip)
2477 {
2478 ARP_PACKET *arp = (ARP_PACKET *) MemAlloc (sizeof (ARP_PACKET), TRUE);
2479 if (arp)
2480 {
2481 //----------------------------------------------
2482 // Initialize ARP reply fields
2483 //----------------------------------------------
2484 arp->m_Proto = htons (ETH_P_ARP);
2485 arp->m_MAC_AddressType = htons (MAC_ADDR_TYPE);
2486 arp->m_PROTO_AddressType = htons (ETH_P_IP);
2487 arp->m_MAC_AddressSize = sizeof (MACADDR);
2488 arp->m_PROTO_AddressSize = sizeof (IPADDR);
2489 arp->m_ARP_Operation = htons (ARP_REPLY);
2490
2491 //----------------------------------------------
2492 // ARP addresses
2493 //----------------------------------------------
2494 COPY_MAC (arp->m_MAC_Source, mac);
2495 COPY_MAC (arp->m_MAC_Destination, p_Adapter->m_MAC);
2496 COPY_MAC (arp->m_ARP_MAC_Source, mac);
2497 COPY_MAC (arp->m_ARP_MAC_Destination, p_Adapter->m_MAC);
2498 arp->m_ARP_IP_Source = ip;
2499 arp->m_ARP_IP_Destination = adapter_ip;
2500
2501 DUMP_PACKET ("ProcessARP",
2502 (unsigned char *) arp,
2503 sizeof (ARP_PACKET));
2504
2505 InjectPacket (p_Adapter, (UCHAR *) arp, sizeof (ARP_PACKET));
2506
2507 MemFree (arp, sizeof (ARP_PACKET));
2508 }
2509
2510 return TRUE;
2511 }
2512 else
2513 return FALSE;
2514}
2515
2516//===============================================================
2517// Used in cases where internally generated packets such as
2518// ARP or DHCP replies must be returned to the kernel, to be
2519// seen as an incoming packet "arriving" on the interface.
2520//===============================================================
2521
2522VOID
2523InjectPacket (TapAdapterPointer p_Adapter,
2524 UCHAR *packet,
2525 const unsigned int len)
2526{
2527 MYASSERT (len >= ETHERNET_HEADER_SIZE);
2528
2529 __try
2530 {
2531 //------------------------------------------------------------
2532 // NdisMEthIndicateReceive and NdisMEthIndicateReceiveComplete
2533 // could potentially be called reentrantly both here and in
2534 // TapDeviceHook/IRP_MJ_WRITE.
2535 //
2536 // The DDK docs imply that this is okay.
2537 //------------------------------------------------------------
2538 NdisMEthIndicateReceive
2539 (p_Adapter->m_MiniportAdapterHandle,
2540 (NDIS_HANDLE) p_Adapter,
2541 packet,
2542 ETHERNET_HEADER_SIZE,
2543 packet + ETHERNET_HEADER_SIZE,
2544 len - ETHERNET_HEADER_SIZE,
2545 len - ETHERNET_HEADER_SIZE);
2546
2547 NdisMEthIndicateReceiveComplete (p_Adapter->m_MiniportAdapterHandle);
2548 }
2549 __except (EXCEPTION_EXECUTE_HANDLER)
2550 {
2551 DEBUGP (("[%s] NdisMEthIndicateReceive failed in InjectPacket\n",
2552 NAME (p_Adapter)));
2553 NOTE_ERROR ();
2554 }
2555}
2556
2557//===================================================================
2558// Go back to default TAP mode from Point-To-Point mode.
2559// Also reset (i.e. disable) DHCP Masq mode.
2560//===================================================================
2561VOID ResetTapAdapterState (TapAdapterPointer p_Adapter)
2562{
2563 // Point-To-Point
2564 p_Adapter->m_PointToPoint = FALSE;
2565 p_Adapter->m_localIP = 0;
2566 p_Adapter->m_remoteIP = 0;
2567 NdisZeroMemory (&p_Adapter->m_TapToUser, sizeof (p_Adapter->m_TapToUser));
2568 NdisZeroMemory (&p_Adapter->m_UserToTap, sizeof (p_Adapter->m_UserToTap));
2569
2570 // DHCP Masq
2571 p_Adapter->m_dhcp_enabled = FALSE;
2572 p_Adapter->m_dhcp_server_arp = FALSE;
2573 p_Adapter->m_dhcp_user_supplied_options_buffer_len = 0;
2574 p_Adapter->m_dhcp_addr = 0;
2575 p_Adapter->m_dhcp_netmask = 0;
2576 p_Adapter->m_dhcp_server_ip = 0;
2577 p_Adapter->m_dhcp_lease_time = 0;
2578 p_Adapter->m_dhcp_received_discover = FALSE;
2579 p_Adapter->m_dhcp_bad_requests = 0;
2580 NdisZeroMemory (p_Adapter->m_dhcp_server_mac, sizeof (MACADDR));
2581}
2582//======================================================================
2583// End of Source
2584//======================================================================
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