~ubuntu-branches/ubuntu/hardy/openvpn/hardy-proposed

« back to all changes in this revision

Viewing changes to tap-win32/tapdrvr.c

  • Committer: Bazaar Package Importer
  • Author(s): Alberto Gonzalez Iniesta
  • Date: 2004-06-10 15:59:39 UTC
  • Revision ID: james.westby@ubuntu.com-20040610155939-dcmtiuvcoqnwek62
Tags: upstream-1.6.0
ImportĀ upstreamĀ versionĀ 1.6.0

Show diffs side-by-side

added added

removed removed

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