Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

453 lines
12 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. ntos\tdi\isn\flt\driver.c
  5. Abstract:
  6. IPX Filter driver dispatch routines
  7. Author:
  8. Vadim Eydelman
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. PFILE_OBJECT RouterFile;
  13. NTSTATUS
  14. IpxFltDispatch(
  15. IN PDEVICE_OBJECT DeviceObject,
  16. IN PIRP Irp
  17. );
  18. VOID
  19. IpxFltUnload(
  20. IN PDRIVER_OBJECT DriverObject
  21. );
  22. VOID
  23. IpxFltCancel (
  24. IN PDEVICE_OBJECT DeviceObject,
  25. IN PIRP irp
  26. );
  27. /*++
  28. D r i v e r E n t r y
  29. Routine Description:
  30. Installable driver initialization entry point.
  31. This entry point is called directly by the I/O system.
  32. Arguments:
  33. DriverObject - pointer to the driver object
  34. RegistryPath - pointer to a unicode string representing the path
  35. to driver-specific key in the registry
  36. Return Value:
  37. STATUS_SUCCESS if successful,
  38. STATUS_UNSUCCESSFUL otherwise
  39. --*/
  40. NTSTATUS
  41. DriverEntry (
  42. IN PDRIVER_OBJECT DriverObject,
  43. IN PUNICODE_STRING RegistryPath
  44. ) {
  45. PDEVICE_OBJECT deviceObject = NULL;
  46. NTSTATUS status;
  47. UNICODE_STRING deviceNameUnicodeString;
  48. IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: Driver Entry.\n"));
  49. RtlInitUnicodeString (&deviceNameUnicodeString,
  50. IPXFLT_NAME);
  51. status = IoCreateDevice (DriverObject,
  52. 0,
  53. &deviceNameUnicodeString,
  54. FILE_DEVICE_IPXFLT,
  55. 0,
  56. FALSE, // Non-Exclusive
  57. &deviceObject
  58. );
  59. if (NT_SUCCESS(status)) {
  60. //
  61. // Create dispatch points for device control, create, close.
  62. //
  63. DriverObject->MajorFunction[IRP_MJ_CREATE]
  64. = DriverObject->MajorFunction[IRP_MJ_CLEANUP]
  65. = DriverObject->MajorFunction[IRP_MJ_CLOSE]
  66. = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]
  67. = IpxFltDispatch;
  68. DriverObject->DriverUnload = IpxFltUnload;
  69. status = BindToFwdDriver (KernelMode);
  70. if (NT_SUCCESS (status)) {
  71. RouterFile = NULL;
  72. return STATUS_SUCCESS;
  73. }
  74. else {
  75. IoDeleteDevice (DriverObject->DeviceObject);
  76. }
  77. }
  78. else
  79. IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS,
  80. ("IpxFlt: Could not create device object.\n"));
  81. return status;
  82. }
  83. /*++
  84. Routine Description:
  85. Process the IRPs sent to this device.
  86. Arguments:
  87. DeviceObject - pointer to a device object
  88. Irp - pointer to an I/O Request Packet
  89. Return Value:
  90. --*/
  91. NTSTATUS
  92. IpxFltDispatch(
  93. IN PDEVICE_OBJECT DeviceObject,
  94. IN PIRP Irp
  95. ) {
  96. PIO_STACK_LOCATION IrpStack;
  97. PVOID inBuffer, outBuffer;
  98. ULONG inpBufLength;
  99. ULONG outBufLength;
  100. NTSTATUS status;
  101. KIRQL cancelIRQL;
  102. ULONG ulBytes;
  103. ulBytes = 0;
  104. Irp->IoStatus.Information = 0;
  105. status = STATUS_SUCCESS;
  106. //
  107. // Get a pointer to the current location in the Irp. This is where
  108. // the function codes and parameters are located.
  109. //
  110. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  111. switch (IrpStack->MajorFunction) {
  112. case IRP_MJ_CREATE:
  113. IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IRP_MJ_CREATE.\n"));
  114. break;
  115. case IRP_MJ_CLOSE:
  116. IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IRP_MJ_CLOSE.\n"));
  117. if (IrpStack->FileObject == RouterFile) {
  118. DeleteTables ();
  119. RouterFile = NULL;
  120. }
  121. break;
  122. case IRP_MJ_CLEANUP:
  123. IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IRP_MJ_CLEANUP.\n"));
  124. if (IrpStack->FileObject==RouterFile) {
  125. IoAcquireCancelSpinLock (&cancelIRQL);
  126. while (!IsListEmpty (&LogIrpQueue)) {
  127. PIRP irp = CONTAINING_RECORD (LogIrpQueue.Blink,
  128. IRP, Tail.Overlay.ListEntry);
  129. irp->Cancel = TRUE;
  130. irp->CancelIrql = cancelIRQL;
  131. irp->CancelRoutine = NULL;
  132. IpxFltCancel(DeviceObject, irp);
  133. IoAcquireCancelSpinLock (&cancelIRQL);
  134. }
  135. IoReleaseCancelSpinLock(cancelIRQL);
  136. }
  137. break;
  138. case IRP_MJ_DEVICE_CONTROL:
  139. //
  140. // Get the pointer to the input/output buffer and it's length
  141. //
  142. status = STATUS_INVALID_PARAMETER;
  143. inpBufLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  144. outBufLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  145. switch (IrpStack->Parameters.DeviceIoControl.IoControlCode&3) {
  146. case METHOD_BUFFERED:
  147. inBuffer = outBuffer = Irp->AssociatedIrp.SystemBuffer;
  148. break;
  149. case METHOD_IN_DIRECT:
  150. case METHOD_OUT_DIRECT:
  151. inBuffer = Irp->AssociatedIrp.SystemBuffer;
  152. if (outBufLength>0) {
  153. outBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, NormalPagePriority);
  154. if (outBuffer == NULL)
  155. {
  156. IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS, ("IpxFlt: System out of PTE's.\n"));
  157. goto DispatchExit;
  158. }
  159. }
  160. else {
  161. outBuffer = NULL;
  162. }
  163. break;
  164. default:
  165. IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS, ("IpxFlt: Unsupported io method.\n"));
  166. goto DispatchExit;
  167. }
  168. if (IrpStack->FileObject==RouterFile) {
  169. switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) {
  170. case IOCTL_FLT_IF_SET_IN_FILTERS:
  171. IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_IF_SET_IN_FILTERS.\n"));
  172. if ((inpBufLength==sizeof (FLT_IF_SET_PARAMS))
  173. && (((PFLT_IF_SET_PARAMS)inBuffer)->FilterSize
  174. ==sizeof (IPX_TRAFFIC_FILTER_INFO)))
  175. status = SetInFilters (
  176. ((PFLT_IF_SET_PARAMS)inBuffer)->InterfaceIndex,
  177. ((PFLT_IF_SET_PARAMS)inBuffer)->FilterAction,
  178. outBufLength,
  179. (PIPX_TRAFFIC_FILTER_INFO)outBuffer);
  180. break;
  181. case IOCTL_FLT_IF_SET_OUT_FILTERS:
  182. IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_IF_SET_OUT_FILTERS.\n"));
  183. if ((inpBufLength==sizeof (FLT_IF_SET_PARAMS))
  184. && (((PFLT_IF_SET_PARAMS)inBuffer)->FilterSize
  185. ==sizeof (IPX_TRAFFIC_FILTER_INFO)))
  186. status = SetOutFilters (
  187. ((PFLT_IF_SET_PARAMS)inBuffer)->InterfaceIndex,
  188. ((PFLT_IF_SET_PARAMS)inBuffer)->FilterAction,
  189. outBufLength,
  190. (PIPX_TRAFFIC_FILTER_INFO)outBuffer);
  191. break;
  192. case IOCTL_FLT_IF_RESET_IN_FILTERS:
  193. IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_IF_RESET_IN_FILTERS.\n"));
  194. if ((inpBufLength==sizeof (ULONG))
  195. && (outBufLength==0))
  196. status = SetInFilters (
  197. *((PULONG)inBuffer),
  198. IPX_TRAFFIC_FILTER_ACTION_DENY,
  199. 0, NULL);
  200. break;
  201. case IOCTL_FLT_IF_RESET_OUT_FILTERS:
  202. IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_IF_RESET_OUT_FILTERS.\n"));
  203. if ((inpBufLength==sizeof (ULONG))
  204. && (outBufLength==0))
  205. status = SetOutFilters (
  206. *((PULONG)inBuffer),
  207. IPX_TRAFFIC_FILTER_ACTION_DENY,
  208. 0, NULL);
  209. break;
  210. case IOCTL_FLT_IF_GET_IN_FILTERS:
  211. IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_IF_GET_IN_FILTERS.\n"));
  212. if ((inpBufLength==sizeof (ULONG))
  213. && (outBufLength>=sizeof (FLT_IF_GET_PARAMS))) {
  214. Irp->IoStatus.Information
  215. = outBufLength-sizeof (FLT_IF_GET_PARAMS);
  216. ulBytes = (ULONG)Irp->IoStatus.Information;
  217. status = GetInFilters (
  218. *((PULONG)inBuffer),
  219. &((PFLT_IF_GET_PARAMS)outBuffer)->FilterAction,
  220. &((PFLT_IF_GET_PARAMS)outBuffer)->TotalSize,
  221. (PIPX_TRAFFIC_FILTER_INFO)
  222. ((PUCHAR)outBuffer+sizeof (FLT_IF_GET_PARAMS)),
  223. &ulBytes);
  224. Irp->IoStatus.Information = ulBytes;
  225. if (NT_SUCCESS (status)) {
  226. Irp->IoStatus.Information += sizeof (FLT_IF_GET_PARAMS);
  227. ((PFLT_IF_GET_PARAMS)outBuffer)->FilterSize
  228. = sizeof (IPX_TRAFFIC_FILTER_INFO);
  229. }
  230. else
  231. Irp->IoStatus.Information = 0;
  232. }
  233. break;
  234. case IOCTL_FLT_IF_GET_OUT_FILTERS:
  235. IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_IF_GET_OUT_FILTERS.\n"));
  236. if ((inpBufLength==sizeof (ULONG))
  237. && (outBufLength>=sizeof (FLT_IF_GET_PARAMS))) {
  238. Irp->IoStatus.Information
  239. = outBufLength-sizeof (FLT_IF_GET_PARAMS);
  240. ulBytes = (ULONG)Irp->IoStatus.Information;
  241. status = GetOutFilters (
  242. *((PULONG)inBuffer),
  243. &((PFLT_IF_GET_PARAMS)outBuffer)->FilterAction,
  244. &((PFLT_IF_GET_PARAMS)outBuffer)->TotalSize,
  245. (PIPX_TRAFFIC_FILTER_INFO)
  246. ((PUCHAR)outBuffer+sizeof (FLT_IF_GET_PARAMS)),
  247. &ulBytes);
  248. Irp->IoStatus.Information = ulBytes;
  249. if (NT_SUCCESS (status)) {
  250. Irp->IoStatus.Information += sizeof (FLT_IF_GET_PARAMS);
  251. ((PFLT_IF_GET_PARAMS)outBuffer)->FilterSize
  252. = sizeof (IPX_TRAFFIC_FILTER_INFO);
  253. }
  254. else
  255. Irp->IoStatus.Information = 0;
  256. }
  257. break;
  258. case IOCTL_FLT_GET_LOGGED_PACKETS:
  259. IpxFltDbgPrint (DBG_PKTLOGS, ("IpxFlt: IOCTL_FLT_GET_LOGGED_PACKETS.\n"));
  260. Irp->IoStatus.Status = status = STATUS_PENDING;
  261. IoMarkIrpPending (Irp);
  262. IoAcquireCancelSpinLock (&cancelIRQL);
  263. InsertTailList (&LogIrpQueue,
  264. &Irp->Tail.Overlay.ListEntry);
  265. IoSetCancelRoutine (Irp, IpxFltCancel);
  266. if (LogIrpQueue.Flink!=&Irp->Tail.Overlay.ListEntry) {
  267. PIRP irp = CONTAINING_RECORD (
  268. LogIrpQueue.Flink,
  269. IRP,
  270. Tail.Overlay.ListEntry);
  271. if (irp->IoStatus.Information>0) {
  272. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  273. IoSetCancelRoutine (irp, NULL);
  274. irp->IoStatus.Status = STATUS_SUCCESS;
  275. IoReleaseCancelSpinLock (cancelIRQL);
  276. IpxFltDbgPrint (DBG_PKTLOGS,
  277. ("IpxFlt: completing logging request"
  278. " with %d bytes of data.\n",
  279. irp->IoStatus.Information));
  280. IoCompleteRequest (irp, IO_NO_INCREMENT);
  281. break;
  282. }
  283. }
  284. IoReleaseCancelSpinLock (cancelIRQL);
  285. break;
  286. default:
  287. IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS,
  288. ("IpxFlt: Unsupported IOCTL %lx.\n",
  289. IrpStack->Parameters.DeviceIoControl.IoControlCode));
  290. status = STATUS_INVALID_DEVICE_REQUEST;
  291. break;
  292. }
  293. }
  294. else if (RouterFile==NULL) {
  295. if (IrpStack->Parameters.DeviceIoControl.IoControlCode
  296. ==IOCTL_FLT_START) {
  297. IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_START.\n"));
  298. status = InitializeTables ();
  299. if (NT_SUCCESS (status)) {
  300. RouterFile = IrpStack->FileObject;
  301. status = STATUS_SUCCESS;
  302. }
  303. }
  304. else {
  305. IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS,
  306. ("IpxFlt: Unsupported IOCTL %lx (driver is not started yet)).\n",
  307. IrpStack->Parameters.DeviceIoControl.IoControlCode));
  308. status = STATUS_INVALID_DEVICE_REQUEST;
  309. }
  310. }
  311. else {
  312. IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS,
  313. ("IpxFlt: Unsupported IOCTL %lx from non-router client.\n",
  314. IrpStack->Parameters.DeviceIoControl.IoControlCode));
  315. status = STATUS_INVALID_DEVICE_REQUEST;
  316. }
  317. break;
  318. default:
  319. IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS,
  320. ("IpxFlt: Unsupported function %lx.\n",
  321. IrpStack->MajorFunction));
  322. status = STATUS_INVALID_DEVICE_REQUEST;
  323. break;
  324. }
  325. DispatchExit:
  326. if (status!=STATUS_PENDING) {
  327. Irp->IoStatus.Status = status;
  328. if (NT_SUCCESS (status))
  329. ;
  330. else
  331. IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS,
  332. ("IpxFlt: Failed call with status %lx.\n",
  333. status));
  334. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  335. }
  336. return status;
  337. }
  338. /*++
  339. Routine Description:
  340. Cleans up on driver unload
  341. Arguments:
  342. DriverObject - pointer to a driver object
  343. Return Value:
  344. --*/
  345. VOID
  346. IpxFltUnload(
  347. IN PDRIVER_OBJECT DriverObject
  348. ) {
  349. IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: Unloading\n"));
  350. if (RouterFile!=NULL) {
  351. DeleteTables ();
  352. RouterFile = NULL;
  353. }
  354. UnbindFromFwdDriver (KernelMode);
  355. IoDeleteDevice (DriverObject->DeviceObject);
  356. }
  357. /*++
  358. I p x F l t C a n c e l
  359. Routine Description:
  360. Cancels specified IRP
  361. Arguments:
  362. DeviceObject - forwarder device object
  363. irp - irp to cancel
  364. Return Value:
  365. None
  366. --*/
  367. VOID
  368. IpxFltCancel (
  369. IN PDEVICE_OBJECT DeviceObject,
  370. IN PIRP irp
  371. ) {
  372. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  373. IoReleaseCancelSpinLock (irp->CancelIrql);
  374. irp->IoStatus.Status = STATUS_CANCELLED;
  375. IpxFltDbgPrint(DBG_IOCTLS, ("IpxFlt: completing cancelled irp.\n"));
  376. IoCompleteRequest(irp, IO_NO_INCREMENT);
  377. }