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