summaryrefslogtreecommitdiff
path: root/windows/TapDriver6/adapter.h
blob: 0ebaaea76fe7c440d4166408f0602dc790fda0e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
/*
 *  TAP-Windows -- A kernel driver to provide virtual tap
 *                 device functionality on Windows.
 *
 *  This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
 *
 *  This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc.,
 *  and is released under the GPL version 2 (see below).
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2
 *  as published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program (see the file COPYING included with this
 *  distribution); if not, write to the Free Software Foundation, Inc.,
 *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#ifndef __TAP_ADAPTER_CONTEXT_H_
#define __TAP_ADAPTER_CONTEXT_H_

#include "tap.h"

// Memory allocation tags.
#define TAP_ADAPTER_TAG             ((ULONG)'ApaT')     // "TapA
#define TAP_RX_NBL_TAG              ((ULONG)'RpaT')     // "TapR
#define TAP_RX_INJECT_BUFFER_TAG    ((ULONG)'IpaT')     // "TapI

#define TAP_MAX_NDIS_NAME_LENGTH     64     // 38 character GUID string plus extra..

// TAP receive indication NBL flag definitions.
#define TAP_RX_NBL_FLAGS                    NBL_FLAGS_MINIPORT_RESERVED
#define TAP_RX_NBL_FLAGS_CLEAR_ALL(_NBL)    ((_NBL)->Flags &= ~TAP_RX_NBL_FLAGS)
#define TAP_RX_NBL_FLAG_SET(_NBL, _F)       ((_NBL)->Flags |= ((_F) & TAP_RX_NBL_FLAGS))
#define TAP_RX_NBL_FLAG_CLEAR(_NBL, _F)     ((_NBL)->Flags &= ~((_F) & TAP_RX_NBL_FLAGS))
#define TAP_RX_NBL_FLAG_TEST(_NBL, _F)      (((_NBL)->Flags & ((_F) & TAP_RX_NBL_FLAGS)) != 0)

#define TAP_RX_NBL_FLAGS_IS_P2P             0x00001000
#define TAP_RX_NBL_FLAGS_IS_INJECTED        0x00002000

// MSDN Ref: http://msdn.microsoft.com/en-us/library/windows/hardware/ff560490(v=vs.85).aspx
typedef
enum _TAP_MINIPORT_ADAPTER_STATE
{
    // The Halted state is the initial state of all adapters. When an
    // adapter is in the Halted state, NDIS can call the driver's
    // MiniportInitializeEx function to initialize the adapter.
    MiniportHaltedState,

    // In the Shutdown state, a system shutdown and restart must occur
    // before the system can use the adapter again.
    MiniportShutdownState,

    // In the Initializing state, a miniport driver completes any
    //operations that are required to initialize an adapter.
    MiniportInitializingState,

    // Entering the Paused state...
    MiniportPausingState,

    // In the Paused state, the adapter does not indicate received
    // network data or accept send requests.
    MiniportPausedState,

    // In the Running state, a miniport driver performs send and
    // receive processing for an adapter.
    MiniportRunning,

    // In the Restarting state, a miniport driver completes any
    // operations that are required to restart send and receive
    // operations for an adapter.
    MiniportRestartingState
} TAP_MINIPORT_ADAPTER_STATE, *PTAP_MINIPORT_ADAPTER_STATE;

//
// Each adapter managed by this driver has a TapAdapter struct.
// ------------------------------------------------------------
// Since there is a one-to-one relationship between adapter instances
// and device instances this structure is the device extension as well.
//
typedef struct _TAP_ADAPTER_CONTEXT
{
    LIST_ENTRY                  AdapterListLink;

    volatile LONG               RefCount;

    NDIS_HANDLE                 MiniportAdapterHandle;

    NDIS_SPIN_LOCK              AdapterLock;    // Lock for protection of state and outstanding sends and recvs

    //
    // All fields that are protected by the AdapterLock are included
    // in the Locked structure to remind us to take the Lock
    // before accessing them :)
    //
    struct
    {
        TAP_MINIPORT_ADAPTER_STATE  AdapterState;
    } Locked;

    BOOLEAN                     ResetInProgress;

    //
    // NetCfgInstanceId as UNICODE_STRING
    // ----------------------------------
    // This a GUID string provided by NDIS that identifies the adapter instance.
    // An example is:
    // 
    //    NetCfgInstanceId={410EB49D-2381-4FE7-9B36-498E22619DF0}
    //
    // Other names are derived from NetCfgInstanceId. For example, MiniportName:
    //
    //    MiniportName=\DEVICE\{410EB49D-2381-4FE7-9B36-498E22619DF0}
    //
    NDIS_STRING                 NetCfgInstanceId;
    WCHAR                       NetCfgInstanceIdBuffer[TAP_MAX_NDIS_NAME_LENGTH];

# define MINIPORT_INSTANCE_ID(a) ((a)->NetCfgInstanceIdAnsi.Buffer)
    ANSI_STRING                 NetCfgInstanceIdAnsi;   // Used occasionally

    ULONG                       MtuSize;        // 1500 byte (typical)

    // TRUE if adapter should always be "connected" even when device node
    // is not open by a userspace process.
    //
    // FALSE if connection state is application controlled.
    BOOLEAN                     MediaStateAlwaysConnected;

    // TRUE if device is "connected".
    BOOLEAN                     LogicalMediaState;

    NDIS_DEVICE_POWER_STATE     CurrentPowerState;

    BOOLEAN                     AllowNonAdmin;

    MACADDR                     PermanentAddress;   // From registry, if available
    MACADDR                     CurrentAddress;

    // Device registration parameters from NdisRegisterDeviceEx.
    NDIS_STRING                 DeviceName;
    WCHAR                       DeviceNameBuffer[TAP_MAX_NDIS_NAME_LENGTH];

    NDIS_STRING                 LinkName;
    WCHAR                       LinkNameBuffer[TAP_MAX_NDIS_NAME_LENGTH];

    NDIS_HANDLE                 DeviceHandle;
    PDEVICE_OBJECT              DeviceObject;
    BOOLEAN                     TapDeviceCreated;   // WAS: m_TapIsRunning

    PFILE_OBJECT                TapFileObject;      // Exclusive access
    BOOLEAN                     TapFileIsOpen;      // WAS: m_TapOpens
    LONG                        TapFileOpenCount;   // WAS: m_NumTapOpens

    // Cancel-Safe read IRP queue.
    TAP_IRP_CSQ                 PendingReadIrpQueue;

    // Queue containing TAP packets representing host send NBs. These are
    // waiting to be read by user-mode application.
    TAP_PACKET_QUEUE            SendPacketQueue;

    // NBL pool for making TAP receive indications.
    NDIS_HANDLE                 ReceiveNblPool;

    volatile LONG               ReceiveNblInFlightCount;
#define TAP_WAIT_POLL_LOOP_TIMEOUT  3000    // 3 seconds
    NDIS_EVENT                  ReceiveNblInFlightCountZeroEvent;

	/*
    // Info for point-to-point mode
    BOOLEAN                     m_tun;
    IPADDR                      m_localIP;
    IPADDR                      m_remoteNetwork;
    IPADDR                      m_remoteNetmask;
    ETH_HEADER                  m_TapToUser;
    ETH_HEADER                  m_UserToTap;
    ETH_HEADER                  m_UserToTap_IPv6; // same as UserToTap but proto=ipv6
	*/

	// Info for DHCP server masquerade
	/*
    BOOLEAN                     m_dhcp_enabled;
    IPADDR                      m_dhcp_addr;
    ULONG                       m_dhcp_netmask;
    IPADDR                      m_dhcp_server_ip;
    BOOLEAN                     m_dhcp_server_arp;
    MACADDR                     m_dhcp_server_mac;
    ULONG                       m_dhcp_lease_time;
    UCHAR                       m_dhcp_user_supplied_options_buffer[DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE];
    ULONG                       m_dhcp_user_supplied_options_buffer_len;
    BOOLEAN                     m_dhcp_received_discover;
    ULONG                       m_dhcp_bad_requests;
	*/

    // Multicast list. Fixed size.
    ULONG                       ulMCListSize;
    UCHAR                       MCList[TAP_MAX_MCAST_LIST][MACADDR_SIZE];

    ULONG                       PacketFilter;
    ULONG                       ulLookahead;

    //
    // Statistics
    // -------------------------------------------------------------------------
    //

    // Packet counts
    ULONG64                     FramesRxDirected;
    ULONG64                     FramesRxMulticast;
    ULONG64                     FramesRxBroadcast;
    ULONG64                     FramesTxDirected;
    ULONG64                     FramesTxMulticast;
    ULONG64                     FramesTxBroadcast;

    // Byte counts
    ULONG64                     BytesRxDirected;
    ULONG64                     BytesRxMulticast;
    ULONG64                     BytesRxBroadcast;
    ULONG64                     BytesTxDirected;
    ULONG64                     BytesTxMulticast;
    ULONG64                     BytesTxBroadcast;

    // Count of transmit errors
    ULONG                       TxAbortExcessCollisions;
    ULONG                       TxLateCollisions;
    ULONG                       TxDmaUnderrun;
    ULONG                       TxLostCRS;
    ULONG                       TxOKButDeferred;
    ULONG                       OneRetry;
    ULONG                       MoreThanOneRetry;
    ULONG                       TotalRetries;
    ULONG                       TransmitFailuresOther;

    // Count of receive errors
    ULONG                       RxCrcErrors;
    ULONG                       RxAlignmentErrors;
    ULONG                       RxResourceErrors;
    ULONG                       RxDmaOverrunErrors;
    ULONG                       RxCdtFrames;
    ULONG                       RxRuntErrors;

