1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Kernel Device Driver
3
4
5 // Neo6.c
6 // Driver Main Program
7
8 #include <GlobalConst.h>
9
10 #define NEO_DEVICE_DRIVER
11
12 #include "Neo6.h"
13
14 // Whether Win8
15 extern bool g_is_win8;
16
17 // Neo driver context
18 static NEO_CTX static_ctx;
19 NEO_CTX *ctx = &static_ctx;
20
21 // Read the packet data from the transmit packet queue
NeoRead(void * buf)22 void NeoRead(void *buf)
23 {
24 NEO_QUEUE *q;
25 UINT num;
26 BOOL left;
27 // Validate arguments
28 if (buf == NULL)
29 {
30 return;
31 }
32
33 // Copy the packets one by one from the queue
34 num = 0;
35 left = TRUE;
36 NeoLockPacketQueue();
37 {
38 while (TRUE)
39 {
40 if (num >= NEO_MAX_PACKET_EXCHANGE)
41 {
42 if (ctx->PacketQueue == NULL)
43 {
44 left = FALSE;
45 }
46 break;
47 }
48 q = NeoGetNextQueue();
49 if (q == NULL)
50 {
51 left = FALSE;
52 break;
53 }
54 NEO_SIZE_OF_PACKET(buf, num) = q->Size;
55 NeoCopy(NEO_ADDR_OF_PACKET(buf, num), q->Buf, q->Size);
56 num++;
57 NeoFreeQueue(q);
58 }
59 }
60 NeoUnlockPacketQueue();
61
62 NEO_NUM_PACKET(buf) = num;
63 NEO_LEFT_FLAG(buf) = left;
64
65 if (left == FALSE)
66 {
67 NeoReset(ctx->Event);
68 }
69 else
70 {
71 NeoSet(ctx->Event);
72 }
73
74 return;
75 }
76
77 // Process the received packet
NeoWrite(void * buf)78 void NeoWrite(void *buf)
79 {
80 UINT num, i, size;
81 UCHAR *packet_buf;
82 NET_BUFFER_LIST *nbl_chain = NULL;
83 NET_BUFFER_LIST *nbl_tail = NULL;
84 UINT num_nbl_chain = 0;
85 // Validate arguments
86 if (buf == NULL)
87 {
88 return;
89 }
90
91 // Number of packets
92 num = NEO_NUM_PACKET(buf);
93 if (num > NEO_MAX_PACKET_EXCHANGE)
94 {
95 // Number of packets is too many
96 return;
97 }
98 if (num == 0)
99 {
100 // No packet
101 return;
102 }
103
104 if (ctx->Halting != FALSE)
105 {
106 // Stopping
107 return;
108 }
109
110 if (ctx->Paused)
111 {
112 // Paused
113 return;
114 }
115
116 if (ctx->Opened == FALSE)
117 {
118 // Not connected
119 return;
120 }
121
122 for (i = 0;i < num;i++)
123 {
124 PACKET_BUFFER *p = ctx->PacketBuffer[i];
125 void *dst;
126 NET_BUFFER_LIST *nbl = ctx->PacketBuffer[i]->NetBufferList;
127 NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
128
129 nbl->SourceHandle = ctx->NdisMiniport;
130
131 NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL;
132
133 size = NEO_SIZE_OF_PACKET(buf, i);
134 if (size > NEO_MAX_PACKET_SIZE)
135 {
136 size = NEO_MAX_PACKET_SIZE;
137 }
138 if (size < NEO_PACKET_HEADER_SIZE)
139 {
140 size = NEO_PACKET_HEADER_SIZE;
141 }
142
143 packet_buf = (UCHAR *)(NEO_ADDR_OF_PACKET(buf, i));
144
145 if (OK(NdisRetreatNetBufferDataStart(nb, size, 0, NULL)))
146 {
147 // Buffer copy
148 dst = NdisGetDataBuffer(nb,
149 size,
150 NULL,
151 1,
152 0);
153
154 if (dst != NULL)
155 {
156 NeoCopy(dst, packet_buf, size);
157
158 if (nbl_chain == NULL)
159 {
160 nbl_chain = nbl;
161 }
162
163 if (nbl_tail != NULL)
164 {
165 NET_BUFFER_LIST_NEXT_NBL(nbl_tail) = nbl;
166 }
167
168 nbl_tail = nbl;
169
170 num_nbl_chain++;
171 }
172 }
173
174 nbl->Status = NDIS_STATUS_RESOURCES;
175
176 ctx->Status.Int64BytesRecvTotal += (UINT64)size;
177
178 if (packet_buf[0] & 0x40)
179 {
180 ctx->Status.Int64NumRecvBroadcast++;
181 ctx->Status.Int64BytesRecvBroadcast += (UINT64)size;
182 }
183 else
184 {
185 ctx->Status.Int64NumRecvUnicast++;
186 ctx->Status.Int64BytesRecvUnicast += (UINT64)size;
187 }
188 }
189
190 if (nbl_chain == NULL)
191 {
192 return;
193 }
194
195 // Notify that it has received
196 ctx->Status.NumPacketRecv += num_nbl_chain;
197
198 NdisMIndicateReceiveNetBufferLists(ctx->NdisMiniport,
199 nbl_chain, 0, num_nbl_chain, NDIS_RECEIVE_FLAGS_RESOURCES);
200
201 if (true)
202 {
203 // Restore the packet buffer
204 NET_BUFFER_LIST *nbl = nbl_chain;
205
206 while (nbl != NULL)
207 {
208 NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
209
210 if (nb != NULL)
211 {
212 UINT size = NET_BUFFER_DATA_LENGTH(nb);
213
214 NdisAdvanceNetBufferDataStart(nb, size, false, NULL);
215 }
216
217 nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
218 }
219 }
220 }
221
222 // Get the number of queue items
NeoGetNumQueue()223 UINT NeoGetNumQueue()
224 {
225 return ctx->NumPacketQueue;
226 }
227
228 // Insert the queue
NeoInsertQueue(void * buf,UINT size)229 void NeoInsertQueue(void *buf, UINT size)
230 {
231 NEO_QUEUE *p;
232 // Validate arguments
233 if (buf == NULL || size == 0)
234 {
235 return;
236 }
237
238 // Prevent the packet accumulation in large quantities in the queue
239 if (ctx->NumPacketQueue > NEO_MAX_PACKET_QUEUED)
240 {
241 NeoFree(buf);
242 return;
243 }
244
245 // Create a queue
246 p = NeoMalloc(sizeof(NEO_QUEUE));
247 p->Next = NULL;
248 p->Size = size;
249 p->Buf = buf;
250
251 // Append to the queue
252 if (ctx->PacketQueue == NULL)
253 {
254 ctx->PacketQueue = p;
255 }
256 else
257 {
258 NEO_QUEUE *q = ctx->Tail;
259 q->Next = p;
260 }
261
262 ctx->Tail = p;
263
264 ctx->NumPacketQueue++;
265 }
266
267 // Get the next queued item
NeoGetNextQueue()268 NEO_QUEUE *NeoGetNextQueue()
269 {
270 NEO_QUEUE *q;
271 if (ctx->PacketQueue == NULL)
272 {
273 // Empty queue
274 return NULL;
275 }
276
277 // Get the next queued item
278 q = ctx->PacketQueue;
279 ctx->PacketQueue = ctx->PacketQueue->Next;
280 q->Next = NULL;
281 ctx->NumPacketQueue--;
282
283 if (ctx->PacketQueue == NULL)
284 {
285 ctx->Tail = NULL;
286 }
287
288 return q;
289 }
290
291 // Release the buffer of the queue
NeoFreeQueue(NEO_QUEUE * q)292 void NeoFreeQueue(NEO_QUEUE *q)
293 {
294 // Validate arguments
295 if (q == NULL)
296 {
297 return;
298 }
299 NeoFree(q->Buf);
300 NeoFree(q);
301 }
302
303 // Lock the packet queue
NeoLockPacketQueue()304 void NeoLockPacketQueue()
305 {
306 NeoLock(ctx->PacketQueueLock);
307 }
308
309 // Unlock the packet queue
NeoUnlockPacketQueue()310 void NeoUnlockPacketQueue()
311 {
312 NeoUnlock(ctx->PacketQueueLock);
313 }
314
315 // Initialize the packet queue
NeoInitPacketQueue()316 void NeoInitPacketQueue()
317 {
318 // Create a lock
319 ctx->PacketQueueLock = NeoNewLock();
320 // Initialize the packet queue
321 ctx->PacketQueue = NULL;
322 ctx->NumPacketQueue = 0;
323 ctx->Tail = NULL;
324 }
325
326 // Delete all the packets from the packet queue
NeoClearPacketQueue(bool no_lock)327 void NeoClearPacketQueue(bool no_lock)
328 {
329 // Release the memory of the packet queue
330 if (no_lock == false)
331 {
332 NeoLock(ctx->PacketQueueLock);
333 }
334 if (true)
335 {
336 NEO_QUEUE *q = ctx->PacketQueue;
337 NEO_QUEUE *qn;
338 while (q != NULL)
339 {
340 qn = q->Next;
341 NeoFree(q->Buf);
342 NeoFree(q);
343 q = qn;
344 }
345 ctx->PacketQueue = NULL;
346 ctx->Tail = NULL;
347 ctx->NumPacketQueue = 0;
348 }
349 if (no_lock == false)
350 {
351 NeoUnlock(ctx->PacketQueueLock);
352 }
353 }
354
355 // Release the packet queue
NeoFreePacketQueue()356 void NeoFreePacketQueue()
357 {
358 // Delete all packets
359 NeoClearPacketQueue(false);
360
361 // Delete the lock
362 NeoFreeLock(ctx->PacketQueueLock);
363 ctx->PacketQueueLock = NULL;
364 }
365
366 // Start the adapter
NeoStartAdapter()367 void NeoStartAdapter()
368 {
369 // Initialize the packet queue
370 NeoInitPacketQueue();
371 }
372
373 // Stop the adapter
NeoStopAdapter()374 void NeoStopAdapter()
375 {
376 // Delete the packet queue
377 NeoFreePacketQueue();
378 }
379
380 // Initialization
NeoInit()381 BOOL NeoInit()
382 {
383 // Initialize the context
384 NeoZero(ctx, sizeof(NEO_CTX));
385
386 // Initialize the status information
387 NeoNewStatus(&ctx->Status);
388
389 return TRUE;
390 }
391
392 // Shutdown
NeoShutdown()393 void NeoShutdown()
394 {
395 if (ctx == NULL)
396 {
397 // Uninitialized
398 return;
399 }
400
401 // Release the status information
402 NeoFreeStatus(&ctx->Status);
403
404 NeoZero(ctx, sizeof(NEO_CTX));
405 }
406
407 // Create a status information
NeoNewStatus(NEO_STATUS * s)408 void NeoNewStatus(NEO_STATUS *s)
409 {
410 // Validate arguments
411 if (s == NULL)
412 {
413 return;
414 }
415
416 // Memory initialization
417 NeoZero(s, sizeof(NEO_STATUS));
418 }
419
420 // Release the status information
NeoFreeStatus(NEO_STATUS * s)421 void NeoFreeStatus(NEO_STATUS *s)
422 {
423 // Validate arguments
424 if (s == NULL)
425 {
426 return;
427 }
428
429 // Memory initialization
430 NeoZero(s, sizeof(NEO_STATUS));
431 }
432
433