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