~ubuntu-branches/ubuntu/precise/openvpn/precise-updates

« back to all changes in this revision

Viewing changes to tap-win32/tmp/tapdrvr.c

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2010-10-05 06:21:14 UTC
  • mfrom: (1.1.16 upstream) (10.2.8 sid)
  • Revision ID: james.westby@ubuntu.com-20101005062114-18lyqud9e3p4g735
Tags: 2.1.3-1ubuntu1
* Merge from debian unstable.  Remaining changes:
  + debian/openvpn.init.d:
    - Do not use start-stop-daemon and </dev/null to avoid blocking boot.
    - Show per-VPN result messages.
    - Add "--script-security 2" by default for backwards compatablitiy
  + debian/control: Add lsb-base >= 3.2-14 to allow status_of_proc()

Show diffs side-by-side

added added

removed removed

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