00001 /* 00002 * Copyright (c) 1999, 2000 00003 * Politecnico di Torino. All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that: (1) source code distributions 00007 * retain the above copyright notice and this paragraph in its entirety, (2) 00008 * distributions including binary code include the above copyright notice and 00009 * this paragraph in its entirety in the documentation or other materials 00010 * provided with the distribution, and (3) all advertising materials mentioning 00011 * features or use of this software display the following acknowledgement: 00012 * ``This product includes software developed by the Politecnico 00013 * di Torino, and its contributors.'' Neither the name of 00014 * the University nor the names of its contributors may be used to endorse 00015 * or promote products derived from this software without specific prior 00016 * written permission. 00017 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 00018 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 00019 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00020 */ 00021 00022 #include "ntddk.h" 00023 #include "ntiologc.h" 00024 #include "ndis.h" 00025 00026 #include "debug.h" 00027 #include "packet.h" 00028 00029 static NDIS_MEDIUM MediumArray[] = { 00030 NdisMedium802_3, 00031 NdisMediumWan, 00032 NdisMediumFddi, 00033 NdisMediumArcnet878_2, 00034 NdisMediumAtm, 00035 NdisMedium802_5 00036 }; 00037 00038 #define NUM_NDIS_MEDIA (sizeof MediumArray / sizeof MediumArray[0]) 00039 00040 ULONG NamedEventsCounter=0; 00041 00042 //Itoa. Replaces the buggy RtlIntegerToUnicodeString 00043 void PacketItoa(UINT n,PUCHAR buf){ 00044 int i; 00045 00046 for(i=0;i<20;i+=2){ 00047 buf[18-i]=(n%10)+48; 00048 buf[19-i]=0; 00049 n/=10; 00050 } 00051 00052 } 00053 00055 struct time_conv G_Start_Time = { 00056 0, 00057 {0, 0}, 00058 }; 00059 00060 UINT n_Opened_Instances = 0; 00061 00062 NDIS_SPIN_LOCK Opened_Instances_Lock; 00063 00064 //------------------------------------------------------------------- 00065 00066 NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) 00067 { 00068 00069 PDEVICE_EXTENSION DeviceExtension; 00070 00071 POPEN_INSTANCE Open; 00072 00073 PIO_STACK_LOCATION IrpSp; 00074 00075 NDIS_STATUS Status; 00076 NDIS_STATUS ErrorStatus; 00077 UINT i; 00078 PUCHAR tpointer; 00079 PLIST_ENTRY PacketListEntry; 00080 PCHAR EvName; 00081 00082 00083 IF_LOUD(DbgPrint("NPF: OpenAdapter\n");) 00084 00085 DeviceExtension = DeviceObject->DeviceExtension; 00086 00087 00088 IrpSp = IoGetCurrentIrpStackLocation(Irp); 00089 00090 // allocate some memory for the open structure 00091 Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), '0OWA'); 00092 00093 00094 if (Open==NULL) { 00095 // no memory 00096 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 00097 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00098 return STATUS_INSUFFICIENT_RESOURCES; 00099 } 00100 00101 RtlZeroMemory( 00102 Open, 00103 sizeof(OPEN_INSTANCE) 00104 ); 00105 00106 00107 EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000"), '1OWA'); 00108 00109 if (EvName==NULL) { 00110 // no memory 00111 ExFreePool(Open); 00112 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 00113 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00114 return STATUS_INSUFFICIENT_RESOURCES; 00115 } 00116 00117 // Save or open here 00118 IrpSp->FileObject->FsContext=Open; 00119 00120 Open->DeviceExtension=DeviceExtension; 00121 00122 00123 // Save the Irp here for the completeion routine to retrieve 00124 Open->OpenCloseIrp=Irp; 00125 00126 // Allocate a packet pool for our xmit and receive packets 00127 NdisAllocatePacketPool( 00128 &Status, 00129 &Open->PacketPool, 00130 TRANSMIT_PACKETS, 00131 sizeof(PACKET_RESERVED)); 00132 00133 00134 if (Status != NDIS_STATUS_SUCCESS) { 00135 00136 IF_LOUD(DbgPrint("NPF: Failed to allocate packet pool\n");) 00137 00138 ExFreePool(Open); 00139 ExFreePool(EvName); 00140 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 00141 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00142 return STATUS_INSUFFICIENT_RESOURCES; 00143 } 00144 00145 00146 RtlCopyBytes(EvName,L"\\BaseNamedObjects\\NPF0000000000",sizeof(L"\\BaseNamedObjects\\NPF0000000000")); 00147 00148 //Create the string containing the name of the read event 00149 RtlInitUnicodeString(&Open->ReadEventName,(PCWSTR) EvName); 00150 00151 PacketItoa(NamedEventsCounter,(PUCHAR)(Open->ReadEventName.Buffer+21)); 00152 00153 InterlockedIncrement(&NamedEventsCounter); 00154 00155 IF_LOUD(DbgPrint("\nCreated the named event for the read; name=%ws, counter=%d\n", Open->ReadEventName.Buffer,NamedEventsCounter-1);) 00156 00157 //allocate the event objects 00158 Open->ReadEvent=IoCreateNotificationEvent(&Open->ReadEventName,&Open->ReadEventHandle); 00159 if(Open->ReadEvent==NULL){ 00160 ExFreePool(Open); 00161 ExFreePool(EvName); 00162 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 00163 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00164 return STATUS_INSUFFICIENT_RESOURCES; 00165 } 00166 00167 KeInitializeEvent(Open->ReadEvent, NotificationEvent, FALSE); 00168 KeClearEvent(Open->ReadEvent); 00169 NdisInitializeEvent(&Open->WriteEvent); 00170 NdisInitializeEvent(&Open->IOEvent); 00171 NdisInitializeEvent(&Open->DumpEvent); 00172 NdisInitializeEvent(&Open->IOEvent); 00173 NdisAllocateSpinLock(&Open->machine_lock); 00174 00175 00176 // list to hold irp's want to reset the adapter 00177 InitializeListHead(&Open->ResetIrpList); 00178 00179 00180 // Initialize the request list 00181 KeInitializeSpinLock(&Open->RequestSpinLock); 00182 InitializeListHead(&Open->RequestList); 00183 00184 // Initializes the extended memory of the NPF machine 00185 Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, '2OWA'); 00186 if((Open->mem_ex.buffer) == NULL) 00187 { 00188 // no memory 00189 ExFreePool(Open); 00190 ExFreePool(EvName); 00191 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 00192 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00193 return STATUS_INSUFFICIENT_RESOURCES; 00194 } 00195 00196 Open->mem_ex.size = DEFAULT_MEM_EX_SIZE; 00197 RtlZeroMemory(Open->mem_ex.buffer, DEFAULT_MEM_EX_SIZE); 00198 00199 // 00200 // Initialize the open instance 00201 // 00202 Open->BufSize = 0; 00203 Open->Buffer = NULL; 00204 Open->Bhead = 0; 00205 Open->Btail = 0; 00206 Open->BLastByte = 0; 00207 Open->Dropped = 0; //reset the dropped packets counter 00208 Open->Received = 0; //reset the received packets counter 00209 Open->Accepted = 0; //reset the accepted packets counter 00210 Open->bpfprogram = NULL; //reset the filter 00211 Open->mode = MODE_CAPT; 00212 Open->Nbytes.QuadPart = 0; 00213 Open->Npackets.QuadPart = 0; 00214 Open->Nwrites = 1; 00215 Open->Multiple_Write_Counter = 0; 00216 Open->MinToCopy = 0; 00217 Open->TimeOut.QuadPart = (LONGLONG)1; 00218 Open->Bound = TRUE; 00219 Open->DumpFileName.Buffer = NULL; 00220 Open->DumpFileHandle = NULL; 00221 Open->tme.active = TME_NONE_ACTIVE; 00222 Open->DumpLimitReached = FALSE; 00223 00224 //allocate the spinlock for the statistic counters 00225 NdisAllocateSpinLock(&Open->CountersLock); 00226 00227 //allocate the spinlock for the buffer pointers 00228 NdisAllocateSpinLock(&Open->BufLock); 00229 00230 // 00231 // link up the request stored in our open block 00232 // 00233 for (i=0;i<MAX_REQUESTS;i++) { 00234 ExInterlockedInsertTailList( 00235 &Open->RequestList, 00236 &Open->Requests[i].ListElement, 00237 &Open->RequestSpinLock); 00238 00239 } 00240 00241 00242 IoMarkIrpPending(Irp); 00243 00244 // 00245 // Try to open the MAC 00246 // 00247 IF_LOUD(DbgPrint("NPF: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);) 00248 00249 NdisOpenAdapter( 00250 &Status, 00251 &ErrorStatus, 00252 &Open->AdapterHandle, 00253 &Open->Medium, 00254 MediumArray, 00255 NUM_NDIS_MEDIA, 00256 DeviceExtension->NdisProtocolHandle, 00257 Open, 00258 &DeviceExtension->AdapterName, 00259 0, 00260 NULL); 00261 00262 IF_LOUD(DbgPrint("NPF: Opened the device, Status=%x\n",Status);) 00263 00264 if (Status != NDIS_STATUS_PENDING) 00265 { 00266 NPF_OpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS); 00267 } 00268 00269 return(STATUS_PENDING); 00270 } 00271 00272 //------------------------------------------------------------------- 00273 00274 VOID NPF_OpenAdapterComplete( 00275 IN NDIS_HANDLE ProtocolBindingContext, 00276 IN NDIS_STATUS Status, 00277 IN NDIS_STATUS OpenErrorStatus) 00278 { 00279 00280 PIRP Irp; 00281 POPEN_INSTANCE Open; 00282 00283 IF_LOUD(DbgPrint("NPF: OpenAdapterComplete\n");) 00284 00285 Open= (POPEN_INSTANCE)ProtocolBindingContext; 00286 00287 // 00288 // get the open irp 00289 // 00290 Irp=Open->OpenCloseIrp; 00291 00292 if (Status != NDIS_STATUS_SUCCESS) { 00293 00294 IF_LOUD(DbgPrint("NPF: OpenAdapterComplete-FAILURE\n");) 00295 00296 NdisFreePacketPool(Open->PacketPool); 00297 00298 //free mem_ex 00299 Open->mem_ex.size = 0; 00300 if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer); 00301 00302 ExFreePool(Open->ReadEventName.Buffer); 00303 00304 ExFreePool(Open); 00305 } 00306 else { 00307 NdisAcquireSpinLock(&Opened_Instances_Lock); 00308 n_Opened_Instances++; 00309 NdisReleaseSpinLock(&Opened_Instances_Lock); 00310 00311 IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);) 00312 00313 // Get the absolute value of the system boot time. 00314 // This is used for timestamp conversion. 00315 TIME_SYNCHRONIZE(&G_Start_Time); 00316 } 00317 00318 Irp->IoStatus.Status = Status; 00319 Irp->IoStatus.Information = 0; 00320 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00321 00322 return; 00323 00324 } 00325 00326 //------------------------------------------------------------------- 00327 00328 NTSTATUS 00329 NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) 00330 { 00331 00332 POPEN_INSTANCE Open; 00333 NDIS_STATUS Status; 00334 PIO_STACK_LOCATION IrpSp; 00335 LARGE_INTEGER ThreadDelay; 00336 00337 IF_LOUD(DbgPrint("NPF: CloseAdapter\n");) 00338 00339 IrpSp = IoGetCurrentIrpStackLocation(Irp); 00340 00341 Open=IrpSp->FileObject->FsContext; 00342 00343 // Reset the buffer size. This tells the dump thread to stop. 00344 Open->BufSize = 0; 00345 00346 if( Open->Bound == FALSE){ 00347 00348 NdisWaitEvent(&Open->IOEvent,10000); 00349 00350 // Free the filter if it's present 00351 if(Open->bpfprogram != NULL) 00352 ExFreePool(Open->bpfprogram); 00353 00354 // Free the jitted filter if it's present 00355 if(Open->Filter != NULL) 00356 BPF_Destroy_JIT_Filter(Open->Filter); 00357 00358 //free the buffer 00359 Open->BufSize=0; 00360 if(Open->Buffer != NULL)ExFreePool(Open->Buffer); 00361 00362 //free mem_ex 00363 Open->mem_ex.size = 0; 00364 if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer); 00365 00366 NdisFreePacketPool(Open->PacketPool); 00367 00368 // Free the string with the name of the dump file 00369 if(Open->DumpFileName.Buffer!=NULL) 00370 ExFreePool(Open->DumpFileName.Buffer); 00371 00372 ExFreePool(Open->ReadEventName.Buffer); 00373 ExFreePool(Open); 00374 00375 Irp->IoStatus.Information = 0; 00376 Irp->IoStatus.Status = STATUS_SUCCESS; 00377 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00378 00379 return(STATUS_SUCCESS); 00380 } 00381 00382 // Unfreeze the consumer 00383 if(Open->mode & MODE_DUMP) 00384 NdisSetEvent(&Open->DumpEvent); 00385 else 00386 KeSetEvent(Open->ReadEvent,0,FALSE); 00387 00388 // Save the IRP 00389 Open->OpenCloseIrp = Irp; 00390 00391 IoMarkIrpPending(Irp); 00392 00393 // If this instance is in dump mode, complete the dump and close the file 00394 if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL){ 00395 00396 NTSTATUS wres; 00397 00398 ThreadDelay.QuadPart = -50000000; 00399 // Wait the completion of the thread 00400 wres = KeWaitForSingleObject(Open->DumpThreadObject, 00401 UserRequest, 00402 KernelMode, 00403 TRUE, 00404 &ThreadDelay); 00405 00406 ObDereferenceObject(Open->DumpThreadObject); 00407 00408 00409 // Flush and close the dump file 00410 NPF_CloseDumpFile(Open); 00411 } 00412 00413 // Destroy the read Event 00414 ZwClose(Open->ReadEventHandle); 00415 00416 // Close the adapter 00417 NdisCloseAdapter( 00418 &Status, 00419 Open->AdapterHandle 00420 ); 00421 00422 if (Status != NDIS_STATUS_PENDING) { 00423 00424 NPF_CloseAdapterComplete( 00425 Open, 00426 Status 00427 ); 00428 return STATUS_SUCCESS; 00429 00430 } 00431 00432 return(STATUS_PENDING); 00433 } 00434 00435 //------------------------------------------------------------------- 00436 00437 VOID 00438 NPF_CloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status) 00439 { 00440 POPEN_INSTANCE Open; 00441 PIRP Irp; 00442 00443 IF_LOUD(DbgPrint("NPF: CloseAdapterComplete\n");) 00444 00445 Open= (POPEN_INSTANCE)ProtocolBindingContext; 00446 00447 // free the allocated structures only if the instance is still bound to the adapter 00448 if(Open->Bound == TRUE){ 00449 00450 // Free the filter if it's present 00451 if(Open->bpfprogram != NULL) 00452 ExFreePool(Open->bpfprogram); 00453 00454 // Free the jitted filter if it's present 00455 if(Open->Filter != NULL) 00456 BPF_Destroy_JIT_Filter(Open->Filter); 00457 00458 //free the buffer 00459 Open->BufSize = 0; 00460 if(Open->Buffer!=NULL)ExFreePool(Open->Buffer); 00461 00462 //free mem_ex 00463 Open->mem_ex.size = 0; 00464 if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer); 00465 00466 NdisFreePacketPool(Open->PacketPool); 00467 00468 Irp=Open->OpenCloseIrp; 00469 00470 // Free the string with the name of the dump file 00471 if(Open->DumpFileName.Buffer!=NULL) 00472 ExFreePool(Open->DumpFileName.Buffer); 00473 00474 ExFreePool(Open->ReadEventName.Buffer); 00475 ExFreePool(Open); 00476 00477 // Complete the request only if the instance is still bound to the adapter 00478 Irp->IoStatus.Status = STATUS_SUCCESS; 00479 Irp->IoStatus.Information = 0; 00480 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00481 } 00482 else 00483 NdisSetEvent(&Open->IOEvent); 00484 00485 // Decrease the counter of open instances 00486 NdisAcquireSpinLock(&Opened_Instances_Lock); 00487 n_Opened_Instances--; 00488 NdisReleaseSpinLock(&Opened_Instances_Lock); 00489 00490 IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);) 00491 00492 if(n_Opened_Instances == 0){ 00493 // Force a synchronization at the next NPF_Open(). 00494 // This hopefully avoids the synchronization issues caused by hibernation or standby. 00495 TIME_DESYNCHRONIZE(&G_Start_Time); 00496 } 00497 00498 return; 00499 00500 } 00501 //------------------------------------------------------------------- 00502 00503 #ifdef NDIS50 00504 NDIS_STATUS 00505 NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent) 00506 { 00507 IF_LOUD(DbgPrint("NPF: PowerChange\n");) 00508 00509 TIME_DESYNCHRONIZE(&G_Start_Time); 00510 00511 TIME_SYNCHRONIZE(&G_Start_Time); 00512 00513 return STATUS_SUCCESS; 00514 } 00515 #endif 00516 00517 //------------------------------------------------------------------- 00518 00519 VOID 00520 NPF_BindAdapter( 00521 OUT PNDIS_STATUS Status, 00522 IN NDIS_HANDLE BindContext, 00523 IN PNDIS_STRING DeviceName, 00524 IN PVOID SystemSpecific1, 00525 IN PVOID SystemSpecific2 00526 ) 00527 { 00528 IF_LOUD(DbgPrint("NPF: NPF_BindAdapter\n");) 00529 } 00530 00531 //------------------------------------------------------------------- 00532 00533 VOID 00534 NPF_UnbindAdapter( 00535 OUT PNDIS_STATUS Status, 00536 IN NDIS_HANDLE ProtocolBindingContext, 00537 IN NDIS_HANDLE UnbindContext 00538 ) 00539 { 00540 POPEN_INSTANCE Open =(POPEN_INSTANCE)ProtocolBindingContext; 00541 NDIS_STATUS lStatus; 00542 00543 IF_LOUD(DbgPrint("NPF: NPF_UnbindAdapter\n");) 00544 00545 // Reset the buffer size. This tells the dump thread to stop. 00546 Open->BufSize=0; 00547 00548 NdisResetEvent(&Open->IOEvent); 00549 00550 // This open instance is no more bound to the adapter, set Bound to False 00551 InterlockedExchange( (PLONG) &Open->Bound, FALSE ); 00552 00553 // Awake a possible pending read on this instance 00554 if(Open->mode & MODE_DUMP) 00555 NdisSetEvent(&Open->DumpEvent); 00556 else 00557 KeSetEvent(Open->ReadEvent,0,FALSE); 00558 00559 // If this instance is in dump mode, complete the dump and close the file 00560 if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL) 00561 NPF_CloseDumpFile(Open); 00562 00563 // Destroy the read Event 00564 ZwClose(Open->ReadEventHandle); 00565 00566 // close the adapter 00567 NdisCloseAdapter( 00568 &lStatus, 00569 Open->AdapterHandle 00570 ); 00571 00572 if (lStatus != NDIS_STATUS_PENDING) { 00573 00574 NPF_CloseAdapterComplete( 00575 Open, 00576 lStatus 00577 ); 00578 00579 *Status = NDIS_STATUS_SUCCESS; 00580 return; 00581 00582 } 00583 00584 *Status = NDIS_STATUS_SUCCESS; 00585 return; 00586 } 00587 00588 //------------------------------------------------------------------- 00589 00590 VOID 00591 NPF_ResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status) 00592 00593 { 00594 POPEN_INSTANCE Open; 00595 PIRP Irp; 00596 00597 PLIST_ENTRY ResetListEntry; 00598 00599 IF_LOUD(DbgPrint("NPF: PacketResetComplte\n");) 00600 00601 Open= (POPEN_INSTANCE)ProtocolBindingContext; 00602 00603 00604 // 00605 // remove the reset IRP from the list 00606 // 00607 ResetListEntry=ExInterlockedRemoveHeadList( 00608 &Open->ResetIrpList, 00609 &Open->RequestSpinLock 00610 ); 00611 00612 #if DBG 00613 if (ResetListEntry == NULL) { 00614 DbgBreakPoint(); 00615 return; 00616 } 00617 #endif 00618 00619 Irp=CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry); 00620 00621 Irp->IoStatus.Status = STATUS_SUCCESS; 00622 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00623 00624 IF_LOUD(DbgPrint("NPF: PacketResetComplte exit\n");) 00625 00626 return; 00627 00628 }
documentation. Copyright (c) 2002 Politecnico di Torino. All rights reserved.