#if PACKET_TRUNCATION_CHECK
    LONG                        m_RxTrunc, m_TxTrunc;
#endif

  BOOLEAN m_InterfaceIsRunning;
  LONG m_Rx, m_RxErr;
  NDIS_MEDIUM m_Medium;

  // Help to tear down the adapter by keeping
  // some state information on allocated
  // resources.
  BOOLEAN m_CalledAdapterFreeResources;
  BOOLEAN m_RegisteredAdapterShutdownHandler;

} TAP_ADAPTER_CONTEXT, *PTAP_ADAPTER_CONTEXT;

FORCEINLINE
LONG
tapAdapterContextReference(
    __in PTAP_ADAPTER_CONTEXT   Adapter
    )
{
    LONG    refCount = NdisInterlockedIncrement(&Adapter->RefCount);

    ASSERT(refCount>1);     // Cannot dereference a zombie.

    return refCount;
}

VOID
tapAdapterContextFree(
    __in PTAP_ADAPTER_CONTEXT     Adapter
    );

FORCEINLINE
LONG
tapAdapterContextDereference(
    IN PTAP_ADAPTER_CONTEXT     Adapter
    )
{
    LONG    refCount = NdisInterlockedDecrement(&Adapter->RefCount);
    ASSERT(refCount >= 0);
    if (!refCount)
    {
        tapAdapterContextFree(Adapter);
    }

    return refCount;
}

