_Use_decl_annotations_ NTSTATUS OvsCleanupDevice(PDEVICE_OBJECT deviceObject, PIRP irp) { PIO_STACK_LOCATION irpSp; PFILE_OBJECT fileObject; NTSTATUS status = STATUS_SUCCESS; #ifdef DBG POVS_DEVICE_EXTENSION ovsExt = (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject); if (ovsExt) { ASSERT(ovsExt->numberOpenInstance > 0); } #else UNREFERENCED_PARAMETER(deviceObject); #endif ASSERT(deviceObject == gOvsDeviceObject); irpSp = IoGetCurrentIrpStackLocation(irp); fileObject = irpSp->FileObject; ASSERT(irpSp->MajorFunction == IRP_MJ_CLEANUP); OvsCleanupOpenInstance(fileObject); return OvsCompleteIrpRequest(irp, (ULONG_PTR)0, status); }
/* * -------------------------------------------------------------------------- * Creates the communication device between user and kernel, and also * initializes the data associated data structures. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsCreateDeviceObject(NDIS_HANDLE ovsExtDriverHandle) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; UNICODE_STRING deviceName; UNICODE_STRING symbolicDeviceName; PDRIVER_DISPATCH dispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1]; NDIS_DEVICE_OBJECT_ATTRIBUTES deviceAttributes; OVS_LOG_TRACE("ovsExtDriverHandle: %p", ovsExtDriverHandle); RtlZeroMemory(dispatchTable, (IRP_MJ_MAXIMUM_FUNCTION + 1) * sizeof (PDRIVER_DISPATCH)); dispatchTable[IRP_MJ_CREATE] = OvsOpenCloseDevice; dispatchTable[IRP_MJ_CLOSE] = OvsOpenCloseDevice; dispatchTable[IRP_MJ_CLEANUP] = OvsCleanupDevice; dispatchTable[IRP_MJ_DEVICE_CONTROL] = OvsDeviceControl; NdisInitUnicodeString(&deviceName, OVS_DEVICE_NAME_NT); NdisInitUnicodeString(&symbolicDeviceName, OVS_DEVICE_NAME_DOS); RtlZeroMemory(&deviceAttributes, sizeof (NDIS_DEVICE_OBJECT_ATTRIBUTES)); OVS_INIT_OBJECT_HEADER(&deviceAttributes.Header, NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES, NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1, sizeof (NDIS_DEVICE_OBJECT_ATTRIBUTES)); deviceAttributes.DeviceName = &deviceName; deviceAttributes.SymbolicName = &symbolicDeviceName; deviceAttributes.MajorFunctions = dispatchTable; deviceAttributes.ExtensionSize = sizeof (OVS_DEVICE_EXTENSION); status = NdisRegisterDeviceEx(ovsExtDriverHandle, &deviceAttributes, &gOvsDeviceObject, &gOvsDeviceHandle); if (status != NDIS_STATUS_SUCCESS) { POVS_DEVICE_EXTENSION ovsExt = (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(gOvsDeviceObject); ASSERT(gOvsDeviceObject != NULL); ASSERT(gOvsDeviceHandle != NULL); if (ovsExt) { ovsExt->numberOpenInstance = 0; } } else { /* Initialize the associated data structures. */ OvsInit(); } OVS_LOG_TRACE("DeviceObject: %p", gOvsDeviceObject); return status; }
VOID OvsDeleteDeviceObject() { if (gOvsDeviceHandle) { #ifdef DBG POVS_DEVICE_EXTENSION ovsExt = (POVS_DEVICE_EXTENSION) NdisGetDeviceReservedExtension(gOvsDeviceObject); if (ovsExt) { ASSERT(ovsExt->numberOpenInstance == 0); } #endif ASSERT(gOvsDeviceObject); NdisDeregisterDeviceEx(gOvsDeviceHandle); gOvsDeviceHandle = NULL; gOvsDeviceObject = NULL; } OvsCleanup(); }
_Use_decl_annotations_ NTSTATUS FilterDeviceIoControl( PDEVICE_OBJECT DeviceObject, PIRP Irp ) { PIO_STACK_LOCATION IrpSp; //NTSTATUS Status = STATUS_SUCCESS; PFILTER_DEVICE_EXTENSION FilterDeviceExtension; //PUCHAR InputBuffer; //PUCHAR OutputBuffer; //ULONG InputBufferLength, OutputBufferLength; //PLIST_ENTRY Link; //PUCHAR pInfo; //ULONG InfoLength = 0; //PMS_FILTER pFilter = NULL; //BOOLEAN bFalse = FALSE; UNREFERENCED_PARAMETER(DeviceObject); IrpSp = IoGetCurrentIrpStackLocation(Irp); if (IrpSp->FileObject == NULL) { return(STATUS_UNSUCCESSFUL); } FilterDeviceExtension = (PFILTER_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(DeviceObject); ASSERT(FilterDeviceExtension->Signature == 'FTDR'); return FlowTableIoControl(Irp); }
NTSTATUS OvsOpenCloseDevice(PDEVICE_OBJECT deviceObject, PIRP irp) { PIO_STACK_LOCATION irpSp; NTSTATUS status = STATUS_SUCCESS; PFILE_OBJECT fileObject; POVS_DEVICE_EXTENSION ovsExt = (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject); ASSERT(deviceObject == gOvsDeviceObject); ASSERT(ovsExt != NULL); irpSp = IoGetCurrentIrpStackLocation(irp); fileObject = irpSp->FileObject; OVS_LOG_TRACE("DeviceObject: %p, fileObject:%p, instance: %u", deviceObject, fileObject, ovsExt->numberOpenInstance); switch (irpSp->MajorFunction) { case IRP_MJ_CREATE: status = OvsAddOpenInstance(ovsExt, fileObject); if (STATUS_SUCCESS == status) { InterlockedIncrement((LONG volatile *)&ovsExt->numberOpenInstance); } break; case IRP_MJ_CLOSE: ASSERT(ovsExt->numberOpenInstance > 0); OvsRemoveOpenInstance(fileObject); InterlockedDecrement((LONG volatile *)&ovsExt->numberOpenInstance); break; default: ASSERT(0); } return OvsCompleteIrpRequest(irp, (ULONG_PTR)0, status); }
_Use_decl_annotations_ NTSTATUS FilterDeviceIoControl( PDEVICE_OBJECT DeviceObject, PIRP Irp ) { PIO_STACK_LOCATION IrpSp; NTSTATUS Status = STATUS_SUCCESS; PFILTER_DEVICE_EXTENSION FilterDeviceExtension; PUCHAR InputBuffer; PUCHAR OutputBuffer; ULONG InputBufferLength, OutputBufferLength; PLIST_ENTRY Link; PUCHAR pInfo; ULONG InfoLength = 0; PMS_FILTER pFilter = NULL; BOOLEAN bFalse = FALSE; UNREFERENCED_PARAMETER(DeviceObject); DbgPrint("------------------FilterDeviceIoControl!\n"); IrpSp = IoGetCurrentIrpStackLocation(Irp); if (IrpSp->FileObject == NULL) { return(STATUS_UNSUCCESSFUL); } FilterDeviceExtension = (PFILTER_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(DeviceObject); ASSERT(FilterDeviceExtension->Signature == 'FTDR'); Irp->IoStatus.Information = 0; switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_FILTER_RESTART_ALL: break; case IOCTL_FILTER_RESTART_ONE_INSTANCE: InputBuffer = OutputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; pFilter = filterFindFilterModule (InputBuffer, InputBufferLength); if (pFilter == NULL) { break; } NdisFRestartFilter(pFilter->FilterHandle); break; case IOCTL_FILTER_ENUERATE_ALL_INSTANCES: InputBuffer = OutputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; pInfo = OutputBuffer; FILTER_ACQUIRE_LOCK(&FilterListLock, bFalse); Link = FilterModuleList.Flink; while (Link != &FilterModuleList) { pFilter = CONTAINING_RECORD(Link, MS_FILTER, FilterModuleLink); InfoLength += (pFilter->FilterModuleName.Length + sizeof(USHORT)); if (InfoLength <= OutputBufferLength) { *(PUSHORT)pInfo = pFilter->FilterModuleName.Length; NdisMoveMemory(pInfo + sizeof(USHORT), (PUCHAR)(pFilter->FilterModuleName.Buffer), pFilter->FilterModuleName.Length); pInfo += (pFilter->FilterModuleName.Length + sizeof(USHORT)); } Link = Link->Flink; } FILTER_RELEASE_LOCK(&FilterListLock, bFalse); if (InfoLength <= OutputBufferLength) { Status = NDIS_STATUS_SUCCESS; } // // Buffer is small // else { Status = STATUS_BUFFER_TOO_SMALL; } break; default: DbgPrint("WRONG request received!\n"); break; } Irp->IoStatus.Status = Status; Irp->IoStatus.Information = InfoLength; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }
NDIS_STATUS FilterRegisterDevice( VOID ) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; UNICODE_STRING DeviceName; UNICODE_STRING DeviceLinkUnicodeString; PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1]; NDIS_DEVICE_OBJECT_ATTRIBUTES DeviceAttribute; PFILTER_DEVICE_EXTENSION FilterDeviceExtension; DEBUGP(DL_TRACE, "==>FilterRegisterDevice\n"); NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH)); DispatchTable[IRP_MJ_CREATE] = FilterDispatch; DispatchTable[IRP_MJ_CLEANUP] = FilterDispatch; DispatchTable[IRP_MJ_CLOSE] = FilterDispatch; DispatchTable[IRP_MJ_DEVICE_CONTROL] = FilterDeviceIoControl; DispatchTable[IRP_MJ_INTERNAL_DEVICE_CONTROL] = FilterInternalDeviceIoControl; NdisInitUnicodeString(&DeviceName, NETMAP_NDIS_NTDEVICE_STRING); NdisInitUnicodeString(&DeviceLinkUnicodeString, NETMAP_NDIS_LINKNAME_STRING); // // Create a device object and register our dispatch handlers // NdisZeroMemory(&DeviceAttribute, sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES)); DeviceAttribute.Header.Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES; DeviceAttribute.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1; DeviceAttribute.Header.Size = sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES); DeviceAttribute.DeviceName = &DeviceName; DeviceAttribute.SymbolicName = &DeviceLinkUnicodeString; DeviceAttribute.MajorFunctions = &DispatchTable[0]; DeviceAttribute.ExtensionSize = sizeof(FILTER_DEVICE_EXTENSION); Status = NdisRegisterDeviceEx( FilterDriverHandle, &DeviceAttribute, &DeviceObject, &NdisFilterDeviceHandle ); if (Status == NDIS_STATUS_SUCCESS) { FilterDeviceExtension = NdisGetDeviceReservedExtension(DeviceObject); FilterDeviceExtension->Signature = 'FTDR'; FilterDeviceExtension->Handle = FilterDriverHandle; } DEBUGP(DL_TRACE, "<==FilterRegisterDevice: %x\n", Status); return (Status); }
/* * -------------------------------------------------------------------------- * IOCTL function handler for the device. * -------------------------------------------------------------------------- */ NTSTATUS OvsDeviceControl(PDEVICE_OBJECT deviceObject, PIRP irp) { PIO_STACK_LOCATION irpSp; NTSTATUS status = STATUS_SUCCESS; PFILE_OBJECT fileObject; PVOID inputBuffer = NULL; PVOID outputBuffer = NULL; UINT32 inputBufferLen, outputBufferLen; UINT32 code, replyLen = 0; POVS_OPEN_INSTANCE instance; UINT32 devOp; OVS_MESSAGE ovsMsgReadOp; POVS_MESSAGE ovsMsg; NETLINK_FAMILY *nlFamilyOps; #ifdef DBG POVS_DEVICE_EXTENSION ovsExt = (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject); ASSERT(deviceObject == gOvsDeviceObject); ASSERT(ovsExt); ASSERT(ovsExt->numberOpenInstance > 0); #else UNREFERENCED_PARAMETER(deviceObject); #endif irpSp = IoGetCurrentIrpStackLocation(irp); ASSERT(irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL); ASSERT(irpSp->FileObject != NULL); fileObject = irpSp->FileObject; instance = (POVS_OPEN_INSTANCE)fileObject->FsContext; code = irpSp->Parameters.DeviceIoControl.IoControlCode; inputBufferLen = irpSp->Parameters.DeviceIoControl.InputBufferLength; outputBufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength; inputBuffer = irp->AssociatedIrp.SystemBuffer; /* Concurrent netlink operations are not supported. */ if (InterlockedCompareExchange((LONG volatile *)&instance->inUse, 1, 0)) { status = STATUS_RESOURCE_IN_USE; goto done; } /* * Validate the input/output buffer arguments depending on the type of the * operation. */ switch (code) { case OVS_IOCTL_TRANSACT: /* Input buffer is mandatory, output buffer is optional. */ if (outputBufferLen != 0) { status = MapIrpOutputBuffer(irp, outputBufferLen, sizeof *ovsMsg, &outputBuffer); if (status != STATUS_SUCCESS) { goto done; } ASSERT(outputBuffer); } if (inputBufferLen < sizeof (*ovsMsg)) { status = STATUS_NDIS_INVALID_LENGTH; goto done; } ovsMsg = inputBuffer; devOp = OVS_TRANSACTION_DEV_OP; break; case OVS_IOCTL_READ: /* Output buffer is mandatory. */ if (outputBufferLen != 0) { status = MapIrpOutputBuffer(irp, outputBufferLen, sizeof *ovsMsg, &outputBuffer); if (status != STATUS_SUCCESS) { goto done; } ASSERT(outputBuffer); } else { status = STATUS_NDIS_INVALID_LENGTH; goto done; } /* * Operate in the mode that read ioctl is similar to ReadFile(). This * might change as the userspace code gets implemented. */ inputBuffer = NULL; inputBufferLen = 0; /* Create an NL message for consumption. */ ovsMsg = &ovsMsgReadOp; devOp = OVS_READ_DEV_OP; /* * For implementing read (ioctl or otherwise), we need to store some * state in the instance to indicate the previous command. The state can * setup 'ovsMsgReadOp' appropriately. * * XXX: Support for that will be added as the userspace code evolves. */ status = STATUS_NOT_IMPLEMENTED; goto done; break; case OVS_IOCTL_WRITE: /* Input buffer is mandatory. */ if (inputBufferLen < sizeof (*ovsMsg)) { status = STATUS_NDIS_INVALID_LENGTH; goto done; } ovsMsg = inputBuffer; devOp = OVS_WRITE_DEV_OP; break; default: status = STATUS_INVALID_DEVICE_REQUEST; goto done; } ASSERT(ovsMsg); switch (ovsMsg->nlMsg.nlmsgType) { case OVS_WIN_NL_CTRL_FAMILY_ID: nlFamilyOps = &nlControlFamilyOps; break; case OVS_WIN_NL_PACKET_FAMILY_ID: case OVS_WIN_NL_DATAPATH_FAMILY_ID: case OVS_WIN_NL_FLOW_FAMILY_ID: case OVS_WIN_NL_VPORT_FAMILY_ID: status = STATUS_NOT_IMPLEMENTED; goto done; default: status = STATUS_INVALID_PARAMETER; goto done; } /* * For read operation, the netlink command has already been validated * previously. */ if (devOp != OVS_READ_DEV_OP) { status = ValidateNetlinkCmd(devOp, ovsMsg, nlFamilyOps); if (status != STATUS_SUCCESS) { goto done; } } status = InvokeNetlinkCmdHandler(irp, fileObject, devOp, ovsMsg, nlFamilyOps, inputBuffer, inputBufferLen, outputBuffer, outputBufferLen, &replyLen); done: KeMemoryBarrier(); instance->inUse = 0; return OvsCompleteIrpRequest(irp, (ULONG_PTR)replyLen, status); }
NTSTATUS OvsDeviceControl(PDEVICE_OBJECT deviceObject, PIRP irp) { PIO_STACK_LOCATION irpSp; NTSTATUS status = STATUS_SUCCESS; PFILE_OBJECT fileObject; PVOID inputBuffer; PVOID outputBuffer; UINT32 inputBufferLen, outputBufferLen, mdlBufferLen; UINT32 code, replyLen = 0; #ifdef DBG POVS_DEVICE_EXTENSION ovsExt = (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject); ASSERT(deviceObject == gOvsDeviceObject); ASSERT(ovsExt); ASSERT(ovsExt->numberOpenInstance > 0); #else UNREFERENCED_PARAMETER(deviceObject); #endif irpSp = IoGetCurrentIrpStackLocation(irp); ASSERT(irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL); ASSERT(irpSp->FileObject != NULL); fileObject = irpSp->FileObject; code = irpSp->Parameters.DeviceIoControl.IoControlCode; inputBufferLen = irpSp->Parameters.DeviceIoControl.InputBufferLength; outputBufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength; /* * In case of an IRP with METHOD_IN_DIRECT or METHOD_OUT_DIRECT, the size * of the MDL is stored in Parameters.DeviceIoControl.OutputBufferLength. */ mdlBufferLen = outputBufferLen; outputBuffer = inputBuffer = irp->AssociatedIrp.SystemBuffer; switch(code) { case OVS_IOCTL_VERSION_GET: status = OvsGetVersionIoctl(outputBuffer, outputBufferLen, &replyLen); break; case OVS_IOCTL_DP_DUMP: status = OvsDpDumpIoctl(outputBuffer, outputBufferLen, &replyLen); break; case OVS_IOCTL_DP_GET: if (irp->MdlAddress == NULL) { status = STATUS_INVALID_PARAMETER; break; } outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); if (outputBuffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; } else { status = OvsDpGetIoctl(inputBuffer, inputBufferLen, outputBuffer, outputBufferLen, &replyLen); } break; case OVS_IOCTL_DP_SET: status = STATUS_NOT_IMPLEMENTED; break; case OVS_IOCTL_VPORT_DUMP: if (irp->MdlAddress == NULL) { status = STATUS_INVALID_PARAMETER; break; } outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); if (outputBuffer) { status = OvsDumpVportIoctl(inputBuffer, inputBufferLen, outputBuffer, outputBufferLen, &replyLen); } else { status = STATUS_INSUFFICIENT_RESOURCES; } break; case OVS_IOCTL_VPORT_GET: if (irp->MdlAddress == NULL) { status = STATUS_INVALID_PARAMETER; break; } outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); if (outputBuffer) { status = OvsGetVportIoctl(inputBuffer, inputBufferLen, outputBuffer, outputBufferLen, &replyLen); } else { status = STATUS_INSUFFICIENT_RESOURCES; } break; case OVS_IOCTL_VPORT_SET: status = STATUS_NOT_IMPLEMENTED; break; case OVS_IOCTL_VPORT_ADD: if (irp->MdlAddress == NULL) { status = STATUS_INVALID_PARAMETER; break; } outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); if (outputBuffer) { status = OvsAddVportIoctl(inputBuffer, inputBufferLen, outputBuffer, outputBufferLen, &replyLen); } else { status = STATUS_INSUFFICIENT_RESOURCES; } break; case OVS_IOCTL_VPORT_DEL: status = OvsDelVportIoctl(inputBuffer, inputBufferLen, &replyLen); break; case OVS_IOCTL_VPORT_EXT_INFO: if (irp->MdlAddress == NULL) { status = STATUS_INVALID_PARAMETER; break; } outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); if (outputBuffer) { status = OvsGetExtInfoIoctl(inputBuffer, inputBufferLen, outputBuffer, outputBufferLen, &replyLen); } else { OVS_LOG_INFO("ExtInfo: fail to get outputBuffer address"); status = STATUS_INSUFFICIENT_RESOURCES; } break; case OVS_IOCTL_FLOW_DUMP: if (irp->MdlAddress == NULL) { status = STATUS_INVALID_PARAMETER; break; } outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); if (outputBuffer) { status = OvsDumpFlowIoctl(inputBuffer, inputBufferLen, outputBuffer, outputBufferLen, &replyLen); } else { status = STATUS_INSUFFICIENT_RESOURCES; } break; case OVS_IOCTL_FLOW_GET: if (irp->MdlAddress == NULL) { status = STATUS_INVALID_PARAMETER; break; } outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); if (outputBuffer) { status = OvsGetFlowIoctl(inputBuffer, inputBufferLen, outputBuffer, outputBufferLen, &replyLen); } else { status = STATUS_INSUFFICIENT_RESOURCES; } break; case OVS_IOCTL_FLOW_PUT: // XXX: This is not really working - mapping the input buffer // XXX: inputBufferLen = mdlBufferLen; // inputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, // NormalPagePriority); status = OvsPutFlowIoctl(inputBuffer, inputBufferLen, outputBuffer, outputBufferLen, &replyLen); break; case OVS_IOCTL_FLOW_FLUSH: status = OvsFlushFlowIoctl(inputBuffer, inputBufferLen); break; case OVS_IOCTL_QOS_QUEUE_DUMP: case OVS_IOCTL_QOS_QUEUE_GET: case OVS_IOCTL_QOS_QUEUE_SET: status = STATUS_NOT_IMPLEMENTED; break; case OVS_IOCTL_DATAPATH_SUBSCRIBE: status = OvsSubscribeDpIoctl(fileObject, inputBuffer, inputBufferLen); break; case OVS_IOCTL_DATAPATH_READ: if (irp->MdlAddress == NULL) { status = STATUS_INVALID_PARAMETER; break; } outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); if (outputBuffer) { status = OvsReadDpIoctl(fileObject, outputBuffer, outputBufferLen, &replyLen); } else { status = STATUS_INSUFFICIENT_RESOURCES; } break; case OVS_IOCTL_DATAPATH_OPERATE: status = STATUS_NOT_IMPLEMENTED; break; case OVS_IOCTL_DATAPATH_EXECUTE: // XXX: need to make the input direct status = OvsExecuteDpIoctl(inputBuffer, inputBufferLen, outputBufferLen); break; case OVS_IOCTL_DATAPATH_PURGE: status = OvsPurgeDpIoctl(fileObject); break; case OVS_IOCTL_DATAPATH_WAIT: status = OvsWaitDpIoctl(irp, fileObject); break; case OVS_IOCTL_EVENT_SUBSCRIBE: status = OvsSubscribeEventIoctl(fileObject, inputBuffer, inputBufferLen); break; case OVS_IOCTL_EVENT_POLL: if (irp->MdlAddress == NULL) { status = STATUS_INVALID_PARAMETER; break; } outputBuffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); if (outputBuffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; } else { status = OvsPollEventIoctl(fileObject, inputBuffer, inputBufferLen, outputBuffer, outputBufferLen, &replyLen); } break; case OVS_IOCTL_EVENT_WAIT: status = OvsWaitEventIoctl(irp, fileObject, inputBuffer, inputBufferLen); break; case OVS_IOCTL_DP_TIMESTAMP_SET: if (inputBufferLen != sizeof (ovsUserTimestampDelta)) { status = STATUS_INFO_LENGTH_MISMATCH; } else { int64 currentUserTS = *(int64 *)inputBuffer; LARGE_INTEGER tickCount; /* So many ticks since system booted. */ KeQueryTickCount(&tickCount); ovsUserTimestampDelta = currentUserTS - (tickCount.QuadPart * ovsTimeIncrementPerTick); status = STATUS_SUCCESS; } break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } if (status == STATUS_PENDING) { return status; } else { /* * When the system-address-space mapping that is returned by * MmGetSystemAddressForMdlSafe is no longer needed, it must be * released. * http://msdn.microsoft.com/en-us/library/windows/hardware/ff554559(v=vs.85).aspx * * We might have to release the MDL here. */ return OvsCompleteIrpRequest(irp, (ULONG_PTR)replyLen, status); } }
_Use_decl_annotations_ NTSTATUS FilterDeviceIoControl( PDEVICE_OBJECT DeviceObject, PIRP Irp ) { PIO_STACK_LOCATION irp_sp; NTSTATUS status = STATUS_SUCCESS; PFILTER_DEVICE_EXTENSION filter_device_extension; PUCHAR input_buffer; PUCHAR output_buffer; ULONG input_buffer_length, output_buffer_length; PLIST_ENTRY link; PUCHAR info; ULONG InfoLength = 0; PLCXL_FILTER filter = NULL; BOOLEAN bFalse = FALSE; UNREFERENCED_PARAMETER(DeviceObject); irp_sp = IoGetCurrentIrpStackLocation(Irp); if (irp_sp->FileObject == NULL) { return(STATUS_UNSUCCESSFUL); } filter_device_extension = (PFILTER_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(DeviceObject); ASSERT(filter_device_extension->Signature == 'FTDR'); Irp->IoStatus.Information = 0; input_buffer = output_buffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; input_buffer_length = output_buffer_length = irp_sp->Parameters.DeviceIoControl.InputBufferLength; switch (irp_sp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_FILTER_RESTART_ALL: break; case IOCTL_FILTER_RESTART_ONE_INSTANCE: filter = filterFindFilterModule (input_buffer, input_buffer_length); if (filter == NULL) { break; } NdisFRestartFilter(filter->filter_handle); break; case IOCTL_FILTER_ENUERATE_ALL_INSTANCES: info = output_buffer; LockLCXLLockList(&g_filter_list); link = GetListofLCXLLockList(&g_filter_list)->Flink; //遍历列表 while (link != GetListofLCXLLockList(&g_filter_list)) { filter = CONTAINING_RECORD(link, LCXL_FILTER, filter_module_link); InfoLength += (filter->module_setting->filter_module_name->Length + sizeof(USHORT)); if (InfoLength <= output_buffer_length) { *(PUSHORT)info = filter->module_setting->filter_module_name->Length; NdisMoveMemory(info + sizeof(USHORT), (PUCHAR)(filter->module_setting->filter_module_name->Buffer), filter->module_setting->filter_module_name->Length); info += (filter->module_setting->filter_module_name->Length + sizeof(USHORT)); } link = link->Flink; } UnlockLCXLLockList(&g_filter_list); if (InfoLength <= output_buffer_length) { status = NDIS_STATUS_SUCCESS; } // // Buffer is small // else { status = STATUS_BUFFER_TOO_SMALL; } break; //添加代码 case IOCTL_LOADER_ALL_APP_MODULE: { PAPP_MODULE_INFO cur_buf; PLCXL_MODULE_SETTING_LIST_ENTRY module; cur_buf = (PAPP_MODULE_INFO)output_buffer; LockLCXLLockList(&g_setting.module_list); module = CONTAINING_RECORD(GetListofLCXLLockList(&g_setting.module_list)->Flink, LCXL_MODULE_SETTING_LIST_ENTRY, list_entry); while (&module->list_entry != GetListofLCXLLockList(&g_setting.module_list)) { //先判断缓冲区是否足够 if (output_buffer_length - (ULONG)((LONG_PTR)cur_buf - (LONG_PTR)output_buffer) < sizeof(APP_MODULE_INFO)) { status = STATUS_BUFFER_TOO_SMALL; break; } cur_buf->app_module_status = module->ref_count == 0 ? AMS_NO_FILTER : AMS_NORMAL; FILTER_ACQUIRE_LOCK(&module->lock, bFalse); cur_buf->real_addr = module->real_addr; cur_buf->virtual_ipv4 = module->virtual_ipv4; cur_buf->virtual_ipv6 = module->virtual_ipv6; LockLCXLLockList(&module->server_list); cur_buf->server_count = GetListCountofLCXLLockList(&module->server_list); UnlockLCXLLockList(&module->server_list); FILTER_RELEASE_LOCK(&module->lock, bFalse); cur_buf->miniport_net_luid = module->miniport_net_luid; cur_buf->filter_module_name_len = (sizeof(cur_buf->filter_module_name) < module->filter_module_name->Length) ? sizeof(cur_buf->filter_module_name) : module->filter_module_name->Length; RtlCopyMemory(cur_buf->filter_module_name, module->filter_module_name->Buffer, cur_buf->filter_module_name_len); cur_buf->miniport_friendly_name_len = (sizeof(cur_buf->miniport_friendly_name) < module->miniport_friendly_name->Length) ? sizeof(cur_buf->miniport_friendly_name) : module->miniport_friendly_name->Length; RtlCopyMemory(cur_buf->miniport_friendly_name, module->miniport_friendly_name->Buffer, cur_buf->miniport_friendly_name_len); cur_buf->miniport_name_len = (sizeof(cur_buf->miniport_name) < module->miniport_name->Length) ? sizeof(cur_buf->miniport_name) : module->miniport_name->Length; RtlCopyMemory(cur_buf->miniport_name, module->miniport_name->Buffer, cur_buf->miniport_name_len); cur_buf++; module = CONTAINING_RECORD(module->list_entry.Flink, LCXL_MODULE_SETTING_LIST_ENTRY, list_entry); } UnlockLCXLLockList(&g_setting.module_list); InfoLength = (ULONG)((ULONG_PTR)cur_buf - (ULONG_PTR)output_buffer); } break; case IOCTL_LOADER_SET_VIRTUAL_IP: if (input_buffer_length == sizeof(APP_IP)) { PAPP_IP ip; PLCXL_FILTER pFilter; ip = (PAPP_IP)input_buffer; LockLCXLLockList(&g_filter_list); pFilter = FindFilter(ip->miniport_net_luid); if (pFilter != NULL) { NdisAcquireSpinLock(&pFilter->module_setting->lock); switch (ip->ip.ip_mode) { //IPv4模式 case IM_IPV4: pFilter->module_setting->virtual_ipv4 = ip->ip.addr.ip_4; break; //IPv6模式 case IM_IPV6: pFilter->module_setting->virtual_ipv6 = ip->ip.addr.ip_6; break; default: status = STATUS_INVALID_PARAMETER; break; } NdisReleaseSpinLock(&pFilter->module_setting->lock); } UnlockLCXLLockList(&g_filter_list); } else { status = STATUS_INFO_LENGTH_MISMATCH; } break; case IOCTL_LOADER_GET_SERVER_LIST: if (input_buffer_length == sizeof(NET_LUID)) { PLCXL_FILTER pFilter; LockLCXLLockList(&g_filter_list); pFilter = FindFilter(*(PNET_LUID)input_buffer); if (pFilter != NULL) { if (pFilter->module_setting != NULL && (pFilter->module_setting->flag & MSF_DELETE_AFTER_RESTART) == 0) { } else { status = STATUS_NOT_FOUND; } } else { status = STATUS_NOT_FOUND; } UnlockLCXLLockList(&g_filter_list); } else { status = STATUS_INFO_LENGTH_MISMATCH; } break; case IOCTL_LOADER_ADD_SERVER: if (sizeof(APP_ADD_SERVER) == input_buffer_length) { PAPP_ADD_SERVER app_add_server; PLCXL_FILTER pFilter; app_add_server = (PAPP_ADD_SERVER)input_buffer; LockLCXLLockList(&g_filter_list); pFilter = FindFilter(app_add_server->miniport_net_luid); if (pFilter != NULL) { LockLCXLLockList(&pFilter->module_setting->server_list); UnlockLCXLLockList(&pFilter->module_setting->server_list); } UnlockLCXLLockList(&g_filter_list); } else { status = STATUS_INFO_LENGTH_MISMATCH; } break; case IOCTL_LOADER_DEL_SERVER: if (sizeof(APP_DEL_SERVER) == input_buffer_length) { PAPP_DEL_SERVER app_del_server = (PAPP_DEL_SERVER)input_buffer; PLCXL_FILTER pFilter; LockLCXLLockList(&g_filter_list); pFilter = FindFilter(app_del_server->miniport_net_luid); UnlockLCXLLockList(&g_filter_list); } else { status = STATUS_INFO_LENGTH_MISMATCH; } break; //!添加代码! default: status = STATUS_INVALID_PARAMETER; break; } Irp->IoStatus.Status = status; Irp->IoStatus.Information = InfoLength; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; }
NDIS_STATUS NDISFilterDriverRegisterDevice(OUT PFILTER_DEVICE_EXTENSION *Extension) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; UNICODE_STRING DeviceName; UNICODE_STRING DeviceLinkUnicodeString; PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1]; NDIS_DEVICE_OBJECT_ATTRIBUTES DeviceAttribute; PFILTER_DEVICE_EXTENSION FilterDeviceExtension; PDRIVER_OBJECT DriverObject; DEBUGP(DL_TRACE, "==>NDISFilterDriverRegisterDevice\n"); NdisZeroMemory(DispatchTable, (IRP_MJ_MAXIMUM_FUNCTION+1) * sizeof(PDRIVER_DISPATCH)); DispatchTable[IRP_MJ_CREATE] = NDISFilterDriverDispatch; DispatchTable[IRP_MJ_CLEANUP] = NDISFilterDriverDispatch; DispatchTable[IRP_MJ_CLOSE] = NDISFilterDriverDispatch; DispatchTable[IRP_MJ_DEVICE_CONTROL] = NDISFilterDriverDeviceIoControl; NdisInitUnicodeString(&DeviceName, NTDEVICE_STRING); NdisInitUnicodeString(&DeviceLinkUnicodeString, LINKNAME_STRING); // // Create a device object and register our dispatch handlers // NdisZeroMemory(&DeviceAttribute, sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES)); DeviceAttribute.Header.Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES; DeviceAttribute.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1; DeviceAttribute.Header.Size = sizeof(NDIS_DEVICE_OBJECT_ATTRIBUTES); DeviceAttribute.DeviceName = &DeviceName; DeviceAttribute.SymbolicName = &DeviceLinkUnicodeString; DeviceAttribute.MajorFunctions = &DispatchTable[0]; DeviceAttribute.ExtensionSize = sizeof(FILTER_DEVICE_EXTENSION); Status = NdisRegisterDeviceEx( FilterDriverHandle, &DeviceAttribute, &DeviceObject, &NdisFilterDeviceHandle ); if (Status == NDIS_STATUS_SUCCESS) { *Extension = FilterDeviceExtension = NdisGetDeviceReservedExtension(DeviceObject); FilterDeviceExtension->Signature = 'FTDR'; FilterDeviceExtension->Handle = FilterDriverHandle; KeInitializeSpinLock(&FilterDeviceExtension->QLock); PRULES_LISTS FilterRules = ExAllocatePool(PagedPool, sizeof(RULES_LISTS)); FilterRules->IsActive = FALSE; FilterRules->FirstRuleIPv4 = NULL; FilterRules->FirstRuleIPv6 = NULL; FilterDeviceExtension->FilterRules = FilterRules; // // Workaround NDIS bug // DriverObject = (PDRIVER_OBJECT)FilterDriverObject; } DEBUGP(DL_TRACE, "<==NDISFilterDriverRegisterDevice: %x\n", Status); return (Status); }
_Use_decl_annotations_ NTSTATUS NDISFilterDriverDeviceIoControl( PDEVICE_OBJECT DeviceObject, PIRP Irp ) { DbgPrint("NDISFilterDriverDeviceIoControl\n"); PIO_STACK_LOCATION IrpSp; NTSTATUS Status = STATUS_SUCCESS; PFILTER_DEVICE_EXTENSION FilterDeviceExtension; PUCHAR InputBuffer; PUCHAR OutputBuffer; ULONG InputBufferLength, OutputBufferLength; PLIST_ENTRY Link; PUCHAR pInfo; ULONG InfoLength = 0; PMS_FILTER pFilter = NULL; BOOLEAN bFalse = FALSE; UNREFERENCED_PARAMETER(DeviceObject); KIRQL OldIrql; IrpSp = IoGetCurrentIrpStackLocation(Irp); if (IrpSp->FileObject == NULL) { return(STATUS_UNSUCCESSFUL); } FilterDeviceExtension = (PFILTER_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(DeviceObject); ASSERT(FilterDeviceExtension->Signature == 'FTDR'); Irp->IoStatus.Information = 0; KeAcquireSpinLock(&FilterDeviceExtension->QLock, &OldIrql); switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_ADD_IPV4_RULE: DbgPrint("IOCTL_ADD_IPV4_RULE BEGIN\n"); InputBuffer = Irp->UserBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (InputBufferLength != sizeof(RULE_IPV4)) { Status = NDIS_STATUS_FAILURE; break; } PRULE_IPV4 pRuleIPv4 = ExAllocatePool(NonPagedPool, sizeof(RULE_IPV4)); RtlCopyMemory(pRuleIPv4, InputBuffer, InputBufferLength); AddIPv4Rule(FilterDeviceExtension, pRuleIPv4); DbgPrint("IOCTL_ADD_IPV4_RULE END\n"); break; case IOCTL_DEL_IPV4_RULE: DbgPrint("IOCTL_DEL_IPV4_RULE BEGIN\n"); InputBuffer = Irp->UserBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (InputBufferLength != sizeof(ULONG)) { Status = NDIS_STATUS_FAILURE; break; } ULONG IdIPv4 = *((PULONG)(InputBuffer)); DelIPv4Rule(FilterDeviceExtension, IdIPv4); DbgPrint("IOCTL_DEL_IPV4_RULE END\n"); break; case IOCTL_ADD_IPV6_RULE: DbgPrint("IOCTL_ADD_IPV6_RULE BEGIN\n"); InputBuffer = Irp->UserBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (InputBufferLength != sizeof(RULE_IPV6)) { Status = NDIS_STATUS_FAILURE; break; } PRULE_IPV6 pRuleIPv6 = ExAllocatePool(NonPagedPool, sizeof(RULE_IPV6)); RtlCopyMemory(pRuleIPv6, InputBuffer, InputBufferLength); AddIPv6Rule(FilterDeviceExtension, pRuleIPv6); DbgPrint("IOCTL_ADD_IPV6_RULE END\n"); break; case IOCTL_DEL_IPV6_RULE: DbgPrint("IOCTL_DEL_IPV6_RULE BEGIN\n"); InputBuffer = Irp->UserBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (InputBufferLength != sizeof(ULONG)) { Status = NDIS_STATUS_FAILURE; break; } ULONG IdIPv6 = *((PULONG)(InputBuffer)); DelIPv6Rule(FilterDeviceExtension, IdIPv6); DbgPrint("IOCTL_END_IPV6_RULE END\n"); break; case IOCTL_ACTIVATE_FILTER: DbgPrint("IOCTL_ACTIVATE_FILTER BEGIN\n"); InputBuffer = Irp->UserBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (InputBufferLength != 0) { Status = NDIS_STATUS_FAILURE; break; } ActivateRules(FilterDeviceExtension); DbgPrint("IOCTL_ACTIVATE_FILTER END\n"); break; case IOCTL_DEACTIVATE_FILTER: DbgPrint("IOCTL_DEACTIVATE_FILTER BEGIN\n"); InputBuffer = Irp->UserBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (InputBufferLength != 0) { Status = NDIS_STATUS_FAILURE; break; } DeactivateRules(FilterDeviceExtension); DbgPrint("IOCTL_DEACTIVATE_FILTER END\n"); break; case IOCTL_FILTER_RESTART_ALL: break; case IOCTL_FILTER_RESTART_ONE_INSTANCE: InputBuffer = OutputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; pFilter = filterFindFilterModule (InputBuffer, InputBufferLength); if (pFilter == NULL) { break; } NdisFRestartFilter(pFilter->FilterHandle); break; case IOCTL_FILTER_ENUERATE_ALL_INSTANCES: InputBuffer = OutputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; pInfo = OutputBuffer; FILTER_ACQUIRE_LOCK(&FilterListLock, bFalse); Link = FilterModuleList.Flink; while (Link != &FilterModuleList) { pFilter = CONTAINING_RECORD(Link, MS_FILTER, FilterModuleLink); InfoLength += (pFilter->FilterModuleName.Length + sizeof(USHORT)); if (InfoLength <= OutputBufferLength) { *(PUSHORT)pInfo = pFilter->FilterModuleName.Length; NdisMoveMemory(pInfo + sizeof(USHORT), (PUCHAR)(pFilter->FilterModuleName.Buffer), pFilter->FilterModuleName.Length); pInfo += (pFilter->FilterModuleName.Length + sizeof(USHORT)); } Link = Link->Flink; } FILTER_RELEASE_LOCK(&FilterListLock, bFalse); if (InfoLength <= OutputBufferLength) { Status = NDIS_STATUS_SUCCESS; } // // Buffer is small // else { Status = STATUS_BUFFER_TOO_SMALL; } break; default: break; } KeReleaseSpinLock(&FilterDeviceExtension->QLock, OldIrql); Irp->IoStatus.Status = Status; Irp->IoStatus.Information = InfoLength; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }