~ubuntu-branches/ubuntu/saucy/openvpn/saucy-proposed

« back to all changes in this revision

Viewing changes to tap-win32/tapdrvr.c

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2013-05-24 17:42:45 UTC
  • mfrom: (1.1.19) (10.2.22 sid)
  • Revision ID: package-import@ubuntu.com-20130524174245-g9y6wlforycufqy5
Tags: 2.3.1-2ubuntu1
* 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 compatabliity.

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