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