VirtualBox

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

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

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