1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Kernel Device Driver
3 
4 
5 // Neo.c
6 // Driver main program
7 
8 #include <GlobalConst.h>
9 
10 #define	NEO_DEVICE_DRIVER
11 
12 #include "Neo.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 	void *packet_buf;
82 	// Validate arguments
83 	if (buf == NULL)
84 	{
85 		return;
86 	}
87 
88 	// Number of packets
89 	num = NEO_NUM_PACKET(buf);
90 	if (num > NEO_MAX_PACKET_EXCHANGE)
91 	{
92 		// Number of packets is too many
93 		return;
94 	}
95 	if (num == 0)
96 	{
97 		// No packet
98 		return;
99 	}
100 
101 	if (ctx->Halting != FALSE)
102 	{
103 		// Halting
104 		return;
105 	}
106 
107 	if (ctx->Opened == FALSE)
108 	{
109 		// Not connected
110 		return;
111 	}
112 
113 	for (i = 0;i < num;i++)
114 	{
115 		PACKET_BUFFER *p = ctx->PacketBuffer[i];
116 
117 		size = NEO_SIZE_OF_PACKET(buf, i);
118 		if (size > NEO_MAX_PACKET_SIZE)
119 		{
120 			size = NEO_MAX_PACKET_SIZE;
121 		}
122 		if (size < NEO_PACKET_HEADER_SIZE)
123 		{
124 			size = NEO_PACKET_HEADER_SIZE;
125 		}
126 
127 		packet_buf = NEO_ADDR_OF_PACKET(buf, i);
128 
129 		// Buffer copy
130 		NeoCopy(p->Buf, packet_buf, size);
131 
132 		if (g_is_win8 == false)
133 		{
134 			// Adjust the buffer size
135 			NdisAdjustBufferLength(p->NdisBuffer, size);
136 			// Set the packet information
137 			NDIS_SET_PACKET_STATUS(p->NdisPacket, NDIS_STATUS_RESOURCES);
138 			NDIS_SET_PACKET_HEADER_SIZE(p->NdisPacket, NEO_PACKET_HEADER_SIZE);
139 		}
140 		else
141 		{
142 			NdisMEthIndicateReceive(ctx->NdisMiniport, ctx,
143 				p->Buf, NEO_PACKET_HEADER_SIZE,
144 				((UCHAR *)p->Buf) + NEO_PACKET_HEADER_SIZE, size - NEO_PACKET_HEADER_SIZE,
145 				size - NEO_PACKET_HEADER_SIZE);
146 			NdisMEthIndicateReceiveComplete(ctx->NdisMiniport);
147 		}
148 	}
149 
150 	// Notify that packets have received
151 	ctx->Status.NumPacketRecv += num;
152 
153 	if (g_is_win8 == false)
154 	{
155 		NdisMIndicateReceivePacket(ctx->NdisMiniport, ctx->PacketBufferArray, num);
156 	}
157 }
158 
159 // Get the number of queue items
NeoGetNumQueue()160 UINT NeoGetNumQueue()
161 {
162 	return ctx->NumPacketQueue;
163 }
164 
165 // Insert the queue
NeoInsertQueue(void * buf,UINT size)166 void NeoInsertQueue(void *buf, UINT size)
167 {
168 	NEO_QUEUE *p;
169 	// Validate arguments
170 	if (buf == NULL || size == 0)
171 	{
172 		return;
173 	}
174 
175 	// Prevent the packet accumulation in large quantities in the queue
176 	if (ctx->NumPacketQueue > NEO_MAX_PACKET_QUEUED)
177 	{
178 		NeoFree(buf);
179 		return;
180 	}
181 
182 	// Create a queue
183 	p = NeoMalloc(sizeof(NEO_QUEUE));
184 	p->Next = NULL;
185 	p->Size = size;
186 	p->Buf = buf;
187 
188 	// Append to the queue
189 	if (ctx->PacketQueue == NULL)
190 	{
191 		ctx->PacketQueue = p;
192 	}
193 	else
194 	{
195 		NEO_QUEUE *q = ctx->Tail;
196 		q->Next = p;
197 	}
198 
199 	ctx->Tail = p;
200 
201 	ctx->NumPacketQueue++;
202 }
203 
204 // Get the next queued item
NeoGetNextQueue()205 NEO_QUEUE *NeoGetNextQueue()
206 {
207 	NEO_QUEUE *q;
208 	if (ctx->PacketQueue == NULL)
209 	{
210 		// No item queued
211 		return NULL;
212 	}
213 
214 	// Get the next queued item
215 	q = ctx->PacketQueue;
216 	ctx->PacketQueue = ctx->PacketQueue->Next;
217 	q->Next = NULL;
218 	ctx->NumPacketQueue--;
219 
220 	if (ctx->PacketQueue == NULL)
221 	{
222 		ctx->Tail = NULL;
223 	}
224 
225 	return q;
226 }
227 
228 // Release the buffer queue
NeoFreeQueue(NEO_QUEUE * q)229 void NeoFreeQueue(NEO_QUEUE *q)
230 {
231 	// Validate arguments
232 	if (q == NULL)
233 	{
234 		return;
235 	}
236 	NeoFree(q->Buf);
237 	NeoFree(q);
238 }
239 
240 // Lock the packet queue
NeoLockPacketQueue()241 void NeoLockPacketQueue()
242 {
243 	NeoLock(ctx->PacketQueueLock);
244 }
245 
246 // Unlock the packet queue
NeoUnlockPacketQueue()247 void NeoUnlockPacketQueue()
248 {
249 	NeoUnlock(ctx->PacketQueueLock);
250 }
251 
252 // Initialize the packet queue
NeoInitPacketQueue()253 void NeoInitPacketQueue()
254 {
255 	// Create a lock
256 	ctx->PacketQueueLock = NeoNewLock();
257 	// Initialize the packet queue
258 	ctx->PacketQueue = NULL;
259 	ctx->NumPacketQueue = 0;
260 	ctx->Tail = NULL;
261 }
262 
263 // Delete all the packets from the packet queue
NeoClearPacketQueue()264 void NeoClearPacketQueue()
265 {
266 	// Release the memory of the packet queue
267 	NeoLock(ctx->PacketQueueLock);
268 	{
269 		NEO_QUEUE *q = ctx->PacketQueue;
270 		NEO_QUEUE *qn;
271 		while (q != NULL)
272 		{
273 			qn = q->Next;
274 			NeoFree(q->Buf);
275 			NeoFree(q);
276 			q = qn;
277 		}
278 		ctx->PacketQueue = NULL;
279 		ctx->Tail = NULL;
280 		ctx->NumPacketQueue = 0;
281 	}
282 	NeoUnlock(ctx->PacketQueueLock);
283 }
284 
285 // Release the packet queue
NeoFreePacketQueue()286 void NeoFreePacketQueue()
287 {
288 	// Delete all packets
289 	NeoClearPacketQueue();
290 
291 	// Delete the lock
292 	NeoFreeLock(ctx->PacketQueueLock);
293 	ctx->PacketQueueLock = NULL;
294 }
295 
296 // Start the adapter
NeoStartAdapter()297 void NeoStartAdapter()
298 {
299 	// Initialize the packet queue
300 	NeoInitPacketQueue();
301 }
302 
303 // Stop the adapter
NeoStopAdapter()304 void NeoStopAdapter()
305 {
306 	// Delete the packet queue
307 	NeoFreePacketQueue();
308 }
309 
310 // Initialization
NeoInit()311 BOOL NeoInit()
312 {
313 	// Initialize the context
314 	NeoZero(ctx, sizeof(NEO_CTX));
315 
316 	// Initialize the status information
317 	NeoNewStatus(&ctx->Status);
318 
319 	return TRUE;
320 }
321 
322 // Shutdown
NeoShutdown()323 void NeoShutdown()
324 {
325 	if (ctx == NULL)
326 	{
327 		// Uninitialized
328 		return;
329 	}
330 
331 	// Release the status information
332 	NeoFreeStatus(&ctx->Status);
333 
334 	NeoZero(ctx, sizeof(NEO_CTX));
335 }
336 
337 // Create a status information
NeoNewStatus(NEO_STATUS * s)338 void NeoNewStatus(NEO_STATUS *s)
339 {
340 	// Validate arguments
341 	if (s == NULL)
342 	{
343 		return;
344 	}
345 
346 	// Memory initialization
347 	NeoZero(s, sizeof(NEO_STATUS));
348 }
349 
350 // Release the status information
NeoFreeStatus(NEO_STATUS * s)351 void NeoFreeStatus(NEO_STATUS *s)
352 {
353 	// Validate arguments
354 	if (s == NULL)
355 	{
356 		return;
357 	}
358 
359 	// Memory initialization
360 	NeoZero(s, sizeof(NEO_STATUS));
361 }
362 
363