1 /*
2  * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
3  * Copyright (c) 2005 CACE Technologies, Davis (California)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the Politecnico di Torino, CACE Technologies
16  * nor the names of its contributors may be used to endorse or promote
17  * products derived from this software without specific prior written
18  * permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33 
34 #include <GlobalConst.h>
35 
36 #include "stdarg.h"
37 #include "ntddk.h"
38 #include "ntiologc.h"
39 #include "ndis.h"
40 
41 #include "ntddpack.h"
42 
43 #include "debug.h"
44 #include "packet.h"
45 #include "win_bpf.h"
46 #include "win_bpf_filter_init.h"
47 
48 #if DBG
49 // Declare the global debug flag for this driver.
50 ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
51 
52 #endif
53 
54 PDEVICE_EXTENSION GlobalDeviceExtension;
55 
56 //
57 // Global strings
58 //
59 NDIS_STRING NPF_Prefix = NDIS_STRING_CONST("SEE_");
60 NDIS_STRING devicePrefix = NDIS_STRING_CONST("\\Device\\");
61 NDIS_STRING symbolicLinkPrefix = NDIS_STRING_CONST("\\DosDevices\\");
62 NDIS_STRING tcpLinkageKeyName = NDIS_STRING_CONST("\\Registry\\Machine\\System"
63 								L"\\CurrentControlSet\\Services\\Tcpip\\Linkage");
64 NDIS_STRING AdapterListKey = NDIS_STRING_CONST("\\Registry\\Machine\\System"
65 								L"\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
66 NDIS_STRING bindValueName = NDIS_STRING_CONST("Bind");
67 
68 /// Global variable that points to the names of the bound adapters
69 WCHAR* bindP = NULL;
70 
71 extern struct time_conv G_Start_Time; // from openclos.c
72 
73 extern NDIS_SPIN_LOCK Opened_Instances_Lock;
74 
75 ULONG NCpu = 1;
76 
77 ULONG TimestampMode;
78 UINT g_SendPacketFlags = 0;
79 
80 
81 // Crush now
Crush(UINT a,UINT b,UINT c,UINT d)82 void Crush(UINT a, UINT b, UINT c, UINT d)
83 {
84 	KeBugCheckEx(0x3f000000 + a, (ULONG_PTR)a, (ULONG_PTR)b, (ULONG_PTR)c, (ULONG_PTR)d);
85 }
86 
87 //
88 //  Packet Driver's entry routine.
89 //
90 NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)91 DriverEntry(
92     IN PDRIVER_OBJECT DriverObject,
93     IN PUNICODE_STRING RegistryPath
94     )
95 {
96 
97     NDIS_PROTOCOL_CHARACTERISTICS  ProtocolChar;
98     PDEVICE_OBJECT DeviceObject = NULL;
99     PDEVICE_EXTENSION DeviceExtension = NULL;
100     NTSTATUS Status = STATUS_SUCCESS;
101     NTSTATUS ErrorCode = STATUS_SUCCESS;
102     NDIS_STRING ProtoName = NDIS_STRING_CONST("PacketDriver");
103     ULONG          DevicesCreated=0;
104     NDIS_HANDLE    NdisProtocolHandle;
105 	WCHAR* bindT;
106 	PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP;
107 	UNICODE_STRING macName;
108 	ULONG			OsMajorVersion, OsMinorVersion;
109 
110 	PsGetVersion(&OsMajorVersion, &OsMinorVersion, NULL, NULL);
111 	//
112 	// Define the correct flag to skip the loopback packets, according to the OS
113 	//
114 	if((OsMajorVersion == 5) && (OsMinorVersion == 0))
115 	{
116 		// Windows 2000 wants both NDIS_FLAGS_DONT_LOOPBACK and NDIS_FLAGS_SKIP_LOOPBACK
117 		g_SendPacketFlags = NDIS_FLAGS_DONT_LOOPBACK | NDIS_FLAGS_SKIP_LOOPBACK_W2K;
118 	}
119 	else
120 	{
121 		// Windows XP, 2003 and following want only  NDIS_FLAGS_DONT_LOOPBACK
122 		g_SendPacketFlags =  NDIS_FLAGS_DONT_LOOPBACK;
123 	}
124 
125 	if (((OsMajorVersion == 6) && (OsMinorVersion >= 1)) || (OsMajorVersion >= 7))
126 	{
127 		// Use KeQueryActiveProcessors to get the number of CPUs in Windows 7 or later
128 		KAFFINITY cpus = KeQueryActiveProcessors();
129 		NCpu = 0;
130 
131 		while (cpus)
132 		{
133 			if (cpus % 2)
134 			{
135 				NCpu++;
136 			}
137 
138 			cpus = cpus / 2;
139 		}
140 	}
141 	else
142 	{
143 		// Use NdisSystemProcessorCount in Windows Vista or earlier
144 		NCpu = NdisSystemProcessorCount();
145 	}
146 
147 
148 	ReadTimeStampModeFromRegistry(RegistryPath);
149 
150 	IF_LOUD(DbgPrint("%ws",RegistryPath->Buffer);)
151 
152     IF_LOUD(DbgPrint("\n\nPacket: DriverEntry\n");)
153 
154 	RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
155 
156 #ifdef NDIS50
157     ProtocolChar.MajorNdisVersion            = 5;
158 #else
159     ProtocolChar.MajorNdisVersion            = 3;
160 #endif
161     ProtocolChar.MinorNdisVersion            = 0;
162     ProtocolChar.Reserved                    = 0;
163     ProtocolChar.OpenAdapterCompleteHandler  = NPF_OpenAdapterComplete;
164     ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete;
165     ProtocolChar.SendCompleteHandler         = NPF_SendComplete;
166     ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete;
167     ProtocolChar.ResetCompleteHandler        = NPF_ResetComplete;
168     ProtocolChar.RequestCompleteHandler      = NPF_RequestComplete;
169     ProtocolChar.ReceiveHandler              = NPF_tap;
170     ProtocolChar.ReceiveCompleteHandler      = NPF_ReceiveComplete;
171     ProtocolChar.StatusHandler               = NPF_Status;
172     ProtocolChar.StatusCompleteHandler       = NPF_StatusComplete;
173 #ifdef NDIS50
174     ProtocolChar.BindAdapterHandler          = NPF_BindAdapter;
175     ProtocolChar.UnbindAdapterHandler        = NPF_UnbindAdapter;
176     ProtocolChar.PnPEventHandler             = NPF_PowerChange;
177     ProtocolChar.ReceivePacketHandler        = NULL;
178 #endif
179     ProtocolChar.Name                        = ProtoName;
180 
181     NdisRegisterProtocol(
182         &Status,
183         &NdisProtocolHandle,
184         &ProtocolChar,
185         sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
186 
187     if (Status != NDIS_STATUS_SUCCESS) {
188 
189         IF_LOUD(DbgPrint("NPF: Failed to register protocol with NDIS\n");)
190 
191         return Status;
192 
193     }
194 
195     NdisAllocateSpinLock(&Opened_Instances_Lock);
196 
197     // Set up the device driver entry points.
198     DriverObject->MajorFunction[IRP_MJ_CREATE] = NPF_Open;
199     DriverObject->MajorFunction[IRP_MJ_CLOSE]  = NPF_Close;
200     DriverObject->MajorFunction[IRP_MJ_READ]   = NPF_Read;
201     DriverObject->MajorFunction[IRP_MJ_WRITE]  = NPF_Write;
202     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = NPF_IoControl;
203     DriverObject->DriverUnload = NPF_Unload;
204 
205  	bindP = getAdaptersList();
206 
207 	if (bindP == NULL)
208 	{
209 		IF_LOUD(DbgPrint("Adapters not found in the registry, try to copy the bindings of TCP-IP.\n");)
210 
211 		tcpBindingsP = getTcpBindings();
212 
213 		if (tcpBindingsP == NULL)
214 		{
215 			IF_LOUD(DbgPrint("TCP-IP not found, quitting.\n");)
216 			goto RegistryError;
217 		}
218 
219 		bindP = (WCHAR*)tcpBindingsP;
220 		bindT = (WCHAR*)(tcpBindingsP->Data);
221 
222 	}
223 	else
224 	{
225 		bindT = bindP;
226 	}
227 
228 	for (; *bindT != UNICODE_NULL; bindT += (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR))
229 	{
230 		RtlInitUnicodeString(&macName, bindT);
231 		createDevice(DriverObject, &macName, NdisProtocolHandle);
232 	}
233 
234 	return STATUS_SUCCESS;
235 
236 RegistryError:
237 
238     NdisDeregisterProtocol(
239         &Status,
240         NdisProtocolHandle
241         );
242 
243     Status=STATUS_UNSUCCESSFUL;
244 
245     return(Status);
246 
247 }
248 
249 //-------------------------------------------------------------------
250 
getAdaptersList(void)251 PWCHAR getAdaptersList(void)
252 {
253 	PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
254 	OBJECT_ATTRIBUTES objAttrs;
255 	NTSTATUS status;
256 	HANDLE keyHandle;
257 	UINT BufPos=0;
258 	UINT BufLen=4096;
259 
260 
261 	PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, BufLen, '0PWA');
262 
263 	if (DeviceNames == NULL) {
264 		IF_LOUD(DbgPrint("Unable the allocate the buffer for the list of the network adapters\n");)
265 			return NULL;
266 	}
267 
268 	InitializeObjectAttributes(&objAttrs, &AdapterListKey,
269 		OBJ_CASE_INSENSITIVE, NULL, NULL);
270 	status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
271 	if (!NT_SUCCESS(status)) {
272 		IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
273 	}
274 	else { //OK
275 
276 		ULONG resultLength;
277 		CHAR AdapInfo[1024];
278 		UINT i=0;
279 		KEY_VALUE_PARTIAL_INFORMATION valueInfo;
280 
281 		IF_LOUD(DbgPrint("getAdaptersList: scanning the list of the adapters in the registry, DeviceNames=%x\n",DeviceNames);)
282 
283 			// Scan the list of the devices
284 			while((status=ZwEnumerateKey(keyHandle,i,KeyBasicInformation,AdapInfo,sizeof(AdapInfo),&resultLength))==STATUS_SUCCESS)
285 			{
286 				WCHAR ExportKeyName [512];
287 				PWCHAR ExportKeyPrefix = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
288 				UINT ExportKeyPrefixSize = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
289 				PWCHAR LinkageKeyPrefix = L"\\Linkage";
290 				UINT LinkageKeyPrefixSize = sizeof(L"\\Linkage");
291 				NDIS_STRING FinalExportKey = NDIS_STRING_CONST("Export");
292 				PKEY_BASIC_INFORMATION tInfo= (PKEY_BASIC_INFORMATION)AdapInfo;
293 				UNICODE_STRING AdapterKeyName;
294 				HANDLE ExportKeyHandle;
295 
296 				RtlCopyMemory(ExportKeyName,
297 					ExportKeyPrefix,
298 					ExportKeyPrefixSize);
299 
300 				RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize,
301 					tInfo->Name,
302 					tInfo->NameLength+2);
303 
304 				RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize+tInfo->NameLength,
305 					LinkageKeyPrefix,
306 					LinkageKeyPrefixSize);
307 
308 				IF_LOUD(DbgPrint("Key name=%ws\n", ExportKeyName);)
309 
310 				RtlInitUnicodeString(&AdapterKeyName, ExportKeyName);
311 
312 				InitializeObjectAttributes(&objAttrs, &AdapterKeyName,
313 					OBJ_CASE_INSENSITIVE, NULL, NULL);
314 
315 				status=ZwOpenKey(&ExportKeyHandle,KEY_READ,&objAttrs);
316 
317 				if (!NT_SUCCESS(status)) {
318 					IF_LOUD(DbgPrint("OpenKey Failed, %d!\n",status);)
319 					i++;
320 					continue;
321 				}
322 
323 				status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
324 					KeyValuePartialInformation, &valueInfo,
325 					sizeof(valueInfo), &resultLength);
326 
327 				if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
328 					IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
329 				}
330 				else {                      // We know how big it needs to be.
331 					ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
332 					PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =	(PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, '1PWA');
333 					if (valueInfoP != NULL) {
334 						status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
335 							KeyValuePartialInformation,
336 							valueInfoP,
337 							valueInfoLength, &resultLength);
338 						if (!NT_SUCCESS(status)) {
339 							IF_LOUD(DbgPrint("Status of %x querying key value\n", status);)
340 						}
341 						else{
342 							IF_LOUD(DbgPrint("Device %d = %ws\n", i, valueInfoP->Data);)
343 								if( BufPos + valueInfoP->DataLength > BufLen ) {
344 									// double the buffer size
345 									PWCHAR DeviceNames2 = (PWCHAR) ExAllocatePoolWithTag(PagedPool, BufLen
346 										<< 1, '0PWA');
347 									if( DeviceNames2 ) {
348 										RtlCopyMemory((PCHAR)DeviceNames2, (PCHAR)DeviceNames, BufLen);
349 										BufLen <<= 1;
350 										ExFreePool(DeviceNames);
351 										DeviceNames = DeviceNames2;
352 									}
353 								}
354 								if( BufPos + valueInfoP->DataLength < BufLen ) {
355 									RtlCopyMemory((PCHAR)DeviceNames+BufPos,
356 										valueInfoP->Data,
357 										valueInfoP->DataLength);
358 									BufPos+=valueInfoP->DataLength-2;
359 								}
360 						}
361 
362 						ExFreePool(valueInfoP);
363 					}
364 					else {
365 						IF_LOUD(DbgPrint("Error Allocating the buffer for the device name\n");)
366 					}
367 
368 				}
369 
370 				// terminate the buffer
371 				DeviceNames[BufPos/2]=0;
372 				DeviceNames[BufPos/2+1]=0;
373 
374 				ZwClose (ExportKeyHandle);
375 				i++;
376 
377 			}
378 
379 			ZwClose (keyHandle);
380 
381 	}
382 	if(BufPos==0){
383 		ExFreePool(DeviceNames);
384 		return NULL;
385 	}
386 	return DeviceNames;
387 }
388 
389 //-------------------------------------------------------------------
390 
getTcpBindings(void)391 PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
392 {
393   PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
394   OBJECT_ATTRIBUTES objAttrs;
395   NTSTATUS status;
396   HANDLE keyHandle;
397 
398   InitializeObjectAttributes(&objAttrs, &tcpLinkageKeyName,
399                              OBJ_CASE_INSENSITIVE, NULL, NULL);
400   status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
401   if (!NT_SUCCESS(status)) {
402     IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
403   }
404   else {
405     ULONG resultLength;
406     KEY_VALUE_PARTIAL_INFORMATION valueInfo;
407 
408     IF_LOUD(DbgPrint("\n\nOpened %ws\n", tcpLinkageKeyName.Buffer);)
409 
410     status = ZwQueryValueKey(keyHandle, &bindValueName,
411                              KeyValuePartialInformation, &valueInfo,
412                              sizeof(valueInfo), &resultLength);
413     if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
414       IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
415     }
416     else {                      // We know how big it needs to be.
417       ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
418       PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =
419         (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, '2PWA');
420 
421 	  if (valueInfoP != NULL) {
422         status = ZwQueryValueKey(keyHandle, &bindValueName,
423                                  KeyValuePartialInformation,
424                                  valueInfoP,
425                                  valueInfoLength, &resultLength);
426 
427 		if (!NT_SUCCESS(status)) {
428           IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status);)
429         }
430         else if (valueInfoLength != resultLength) {
431           IF_LOUD(DbgPrint("\n\nQuerying key value result len = %u "
432                      "but previous len = %u\n",
433                      resultLength, valueInfoLength);)
434         }
435         else if (valueInfoP->Type != REG_MULTI_SZ) {
436           IF_LOUD(DbgPrint("\n\nTcpip bind value not REG_MULTI_SZ but %u\n",
437                      valueInfoP->Type);)
438         }
439         else {                  // It's OK
440 #if DBG
441           ULONG i;
442           WCHAR* dataP = (WCHAR*)(&valueInfoP->Data[0]);
443           IF_LOUD(DbgPrint("\n\nBind value:\n");)
444           for (i = 0; *dataP != UNICODE_NULL; i++) {
445             UNICODE_STRING macName;
446             RtlInitUnicodeString(&macName, dataP);
447             IF_LOUD(DbgPrint("\n\nMac %u = %ws\n", i, macName.Buffer);)
448             dataP +=
449               (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
450           }
451 #endif // DBG
452           result = valueInfoP;
453         }
454       }
455     }
456     ZwClose(keyHandle);
457   }
458   return result;
459 }
460 
461 //-------------------------------------------------------------------
462 
createDevice(IN OUT PDRIVER_OBJECT adriverObjectP,IN PUNICODE_STRING amacNameP,NDIS_HANDLE aProtoHandle)463 BOOLEAN createDevice(IN OUT PDRIVER_OBJECT adriverObjectP,
464 					 IN PUNICODE_STRING amacNameP, NDIS_HANDLE aProtoHandle)
465 {
466 	NTSTATUS status;
467 	PDEVICE_OBJECT devObjP;
468 	UNICODE_STRING deviceName;
469 	UNICODE_STRING deviceSymLink;
470 
471 	IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer););
472 	if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer,
473 		devicePrefix.Length) < devicePrefix.Length)
474 	{
475 		return FALSE;
476 	}
477 
478 	deviceName.Length = 0;
479 	deviceName.MaximumLength = (USHORT)(amacNameP->Length + NPF_Prefix.Length + sizeof(UNICODE_NULL));
480 	deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, '3PWA');
481 
482 	if (deviceName.Buffer == NULL)
483 		return FALSE;
484 
485 	deviceSymLink.Length = 0;
486 	deviceSymLink.MaximumLength =(USHORT)(amacNameP->Length-devicePrefix.Length
487 		+ symbolicLinkPrefix.Length
488 		+ NPF_Prefix.Length
489 		+ sizeof(UNICODE_NULL));
490 
491 	deviceSymLink.Buffer = ExAllocatePoolWithTag(NonPagedPool, deviceSymLink.MaximumLength, '3PWA');
492 
493 	if (deviceSymLink.Buffer  == NULL)
494 	{
495 		ExFreePool(deviceName.Buffer);
496 		return FALSE;
497 	}
498 
499 	RtlAppendUnicodeStringToString(&deviceName, &devicePrefix);
500 	RtlAppendUnicodeStringToString(&deviceName, &NPF_Prefix);
501 	RtlAppendUnicodeToString(&deviceName, amacNameP->Buffer +
502 		devicePrefix.Length / sizeof(WCHAR));
503 
504 	RtlAppendUnicodeStringToString(&deviceSymLink, &symbolicLinkPrefix);
505 	RtlAppendUnicodeStringToString(&deviceSymLink, &NPF_Prefix);
506 	RtlAppendUnicodeToString(&deviceSymLink, amacNameP->Buffer +
507 		devicePrefix.Length / sizeof(WCHAR));
508 
509 	IF_LOUD(DbgPrint("Creating device name: %ws\n", deviceName.Buffer);)
510 
511 		status = IoCreateDevice(adriverObjectP,
512 		sizeof(DEVICE_EXTENSION),
513 		&deviceName,
514 		FILE_DEVICE_TRANSPORT,
515 		0,
516 		FALSE,
517 		&devObjP);
518 
519 	if (NT_SUCCESS(status))
520 	{
521 		PDEVICE_EXTENSION devExtP = (PDEVICE_EXTENSION)devObjP->DeviceExtension;
522 
523 		IF_LOUD(DbgPrint("Device created successfully\n"););
524 
525 		devObjP->Flags |= DO_DIRECT_IO;
526 		RtlInitUnicodeString(&devExtP->AdapterName,amacNameP->Buffer);
527 		devExtP->NdisProtocolHandle=aProtoHandle;
528 
529 		IF_LOUD(DbgPrint("Trying to create SymLink %ws\n",deviceSymLink.Buffer););
530 
531 		if (IoCreateSymbolicLink(&deviceSymLink,&deviceName) != STATUS_SUCCESS)
532 		{
533 			IF_LOUD(DbgPrint("\n\nError creating SymLink %ws\nn", deviceSymLink.Buffer););
534 
535 			ExFreePool(deviceName.Buffer);
536 			ExFreePool(deviceSymLink.Buffer);
537 
538 			devExtP->ExportString = NULL;
539 
540 			return FALSE;
541 		}
542 
543 		IF_LOUD(DbgPrint("SymLink %ws successfully created.\n\n", deviceSymLink.Buffer););
544 
545 		devExtP->ExportString = deviceSymLink.Buffer;
546 
547 		ExFreePool(deviceName.Buffer);
548 
549 		return TRUE;
550 	}
551 
552 	else
553 	{
554 		IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status););
555 
556 		ExFreePool(deviceName.Buffer);
557 		ExFreePool(deviceSymLink.Buffer);
558 
559 		return FALSE;
560 	}
561 }
562 //-------------------------------------------------------------------
563 
NPF_Unload(IN PDRIVER_OBJECT DriverObject)564 VOID NPF_Unload(IN PDRIVER_OBJECT DriverObject)
565 {
566 	PDEVICE_OBJECT     DeviceObject;
567 	PDEVICE_OBJECT     OldDeviceObject;
568 	PDEVICE_EXTENSION  DeviceExtension;
569 
570 	NDIS_HANDLE        NdisProtocolHandle = NULL;
571 	NDIS_STATUS        Status;
572 
573 	NDIS_STRING		   SymLink;
574 
575 	IF_LOUD(DbgPrint("NPF: Unload\n"););
576 
577 	DeviceObject    = DriverObject->DeviceObject;
578 
579 	while (DeviceObject != NULL) {
580 		OldDeviceObject = DeviceObject;
581 
582 		DeviceObject = DeviceObject->NextDevice;
583 
584 		DeviceExtension = OldDeviceObject->DeviceExtension;
585 
586 		NdisProtocolHandle=DeviceExtension->NdisProtocolHandle;
587 
588 		IF_LOUD(DbgPrint("Deleting Adapter %ws, Protocol Handle=%x, Device Obj=%x (%x)\n",
589 			DeviceExtension->AdapterName.Buffer,
590 			NdisProtocolHandle,
591 			DeviceObject,
592 			OldDeviceObject););
593 
594 		if (DeviceExtension->ExportString)
595 		{
596 			RtlInitUnicodeString(&SymLink , DeviceExtension->ExportString);
597 
598 			IF_LOUD(DbgPrint("Deleting SymLink at %p\n", SymLink.Buffer););
599 
600 			IoDeleteSymbolicLink(&SymLink);
601 			ExFreePool(DeviceExtension->ExportString);
602 		}
603 
604 		IoDeleteDevice(OldDeviceObject);
605 	}
606 
607 	NdisDeregisterProtocol(
608 		&Status,
609 		NdisProtocolHandle
610 		);
611 
612 	// Free the adapters names
613 	ExFreePool( bindP );
614 }
615 
616 #define SET_FAILURE_BUFFER_SMALL() do{\
617 	Information = 0; \
618 	Status = STATUS_BUFFER_TOO_SMALL; \
619 } while(FALSE)
620 
621 #define SET_RESULT_SUCCESS(__a__) do{\
622 	Information = __a__;	\
623 	Status = STATUS_SUCCESS;	\
624 } while(FALSE)
625 
626 #define SET_FAILURE_INVALID_REQUEST() do{\
627 	Information = 0; \
628 	Status = STATUS_INVALID_DEVICE_REQUEST; \
629 } while(FALSE)
630 
631 #define SET_FAILURE_UNSUCCESSFUL()  do{\
632 	Information = 0; \
633 	Status = STATUS_UNSUCCESSFUL; \
634 } while(FALSE)
635 
636 #define SET_FAILURE_NOMEM()  do{\
637 	Information = 0; \
638 	Status = STATUS_INSUFFICIENT_RESOURCES; \
639 } while(FALSE)
640 
641 
642 //-------------------------------------------------------------------
643 
NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)644 NTSTATUS NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
645 {
646     POPEN_INSTANCE      Open;
647     PIO_STACK_LOCATION  IrpSp;
648     PLIST_ENTRY         RequestListEntry;
649     PINTERNAL_REQUEST   pRequest;
650     ULONG               FunctionCode;
651     NDIS_STATUS	        Status;
652 	UINT				i;
653 	PUCHAR				tpointer;
654 	ULONG				dim,timeout;
655 	PUCHAR				prog;
656 	PPACKET_OID_DATA    OidData;
657 	ULONG				mode;
658 //	PWSTR				DumpNameBuff;
659 	PUCHAR				TmpBPFProgram;
660 	INT					WriteRes;
661 	BOOLEAN				SyncWrite = FALSE;
662 //	struct bpf_insn		*initprogram;
663 	ULONG				insns;
664 	ULONG				cnt;
665 	BOOLEAN				IsExtendedFilter=FALSE;
666 
667 	BOOLEAN				Flag;
668 	PUINT				pStats;
669 	ULONG				Information = 0;
670 
671 	BOOLEAN check_ok;
672 
673     IF_LOUD(DbgPrint("NPF: IoControl\n");)
674 
675 	IrpSp = IoGetCurrentIrpStackLocation(Irp);
676     FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
677     Open=IrpSp->FileObject->FsContext;
678 
679     Irp->IoStatus.Status = STATUS_SUCCESS;
680 
681 	IF_LOUD(DbgPrint("NPF: Function code is %08lx  buff size=%08lx  %08lx\n",FunctionCode,IrpSp->Parameters.DeviceIoControl.InputBufferLength,IrpSp->Parameters.DeviceIoControl.OutputBufferLength);)
682 
683 	switch (FunctionCode){
684 
685 	case BIOCGSTATS: //function to get the capture stats
686 
687 		if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4*sizeof(UINT)){
688 			EXIT_FAILURE(0);
689 		}
690 
691 		check_ok = TRUE;
692 		__try
693 		{
694 			ProbeForWrite(Irp->UserBuffer, IrpSp->Parameters.DeviceIoControl.OutputBufferLength, 1);
695 		}
696 		__except (EXCEPTION_EXECUTE_HANDLER)
697 		{
698 			check_ok = FALSE;
699 		}
700 
701 		if (check_ok == FALSE)
702 		{
703 			EXIT_FAILURE(0);
704 		}
705 		else
706 		{
707 			pStats = (PUINT)(Irp->UserBuffer);
708 
709 			pStats[3] = 0;
710 			pStats[0] = 0;
711 			pStats[1] = 0;
712 			pStats[2] = 0;		// Not yet supported
713 
714 			for(i = 0 ; i < NCpu ; i++)
715 			{
716 
717 				pStats[3] += Open->CpuData[i].Accepted;
718 				pStats[0] += Open->CpuData[i].Received;
719 				pStats[1] += Open->CpuData[i].Dropped;
720 				pStats[2] += 0;		// Not yet supported
721 			}
722 			EXIT_SUCCESS(4*sizeof(UINT));
723 		}
724 
725 		break;
726 
727 	case BIOCGEVNAME: //function to get the name of the event associated with the current instance
728 
729 		if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength<26){
730 			EXIT_FAILURE(0);
731 		}
732 
733 		check_ok = TRUE;
734 		__try
735 		{
736 			ProbeForWrite(Irp->UserBuffer, IrpSp->Parameters.DeviceIoControl.OutputBufferLength, 1);
737 		}
738 		__except (EXCEPTION_EXECUTE_HANDLER)
739 		{
740 			check_ok = FALSE;
741 		}
742 
743 		if (check_ok == FALSE)
744 		{
745 			EXIT_FAILURE(0);
746 		}
747 		else
748 		{
749 			RtlCopyMemory(Irp->UserBuffer,(Open->ReadEventName.Buffer)+18,26);
750 
751 			EXIT_SUCCESS(26);
752 		}
753 
754 		break;
755 
756 	case BIOCSENDPACKETSSYNC:
757 
758 		SyncWrite = TRUE;
759 
760 	case BIOCSENDPACKETSNOSYNC:
761 
762 		NdisAcquireSpinLock(&Open->WriteLock);
763 		if(Open->WriteInProgress)
764 		{
765 			// Another write operation is currently in progress
766 			EXIT_FAILURE(0);
767 		}
768 		else
769 		{
770 			Open->WriteInProgress = TRUE;
771 		}
772 		NdisReleaseSpinLock(&Open->WriteLock);
773 
774 		WriteRes = NPF_BufferedWrite(Irp,
775 			(PUCHAR)Irp->AssociatedIrp.SystemBuffer,
776 			IrpSp->Parameters.DeviceIoControl.InputBufferLength,
777 			SyncWrite);
778 
779 		NdisAcquireSpinLock(&Open->WriteLock);
780 		Open->WriteInProgress = FALSE;
781 		NdisReleaseSpinLock(&Open->WriteLock);
782 
783 		if( WriteRes != -1)
784 		{
785 			EXIT_SUCCESS(WriteRes);
786 		}
787 
788 		EXIT_FAILURE(WriteRes);
789 
790 		break;
791 
792 	case BIOCSETF:
793 
794 		Open->SkipProcessing = 1;
795 
796 		do
797 		{
798 			Flag = FALSE;
799 			for(i = 0; i < NCpu ; i++)
800 				if (Open->CpuData[i].Processing == 1)
801 					Flag = TRUE;
802 		}
803 		while(Flag);  //BUSY FORM WAITING...
804 
805 
806 		// Free the previous buffer if it was present
807 		if(Open->bpfprogram != NULL){
808 			TmpBPFProgram = Open->bpfprogram;
809 			Open->bpfprogram = NULL;
810 			ExFreePool(TmpBPFProgram);
811 		}
812 
813 //
814 // Jitted filters are supported on x86 (32bit) only
815 //
816 #ifdef __NPF_x86__
817 		if (Open->Filter != NULL)
818 		{
819 			JIT_BPF_Filter *OldFilter=Open->Filter;
820 			Open->Filter=NULL;
821 			BPF_Destroy_JIT_Filter(OldFilter);
822 		}
823 #endif // __NPF_x86__
824 
825 		// Get the pointer to the new program
826 		prog=(PUCHAR)Irp->AssociatedIrp.SystemBuffer;
827 
828 		if(prog==NULL)
829 		{
830 			Open->SkipProcessing = 0;
831 			EXIT_FAILURE(0);
832 		}
833 
834 		insns = (IrpSp->Parameters.DeviceIoControl.InputBufferLength)/sizeof(struct bpf_insn);
835 
836 		//count the number of operative instructions
837 		for (cnt=0;(cnt<insns) &&(((struct bpf_insn*)prog)[cnt].code!=BPF_SEPARATION); cnt++);
838 
839 		IF_LOUD(DbgPrint("Operative instructions=%u\n",cnt);)
840 
841 #ifdef __NPF_x86__
842 		if ( cnt != insns && insns != cnt+1 && ((struct bpf_insn*)prog)[cnt].code == BPF_SEPARATION )
843 		{
844 			IF_LOUD(DbgPrint("Initialization instructions=%u\n",insns-cnt-1);)
845 
846 			IsExtendedFilter=TRUE;
847 
848 			initprogram=&((struct bpf_insn*)prog)[cnt+1];
849 
850 			if(bpf_filter_init(initprogram,&(Open->mem_ex),&(Open->tme), &G_Start_Time)!=INIT_OK)
851 			{
852 
853 				IF_LOUD(DbgPrint("Error initializing NPF machine (bpf_filter_init)\n");)
854 
855 				Open->SkipProcessing = 0;
856 				EXIT_FAILURE(0);
857 			}
858 		}
859 #else  //x86-64 and IA64
860 		if ( cnt != insns)
861 		{
862 			IF_LOUD(DbgPrint("Error installing the BPF filter. The filter contains TME extensions,"
863 				" not supported on 64bit platforms.\n");)
864 
865 			Open->SkipProcessing = 0;
866 			EXIT_FAILURE(0);
867 		}
868 
869 
870 #endif
871 
872 		//the NPF processor has been initialized, we have to validate the operative instructions
873 		insns = cnt;
874 
875 		//NOTE: the validation code checks for TME instructions, and fails if a TME instruction is
876 		//encountered on 64 bit machines
877 		if(bpf_validate((struct bpf_insn*)prog,cnt,Open->mem_ex.size)==0)
878 		{
879 			IF_LOUD(DbgPrint("Error validating program");)
880 			//FIXME: the machine has been initialized(?), but the operative code is wrong.
881 			//we have to reset the machine!
882 			//something like: reallocate the mem_ex, and reset the tme_core
883 			Open->SkipProcessing = 0;
884 			EXIT_FAILURE(0);
885 		}
886 
887 		// Allocate the memory to contain the new filter program
888 		// We could need the original BPF binary if we are forced to use bpf_filter_with_2_buffers()
889 		TmpBPFProgram = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, cnt*sizeof(struct bpf_insn), '4PWA');
890 		if (TmpBPFProgram == NULL)
891 		{
892 			IF_LOUD(DbgPrint("Error - No memory for filter");)
893 			// no memory
894 			Open->SkipProcessing = 0;
895 			EXIT_FAILURE(0);
896 		}
897 
898 		//copy the program in the new buffer
899 		RtlCopyMemory(TmpBPFProgram,prog,cnt*sizeof(struct bpf_insn));
900 		Open->bpfprogram=TmpBPFProgram;
901 
902 		//
903 		// At the moment the JIT compiler works on x86 (32 bit) only
904 		//
905 #ifdef __NPF_x86__
906 		// Create the new JIT filter function
907 		if(!IsExtendedFilter)
908 			if((Open->Filter=BPF_jitter((struct bpf_insn*)Open->bpfprogram,cnt)) == NULL)
909 			{
910 				IF_LOUD(DbgPrint("Error jittering filter");)
911 				Open->SkipProcessing = 0;
912 				EXIT_FAILURE(0);
913 			}
914 #endif
915 
916 		//return
917 		for (i = 0 ; i < NCpu ; i++)
918 		{
919 			Open->CpuData[i].C=0;
920 			Open->CpuData[i].P=0;
921 			Open->CpuData[i].Free = Open->Size;
922 			Open->CpuData[i].Accepted=0;
923 			Open->CpuData[i].Dropped=0;
924 			Open->CpuData[i].Received = 0;
925 		}
926 
927 		Open->ReaderSN=0;
928 		Open->WriterSN=0;
929 
930 		Open->SkipProcessing = 0;
931 		EXIT_SUCCESS(IrpSp->Parameters.DeviceIoControl.InputBufferLength);
932 
933 		break;
934 
935 	case BIOCSMODE:  //set the capture mode
936 
937 		if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
938 		{
939 			EXIT_FAILURE(0);
940 		}
941 
942 		mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer);
943 
944 ///////kernel dump does not work at the moment//////////////////////////////////////////
945 		if (mode & MODE_DUMP)
946 		{
947 			EXIT_FAILURE(0);
948 		}
949 ///////kernel dump does not work at the moment//////////////////////////////////////////
950 
951 		if(mode == MODE_CAPT)
952 		{
953 			Open->mode = MODE_CAPT;
954 
955 			EXIT_SUCCESS(0);
956 		}
957  		else if (mode == MODE_MON)
958 		{
959 //
960 // The MONITOR_MODE (aka TME extensions) is not supported on
961 // 64 bit architectures
962 //
963 #ifdef __NPF_x86__
964 			Open->mode = MODE_MON;
965 			EXIT_SUCCESS(0);
966 #else // _NPF_x86__
967 			EXIT_FAILURE(0);
968 #endif // __NPF_x86__
969 
970 		}
971 		else{
972 			if(mode & MODE_STAT){
973 				Open->mode = MODE_STAT;
974 				NdisAcquireSpinLock(&Open->CountersLock);
975 				Open->Nbytes.QuadPart = 0;
976 				Open->Npackets.QuadPart = 0;
977 				NdisReleaseSpinLock(&Open->CountersLock);
978 
979 				if(Open->TimeOut.QuadPart==0)Open->TimeOut.QuadPart = -10000000;
980 
981 			}
982 
983 			if(mode & MODE_DUMP){
984 
985 				Open->mode |= MODE_DUMP;
986 //				Open->MinToCopy=(Open->BufSize<2000000)?Open->BufSize/2:1000000;
987 
988 			}
989 			EXIT_SUCCESS(0);
990 		}
991 
992 		EXIT_FAILURE(0);
993 
994 		break;
995 
996 	case BIOCSETDUMPFILENAME:
997 
998 ///////kernel dump does not work at the moment//////////////////////////////////////////
999 		EXIT_FAILURE(0);
1000 ///////kernel dump does not work at the moment//////////////////////////////////////////
1001 
1002 //
1003 // Remove the following #if 0 to enable the kernel dump again
1004 //
1005 #if 0
1006 		if(Open->mode & MODE_DUMP)
1007 		{
1008 
1009 			// Close current dump file
1010 			if(Open->DumpFileHandle != NULL)
1011 			{
1012 				NPF_CloseDumpFile(Open);
1013 				Open->DumpFileHandle = NULL;
1014 			}
1015 
1016 			if(IrpSp->Parameters.DeviceIoControl.InputBufferLength == 0){
1017 				EXIT_FAILURE(0);
1018 			}
1019 
1020 			// Allocate the buffer that will contain the string
1021 			DumpNameBuff=ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength, '5PWA');
1022 			if(DumpNameBuff==NULL || Open->DumpFileName.Buffer!=NULL){
1023 				IF_LOUD(DbgPrint("NPF: unable to allocate the dump filename: not enough memory or name already set\n");)
1024 					EXIT_FAILURE(0);
1025 			}
1026 
1027 			// Copy the buffer
1028 			RtlCopyBytes((PVOID)DumpNameBuff,
1029 				Irp->AssociatedIrp.SystemBuffer,
1030 				IrpSp->Parameters.DeviceIoControl.InputBufferLength);
1031 
1032 			// Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system
1033 			((PSHORT)DumpNameBuff)[IrpSp->Parameters.DeviceIoControl.InputBufferLength/2-1]=0;
1034 
1035 			// Create the unicode string
1036 			RtlInitUnicodeString(&Open->DumpFileName, DumpNameBuff);
1037 
1038 			IF_LOUD(DbgPrint("NPF: dump file name set to %ws, len=%d\n",
1039 				Open->DumpFileName.Buffer,
1040 				IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
1041 
1042 			// Try to create the file
1043 			if ( NT_SUCCESS( NPF_OpenDumpFile(Open,&Open->DumpFileName,FALSE)) &&
1044 				NT_SUCCESS( NPF_StartDump(Open)))
1045 			{
1046 				EXIT_SUCCESS(0);
1047 			}
1048 		}
1049 
1050 		EXIT_FAILURE(0);
1051 
1052 		break;
1053 #endif // #if 0
1054 	case BIOCSETDUMPLIMITS:
1055 
1056 ///////kernel dump does not work at the moment//////////////////////////////////////////
1057 		EXIT_FAILURE(0);
1058 ///////kernel dump does not work at the moment//////////////////////////////////////////
1059 
1060 //
1061 // Remove the following #if 0 to enable the kernel dump again
1062 //
1063 #if 0
1064 		if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < 2*sizeof(ULONG))
1065 		{
1066 			EXIT_FAILURE(0);
1067 		}
1068 
1069 		Open->MaxDumpBytes = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
1070 		Open->MaxDumpPacks = *((PULONG)Irp->AssociatedIrp.SystemBuffer + 1);
1071 
1072 		IF_LOUD(DbgPrint("NPF: Set dump limits to %u bytes, %u packs\n", Open->MaxDumpBytes, Open->MaxDumpPacks);)
1073 
1074 		EXIT_SUCCESS(0);
1075 
1076 		break;
1077 
1078 #endif // #if 0
1079 
1080 	case BIOCISDUMPENDED:
1081 
1082 ///////kernel dump does not work at the moment//////////////////////////////////////////
1083 		EXIT_FAILURE(0);
1084 ///////kernel dump does not work at the moment//////////////////////////////////////////
1085 
1086 //
1087 // Remove the following #if 0 to enable the kernel dump again
1088 //
1089 #if 0
1090 		if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT))
1091 		{
1092 			EXIT_FAILURE(0);
1093 		}
1094 
1095 		*((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0;
1096 
1097 		EXIT_SUCCESS(4);
1098 
1099 		break;
1100 
1101 #endif // #if 0
1102 
1103 	case BIOCSETBUFFERSIZE:
1104 
1105 
1106 		if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
1107 		{
1108 			EXIT_FAILURE(0);
1109 		}
1110 
1111 		// Get the number of bytes to allocate
1112 		dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
1113 
1114 		Open->SkipProcessing = 1;
1115 
1116 		do
1117 		{
1118 			Flag = FALSE;
1119 			for(i=0;i<NCpu;i++)
1120 				if (Open->CpuData[i].Processing == 1)
1121 					Flag = TRUE;
1122 		}
1123 		while(Flag);  //BUSY FORM WAITING...
1124 
1125 		if (dim / NCpu < sizeof(struct PacketHeader))
1126 			dim = 0;
1127 		else
1128 		{
1129 			tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, '6PWA');
1130 			if (tpointer==NULL)
1131 			{
1132 				// no memory
1133 				Open->SkipProcessing = 0;
1134 				EXIT_FAILURE(0);
1135 			}
1136 		}
1137 
1138 		if (Open->CpuData[0].Buffer != NULL)
1139 			ExFreePool(Open->CpuData[0].Buffer);
1140 
1141 		for (i = 0 ; i < NCpu ; i++)
1142 		{
1143 			if (dim > 0)
1144 				Open->CpuData[i].Buffer=(PUCHAR)tpointer + (dim/NCpu)*i;
1145 			else
1146 				Open->CpuData[i].Buffer = NULL;
1147 			Open->CpuData[i].Free = dim/NCpu;
1148 			Open->CpuData[i].P = 0;
1149 			Open->CpuData[i].C = 0;
1150 			Open->CpuData[i].Accepted = 0;
1151 			Open->CpuData[i].Dropped = 0;
1152 			Open->CpuData[i].Received = 0;
1153 		}
1154 
1155 		Open->ReaderSN=0;
1156 		Open->WriterSN=0;
1157 
1158 		Open->Size = dim/NCpu;
1159 
1160 		Open->SkipProcessing = 0;
1161 		EXIT_SUCCESS(dim);
1162 
1163 		break;
1164 
1165 	case BIOCSRTIMEOUT: //set the timeout on the read calls
1166 
1167 
1168 		if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
1169 		{
1170 			EXIT_FAILURE(0);
1171 		}
1172 
1173 		timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
1174 		if(timeout == (ULONG)-1)
1175 			Open->TimeOut.QuadPart=(LONGLONG)IMMEDIATE;
1176 		else
1177 		{
1178 			Open->TimeOut.QuadPart = (LONGLONG)timeout;
1179 			Open->TimeOut.QuadPart *= 10000;
1180 			Open->TimeOut.QuadPart = -Open->TimeOut.QuadPart;
1181 		}
1182 
1183 		IF_LOUD(DbgPrint("NPF: read timeout set to %d:%d\n",Open->TimeOut.HighPart,Open->TimeOut.LowPart);)
1184 		EXIT_SUCCESS(timeout);
1185 
1186 		break;
1187 
1188 	case BIOCSWRITEREP: //set the writes repetition number
1189 
1190 	if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
1191 	{
1192 		EXIT_FAILURE(0);
1193 	}
1194 
1195 		Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
1196 
1197 		EXIT_SUCCESS(Open->Nwrites);
1198 
1199 		break;
1200 
1201 	case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application
1202 
1203 		if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
1204 		{
1205 			EXIT_FAILURE(0);
1206 		}
1207 
1208 		Open->MinToCopy = (*((PULONG)Irp->AssociatedIrp.SystemBuffer))/NCpu;  //An hack to make the NCPU-buffers behave like a larger one
1209 
1210 		EXIT_SUCCESS(Open->MinToCopy);
1211 
1212 		break;
1213 
1214 	case IOCTL_PROTOCOL_RESET:
1215 
1216         IF_LOUD(DbgPrint("NPF: IoControl - Reset request\n");)
1217 
1218 		IoMarkIrpPending(Irp);
1219 		Irp->IoStatus.Status = STATUS_SUCCESS;
1220 
1221 		ExInterlockedInsertTailList(&Open->ResetIrpList,&Irp->Tail.Overlay.ListEntry,&Open->RequestSpinLock);
1222         NdisReset(&Status,Open->AdapterHandle);
1223         if (Status != NDIS_STATUS_PENDING)
1224         {
1225             IF_LOUD(DbgPrint("NPF: IoControl - ResetComplete being called\n");)
1226 				NPF_ResetComplete(Open,Status);
1227         }
1228 
1229 		break;
1230 
1231 
1232 	case BIOCSETOID:
1233 	case BIOCQUERYOID:
1234 
1235 		// Extract a request from the list of free ones
1236 		RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock);
1237 		if (RequestListEntry == NULL)
1238 		{
1239 			EXIT_FAILURE(0);
1240 		}
1241 
1242 		pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement);
1243 		pRequest->Irp = Irp;
1244 		pRequest->Internal = FALSE;
1245 
1246 
1247 		//
1248         //  See if it is an Ndis request
1249         //
1250         OidData=Irp->AssociatedIrp.SystemBuffer;
1251 
1252         if (((FunctionCode == BIOCSETOID) || (FunctionCode == BIOCQUERYOID))
1253             &&
1254             (IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength)
1255             &&
1256             (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA))
1257             &&
1258             (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) {
1259 
1260             IF_LOUD(DbgPrint("NPF: IoControl: Request: Oid=%08lx, Length=%08lx\n",OidData->Oid,OidData->Length);)
1261 
1262 				//
1263 				//  The buffer is valid
1264 				//
1265 				if (FunctionCode == BIOCSETOID){
1266 
1267 					pRequest->Request.RequestType=NdisRequestSetInformation;
1268 					pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid;
1269 
1270 					pRequest->Request.DATA.SET_INFORMATION.InformationBuffer=OidData->Data;
1271 					pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength=OidData->Length;
1272 
1273 
1274 				}
1275 				else{
1276 
1277 					pRequest->Request.RequestType=NdisRequestQueryInformation;
1278 					pRequest->Request.DATA.QUERY_INFORMATION.Oid=OidData->Oid;
1279 
1280 					pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer=OidData->Data;
1281 					pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength=OidData->Length;
1282 
1283 				}
1284 
1285 				NdisResetEvent(&Open->IOEvent);
1286 				//
1287 				//  submit the request
1288 				//
1289 				NdisRequest(
1290 					&Status,
1291 					Open->AdapterHandle,
1292 					&pRequest->Request
1293 					);
1294 
1295         } else {
1296             //
1297             //  buffer too small
1298             //
1299             Status=NDIS_STATUS_FAILURE;
1300             pRequest->Request.DATA.SET_INFORMATION.BytesRead=0;
1301             pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0;
1302 
1303         }
1304 
1305         if (Status != NDIS_STATUS_PENDING) {
1306             IF_LOUD(DbgPrint("NPF: Calling RequestCompleteHandler\n");)
1307 
1308 			NPF_RequestComplete(Open, &pRequest->Request, Status);
1309             return Status;
1310 
1311         }
1312 
1313 		NdisWaitEvent(&Open->IOEvent, 5000);
1314 
1315 		return(Open->IOStatus);
1316 
1317 		break;
1318 
1319 	case BIOCISETLOBBEH:
1320 
1321 		if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(INT))
1322 		{
1323 			SET_FAILURE_BUFFER_SMALL();
1324 			break;
1325 		}
1326 
1327 #ifdef __NPF_NT4__
1328 
1329 		// NT4 doesn't support loopback inhibition / activation
1330 		SET_FAILURE_INVALID_REQUEST();
1331 		break;
1332 
1333 #else //not __NPF_NT4__
1334 		//
1335 		// win2000/xp/2003/vista
1336 		//
1337 		if(*(PINT)Irp->AssociatedIrp.SystemBuffer == 1)
1338 		{
1339 			Open->SkipSentPackets = TRUE;
1340 
1341 			//
1342 			// Reset the capture buffers, since they could contain loopbacked packets
1343 			//
1344 
1345 //			NPF_ResetBufferContents(Open);
1346 
1347 			SET_RESULT_SUCCESS(0);
1348 			break;
1349 
1350 		}
1351 		else
1352 			if(*(PINT)Irp->AssociatedIrp.SystemBuffer == 2)
1353 			{
1354 				Open->SkipSentPackets = FALSE;
1355 
1356 				SET_RESULT_SUCCESS(0);
1357 				break;
1358 			}
1359 			else
1360 			{
1361 				// Unknown operation
1362 				SET_FAILURE_INVALID_REQUEST();
1363 				break;
1364 			}
1365 
1366 #endif // !__NPF_NT4__
1367 			break;
1368 
1369 
1370 
1371 	default:
1372 
1373 		EXIT_FAILURE(0);
1374 	}
1375 
1376 	if (FunctionCode == BIOCISETLOBBEH)
1377 	{
1378 		Irp->IoStatus.Information = Information;
1379 		Irp->IoStatus.Status = Status;
1380 		IoCompleteRequest(Irp, IO_NO_INCREMENT);
1381 	}
1382 
1383 	return Status;
1384 }
1385 
1386 //-------------------------------------------------------------------
1387 
1388 VOID
NPF_RequestComplete(IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_REQUEST NdisRequest,IN NDIS_STATUS Status)1389 NPF_RequestComplete(
1390     IN NDIS_HANDLE   ProtocolBindingContext,
1391     IN PNDIS_REQUEST NdisRequest,
1392     IN NDIS_STATUS   Status
1393     )
1394 
1395 {
1396     POPEN_INSTANCE      Open;
1397     PIO_STACK_LOCATION  IrpSp;
1398     PIRP                Irp;
1399     PINTERNAL_REQUEST   pRequest;
1400     UINT                FunctionCode;
1401 //	KIRQL				OldIrq;
1402 
1403     PPACKET_OID_DATA    OidData;
1404 
1405     IF_LOUD(DbgPrint("NPF: RequestComplete\n");)
1406 
1407     Open= (POPEN_INSTANCE)ProtocolBindingContext;
1408 
1409     pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request);
1410     Irp=pRequest->Irp;
1411 
1412 	if(pRequest->Internal == TRUE){
1413 
1414 		// Put the request in the list of the free ones
1415 		ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
1416 
1417 	    if(Status != NDIS_STATUS_SUCCESS)
1418 			Open->MaxFrameSize = 1600;	// Assume Ethernet
1419 
1420 		// We always return success, because the adapter has been already opened
1421 		Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
1422 		Irp->IoStatus.Information = 0;
1423 		IoCompleteRequest(Irp, IO_NO_INCREMENT);
1424 		return;
1425 	}
1426 
1427     IrpSp = IoGetCurrentIrpStackLocation(Irp);
1428 
1429     FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
1430 
1431     OidData=Irp->AssociatedIrp.SystemBuffer;
1432 
1433     if (FunctionCode == BIOCSETOID) {
1434 
1435         OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead;
1436 
1437     } else {
1438 
1439         if (FunctionCode == BIOCQUERYOID) {
1440 
1441             OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;
1442 
1443 		    IF_LOUD(DbgPrint("RequestComplete: BytesWritten=%d\n",pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten);)
1444         }
1445 
1446     }
1447 
1448     Irp->IoStatus.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1449 
1450     IF_LOUD(DbgPrint("RequestComplete: BytesReturned=%d\n",IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
1451 
1452     ExInterlockedInsertTailList(
1453         &Open->RequestList,
1454         &pRequest->ListElement,
1455         &Open->RequestSpinLock);
1456 
1457     Irp->IoStatus.Status = Status;
1458 
1459 	Open->IOStatus = Status;
1460 
1461 	IoCompleteRequest(Irp, IO_NO_INCREMENT);
1462 
1463 	// Unlock the caller
1464 	NdisSetEvent(&Open->IOEvent);
1465 
1466     return;
1467 
1468 
1469 }
1470 
1471 //-------------------------------------------------------------------
1472 
1473 VOID
NPF_Status(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status,IN PVOID StatusBuffer,IN UINT StatusBufferSize)1474 NPF_Status(
1475     IN NDIS_HANDLE   ProtocolBindingContext,
1476     IN NDIS_STATUS   Status,
1477     IN PVOID         StatusBuffer,
1478     IN UINT          StatusBufferSize
1479     )
1480 
1481 {
1482 
1483     IF_LOUD(DbgPrint("NPF: Status Indication\n");)
1484 
1485     return;
1486 
1487 }
1488 
1489 //-------------------------------------------------------------------
1490 
1491 VOID
NPF_StatusComplete(IN NDIS_HANDLE ProtocolBindingContext)1492 NPF_StatusComplete(
1493     IN NDIS_HANDLE  ProtocolBindingContext
1494     )
1495 
1496 {
1497 
1498     IF_LOUD(DbgPrint("NPF: StatusIndicationComplete\n");)
1499 
1500     return;
1501 
1502 }
1503 
1504 //-------------------------------------------------------------------
1505 
1506 NTSTATUS
NPF_ReadRegistry(IN PWSTR * MacDriverName,IN PWSTR * PacketDriverName,IN PUNICODE_STRING RegistryPath)1507 NPF_ReadRegistry(
1508     IN  PWSTR              *MacDriverName,
1509     IN  PWSTR              *PacketDriverName,
1510     IN  PUNICODE_STRING     RegistryPath
1511     )
1512 
1513 {
1514     NTSTATUS   Status;
1515 
1516     RTL_QUERY_REGISTRY_TABLE ParamTable[4];
1517 
1518     PWSTR      Bind       = L"Bind";
1519     PWSTR      Export     = L"Export";
1520     PWSTR      Parameters = L"Parameters";
1521     PWSTR      Linkage    = L"Linkage";
1522 
1523     PWCHAR     Path;
1524 
1525 
1526 
1527     Path=ExAllocatePoolWithTag(PagedPool, RegistryPath->Length+sizeof(WCHAR), '7PWA');
1528 
1529     if (Path == NULL) {
1530         return STATUS_INSUFFICIENT_RESOURCES;
1531     }
1532 
1533     RtlZeroMemory(
1534         Path,
1535         RegistryPath->Length+sizeof(WCHAR)
1536         );
1537 
1538     RtlCopyMemory(
1539         Path,
1540         RegistryPath->Buffer,
1541         RegistryPath->Length
1542         );
1543 
1544     IF_LOUD(DbgPrint("NPF: Reg path is %ws\n",RegistryPath->Buffer);)
1545 
1546     RtlZeroMemory(
1547         ParamTable,
1548         sizeof(ParamTable)
1549         );
1550 
1551 
1552 
1553     //
1554     //  change to the linkage key
1555     //
1556 
1557     ParamTable[0].QueryRoutine = NULL;
1558     ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
1559     ParamTable[0].Name = Linkage;
1560 
1561 
1562     //
1563     //  Get the name of the mac driver we should bind to
1564     //
1565 
1566     ParamTable[1].QueryRoutine = NPF_QueryRegistryRoutine;
1567     ParamTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED |
1568                           RTL_QUERY_REGISTRY_NOEXPAND;
1569 
1570     ParamTable[1].Name = Bind;
1571     ParamTable[1].EntryContext = (PVOID)MacDriverName;
1572     ParamTable[1].DefaultType = REG_MULTI_SZ;
1573 
1574     //
1575     //  Get the name that we should use for the driver object
1576     //
1577 
1578     ParamTable[2].QueryRoutine = NPF_QueryRegistryRoutine;
1579     ParamTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED |
1580                           RTL_QUERY_REGISTRY_NOEXPAND;
1581 
1582     ParamTable[2].Name = Export;
1583     ParamTable[2].EntryContext = (PVOID)PacketDriverName;
1584     ParamTable[2].DefaultType = REG_MULTI_SZ;
1585 
1586 
1587     Status=RtlQueryRegistryValues(
1588                RTL_REGISTRY_ABSOLUTE,
1589                Path,
1590                ParamTable,
1591                NULL,
1592                NULL
1593                );
1594 
1595 
1596     ExFreePool(Path);
1597 
1598     return Status;
1599 }
1600 
1601 //-------------------------------------------------------------------
1602 
1603 NTSTATUS
NPF_QueryRegistryRoutine(IN PWSTR ValueName,IN ULONG ValueType,IN PVOID ValueData,IN ULONG ValueLength,IN PVOID Context,IN PVOID EntryContext)1604 NPF_QueryRegistryRoutine(
1605     IN PWSTR     ValueName,
1606     IN ULONG     ValueType,
1607     IN PVOID     ValueData,
1608     IN ULONG     ValueLength,
1609     IN PVOID     Context,
1610     IN PVOID     EntryContext
1611     )
1612 
1613 {
1614 
1615     PUCHAR       Buffer;
1616 
1617     IF_LOUD(DbgPrint("Perf: QueryRegistryRoutine\n");)
1618 
1619     if (ValueType != REG_MULTI_SZ) {
1620 
1621         return STATUS_OBJECT_NAME_NOT_FOUND;
1622 
1623     }
1624 
1625     Buffer=ExAllocatePoolWithTag(NonPagedPool, ValueLength, '8PWA');
1626 
1627     if (Buffer==NULL) {
1628 
1629         return STATUS_INSUFFICIENT_RESOURCES;
1630 
1631     }
1632 
1633     RtlCopyMemory(
1634         Buffer,
1635         ValueData,
1636         ValueLength
1637         );
1638 
1639     *((PUCHAR *)EntryContext)=Buffer;
1640 
1641     return STATUS_SUCCESS;
1642 
1643 }
1644