VOID
tapAdapterAcquireLock(
    __in    PTAP_ADAPTER_CONTEXT    Adapter,
    __in    BOOLEAN                 DispatchLevel
    );

VOID
tapAdapterReleaseLock(
    __in    PTAP_ADAPTER_CONTEXT    Adapter,
    __in    BOOLEAN                 DispatchLevel
    );

// Returns with added reference on adapter context.
PTAP_ADAPTER_CONTEXT
tapAdapterContextFromDeviceObject(
    __in PDEVICE_OBJECT DeviceObject
    );

BOOLEAN
tapAdapterReadAndWriteReady(
    __in PTAP_ADAPTER_CONTEXT     Adapter
    );

NDIS_STATUS
tapAdapterSendAndReceiveReady(
    __in PTAP_ADAPTER_CONTEXT     Adapter
    );

ULONG
tapGetNetBufferFrameType(
    __in PNET_BUFFER       NetBuffer
    );

ULONG
tapGetNetBufferCountsFromNetBufferList(
    __in PNET_BUFFER_LIST   NetBufferList,
    __inout_opt PULONG      TotalByteCount      // Of all linked NBs
    );

// Prototypes for standard NDIS miniport entry points
MINIPORT_SET_OPTIONS                AdapterSetOptions;
MINIPORT_INITIALIZE                 AdapterCreate;
MINIPORT_HALT                       AdapterHalt;
MINIPORT_UNLOAD                     TapDriverUnload;
MINIPORT_PAUSE                      AdapterPause;
MINIPORT_RESTART                    AdapterRestart;
MINIPORT_OID_REQUEST                AdapterOidRequest;
MINIPORT_SEND_NET_BUFFER_LISTS      AdapterSendNetBufferLists;
MINIPORT_RETURN_NET_BUFFER_LISTS    AdapterReturnNetBufferLists;
MINIPORT_CANCEL_SEND                AdapterCancelSend;
MINIPORT_CHECK_FOR_HANG             AdapterCheckForHangEx;
MINIPORT_RESET                      AdapterReset;
MINIPORT_DEVICE_PNP_EVENT_NOTIFY    AdapterDevicePnpEventNotify;
MINIPORT_SHUTDOWN                   AdapterShutdownEx;
MINIPORT_CANCEL_OID_REQUEST         AdapterCancelOidRequest;

#endif // __TAP_ADAPTER_CONTEXT_H_