Source code of Windows XP (NT5)
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.

2836 lines
74 KiB

  1. /*++
  2. Copyright (c) 1991-2000 Microsoft Corporation
  3. Module Name:
  4. ntirp.c
  5. Abstract:
  6. NT specific routines for dispatching and handling IRPs.
  7. Author:
  8. Mike Massa (mikemas) Aug 13, 1993
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. mikemas 08-13-93 created
  13. Notes:
  14. --*/
  15. #include "precomp.h"
  16. #include "iproute.h"
  17. #include "icmp.h"
  18. #include "arpdef.h"
  19. #include "info.h"
  20. #include "ipstatus.h"
  21. #include "tcpipbuf.h"
  22. //
  23. // Local structures.
  24. //
  25. typedef struct pending_irp {
  26. LIST_ENTRY Linkage;
  27. PIRP Irp;
  28. PFILE_OBJECT FileObject;
  29. PVOID Context;
  30. } PENDING_IRP, *PPENDING_IRP;
  31. DEFINE_LOCK_STRUCTURE(AddChangeLock)
  32. DEFINE_LOCK_STRUCTURE(ClientNotifyLock)
  33. //
  34. // Global variables
  35. //
  36. LIST_ENTRY PendingEchoList;
  37. LIST_ENTRY PendingIPSetNTEAddrList;
  38. PIRP PendingIPGetIPEventRequest;
  39. LIST_ENTRY PendingEnableRouterList;
  40. LIST_ENTRY PendingMediaSenseRequestList;
  41. LIST_ENTRY PendingArpSendList;
  42. IP_STATUS ARPResolve(IPAddr DestAddress, IPAddr SourceAddress,
  43. ARPControlBlock * ControlBlock, ArpRtn Callback);
  44. VOID CompleteArpResolveRequest(void *ControlBlock, IP_STATUS ipstatus);
  45. extern Interface *IFList;
  46. //
  47. // External prototypes
  48. //
  49. IP_STATUS ICMPEchoRequest(void *InputBuffer, uint InputBufferLength,
  50. EchoControl * ControlBlock, EchoRtn Callback);
  51. ulong ICMPEchoComplete(EchoControl * ControlBlock, IP_STATUS Status,
  52. void *Data, uint DataSize, IPOptInfo *OptionInfo);
  53. #if defined(_WIN64)
  54. ulong ICMPEchoComplete32(EchoControl * ControlBlock, IP_STATUS Status,
  55. void *Data, uint DataSize, IPOptInfo *OptionInfo);
  56. #endif // _WIN64
  57. IP_STATUS IPSetNTEAddrEx(uint Index, IPAddr Addr, IPMask Mask,
  58. SetAddrControl * ControlBlock, SetAddrRtn Callback, USHORT Type);
  59. IP_STATUS IPAddDynamicNTE(ulong InterfaceContext, PUNICODE_STRING InterfaceName,
  60. int InterfaceNameLen, IPAddr NewAddr, IPMask NewMask,
  61. ushort * NTEContext, ulong * NTEInstance);
  62. IP_STATUS IPDeleteDynamicNTE(ushort NTEContext);
  63. uint IPGetNTEInfo(ushort NTEContext, ulong * NTEInstance, IPAddr * Address,
  64. IPMask * SubnetMask, ushort * NTEFlags);
  65. uint SetDHCPNTE(uint Context);
  66. NTSTATUS SetIFPromiscuous(ULONG Index, UCHAR Type, UCHAR Add);
  67. extern void NotifyAddrChange(IPAddr Addr, IPMask Mask, void *Context,
  68. ushort IPContext, PVOID * Handle,
  69. PNDIS_STRING ConfigName, PNDIS_STRING IFName,
  70. uint Added);
  71. extern NTSTATUS IPStatusToNTStatus(IP_STATUS ipStatus);
  72. extern int IPEnableRouterRefCount;
  73. extern int IPEnableRouterWithRefCount(LOGICAL Enable);
  74. extern NTSTATUS IPGetCapability(ULONG Context, PULONG buf, uint cap);
  75. extern int IPEnableMediaSense(LOGICAL Enable, KIRQL *irql);
  76. extern uint DisableMediaSense;
  77. NTSTATUS FlushArpTable(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  78. //
  79. // Local prototypes
  80. //
  81. NTSTATUS IPDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  82. NTSTATUS IPDispatchDeviceControl(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  83. NTSTATUS IPDispatchInternalDeviceControl(IN PIRP Irp,
  84. IN PIO_STACK_LOCATION IrpSp);
  85. NTSTATUS IPCreate(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  86. NTSTATUS IPCleanup(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  87. NTSTATUS IPClose(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  88. NTSTATUS DispatchEchoRequest(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  89. NTSTATUS DispatchARPRequest(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  90. NTSTATUS RtChangeNotifyRequest(PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  91. NTSTATUS RtChangeNotifyRequestEx(PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  92. NTSTATUS AddrChangeNotifyRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp);
  93. #if MILLEN
  94. NTSTATUS IfChangeNotifyRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp);
  95. #endif // MILLEN
  96. NTSTATUS IPEnableRouterRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp);
  97. NTSTATUS IPUnenableRouterRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp,
  98. PVOID ApcContext);
  99. VOID CancelIPEnableRouterRequest(IN PDEVICE_OBJECT Device, IN PIRP Irp);
  100. NTSTATUS IPGetBestInterfaceIndex(IN IPAddr Address, OUT PULONG pIndex,
  101. OUT PULONG pMetric);
  102. extern NTSTATUS GetBestInterfaceId(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  103. extern NTSTATUS IPGetBestInterface(IN IPAddr Address, OUT PVOID * ppIF);
  104. extern NTSTATUS GetInterfaceInfo(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  105. extern NTSTATUS GetIgmpList(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  106. extern NTSTATUS DispatchIPSetBlockofRoutes(IN PIRP Irp,
  107. IN PIO_STACK_LOCATION IrpSp);
  108. extern NTSTATUS DispatchIPSetRouteWithRef(IN PIRP Irp,
  109. IN PIO_STACK_LOCATION IrpSp);
  110. extern NTSTATUS DispatchIPSetMultihopRoute(IN PIRP Irp,
  111. IN PIO_STACK_LOCATION IrpSp);
  112. void CompleteEchoRequest(void *Context, IP_STATUS Status, void *Data,
  113. uint DataSize, IPOptInfo *OptionInfo);
  114. NTSTATUS DispatchIPSetNTEAddrRequest(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  115. void CompleteIPSetNTEAddrRequest(void *Context, IP_STATUS Status);
  116. NTSTATUS IPGetIfIndex(IN PIRP pIrp, IN PIO_STACK_LOCATION pIrpSp);
  117. NTSTATUS IPGetIfName(IN PIRP pIrp, IN PIO_STACK_LOCATION pIrpSp);
  118. NTSTATUS DispatchIPGetIPEvent(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  119. NTSTATUS IPGetMcastCounters(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  120. NTSTATUS
  121. IPEnableMediaSenseRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp);
  122. NTSTATUS
  123. IPDisableMediaSenseRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp );
  124. VOID
  125. CancelIPEnableMediaSenseRequest(IN PDEVICE_OBJECT Device, IN PIRP Irp);
  126. //
  127. // All of this code is pageable.
  128. //
  129. #if !MILLEN
  130. #ifdef ALLOC_PRAGMA
  131. #pragma alloc_text(PAGE, IPDispatch)
  132. #pragma alloc_text(PAGE, IPDispatchInternalDeviceControl)
  133. #pragma alloc_text(PAGE, IPCreate)
  134. #pragma alloc_text(PAGE, IPClose)
  135. #pragma alloc_text(PAGE, DispatchEchoRequest)
  136. #pragma alloc_text(PAGE, DispatchARPRequest)
  137. #endif // ALLOC_PRAGMA
  138. #endif // !MILLEN
  139. //
  140. // Dispatch function definitions
  141. //
  142. NTSTATUS
  143. IPDispatch(
  144. IN PDEVICE_OBJECT DeviceObject,
  145. IN PIRP Irp
  146. )
  147. /*++
  148. Routine Description:
  149. This is the dispatch routine for IP.
  150. Arguments:
  151. DeviceObject - Pointer to device object for target device
  152. Irp - Pointer to I/O request packet
  153. Return Value:
  154. NTSTATUS -- Indicates whether the request was successfully queued.
  155. --*/
  156. {
  157. PIO_STACK_LOCATION irpSp;
  158. NTSTATUS status;
  159. UNREFERENCED_PARAMETER(DeviceObject);
  160. PAGED_CODE();
  161. irpSp = IoGetCurrentIrpStackLocation(Irp);
  162. DEBUGMSG(DBG_TRACE && DBG_IP && DBG_VERBOSE,
  163. (DTEXT("+IPDispatch(%x, %x) MajorFunction %x\n"),
  164. DeviceObject, Irp, irpSp->MajorFunction));
  165. switch (irpSp->MajorFunction) {
  166. case IRP_MJ_DEVICE_CONTROL:
  167. return IPDispatchDeviceControl(Irp, irpSp);
  168. case IRP_MJ_INTERNAL_DEVICE_CONTROL:
  169. return IPDispatchDeviceControl(Irp, irpSp);
  170. case IRP_MJ_CREATE:
  171. status = IPCreate(Irp, irpSp);
  172. break;
  173. case IRP_MJ_CLEANUP:
  174. status = IPCleanup(Irp, irpSp);
  175. break;
  176. case IRP_MJ_CLOSE:
  177. status = IPClose(Irp, irpSp);
  178. break;
  179. default:
  180. DEBUGMSG(DBG_ERROR,
  181. (DTEXT("IPDispatch: Invalid major function. IRP %x MajorFunc %x\n"),
  182. Irp, irpSp->MajorFunction));
  183. status = STATUS_NOT_IMPLEMENTED;
  184. break;
  185. }
  186. Irp->IoStatus.Status = status;
  187. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  188. DEBUGMSG(DBG_TRACE && DBG_IP && DBG_VERBOSE, (DTEXT("-IPDispatch [%x]\n"), status));
  189. return (status);
  190. }
  191. NTSTATUS
  192. IPDispatchDeviceControl(
  193. IN PIRP Irp,
  194. IN PIO_STACK_LOCATION IrpSp
  195. )
  196. /*++
  197. Routine Description:
  198. Arguments:
  199. Irp - Pointer to I/O request packet
  200. IrpSp - Pointer to the current stack location in the Irp.
  201. Return Value:
  202. NTSTATUS -- Indicates whether the request was successfully queued.
  203. --*/
  204. {
  205. NTSTATUS status;
  206. ULONG code;
  207. Irp->IoStatus.Information = 0;
  208. code = IrpSp->Parameters.DeviceIoControl.IoControlCode;
  209. DEBUGMSG(DBG_TRACE && DBG_IP,
  210. (DTEXT("+IPDispatchDeviceControl(%x, %x) IoControlCode %x\n"),
  211. Irp, IrpSp, code));
  212. switch (code) {
  213. case IOCTL_ICMP_ECHO_REQUEST:
  214. return (DispatchEchoRequest(Irp, IrpSp));
  215. case IOCTL_ARP_SEND_REQUEST:
  216. return (DispatchARPRequest(Irp, IrpSp));
  217. case IOCTL_IP_INTERFACE_INFO:
  218. return (GetInterfaceInfo(Irp, IrpSp));
  219. case IOCTL_IP_GET_IGMPLIST:
  220. return (GetIgmpList(Irp, IrpSp));
  221. case IOCTL_IP_GET_BEST_INTERFACE:
  222. return (GetBestInterfaceId(Irp, IrpSp));
  223. case IOCTL_IP_SET_ADDRESS:
  224. case IOCTL_IP_SET_ADDRESS_DUP:
  225. case IOCTL_IP_SET_ADDRESS_EX:
  226. return (DispatchIPSetNTEAddrRequest(Irp, IrpSp));
  227. case IOCTL_IP_SET_BLOCKOFROUTES:
  228. return (DispatchIPSetBlockofRoutes(Irp, IrpSp));
  229. case IOCTL_IP_SET_ROUTEWITHREF:
  230. return (DispatchIPSetRouteWithRef(Irp, IrpSp));
  231. case IOCTL_IP_SET_MULTIHOPROUTE:
  232. return (DispatchIPSetMultihopRoute(Irp, IrpSp));
  233. case IOCTL_IP_ADD_NTE:
  234. {
  235. PIP_ADD_NTE_REQUEST request;
  236. PIP_ADD_NTE_RESPONSE response;
  237. IP_STATUS ipStatus;
  238. int InterfaceNameLen;
  239. UNICODE_STRING InterfaceName;
  240. BOOLEAN requestValid = FALSE;
  241. request = Irp->AssociatedIrp.SystemBuffer;
  242. response = (PIP_ADD_NTE_RESPONSE) request;
  243. //
  244. // Validate input parameters
  245. //
  246. if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  247. sizeof(IP_ADD_NTE_REQUEST_OLD)) &&
  248. (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
  249. sizeof(IP_ADD_NTE_RESPONSE))) {
  250. #if defined(_WIN64)
  251. PIP_ADD_NTE_REQUEST32 request32;
  252. if (IoIs32bitProcess(Irp)) {
  253. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  254. sizeof(IP_ADD_NTE_REQUEST32)) {
  255. requestValid = TRUE;
  256. request32 = Irp->AssociatedIrp.SystemBuffer;
  257. InterfaceName.Length = request32->InterfaceName.Length;
  258. InterfaceName.MaximumLength =
  259. request32->InterfaceName.MaximumLength;
  260. InterfaceName.Buffer =
  261. (PWCHAR)request32->InterfaceNameBuffer;
  262. InterfaceNameLen =
  263. IrpSp->Parameters.DeviceIoControl.InputBufferLength
  264. - FIELD_OFFSET(IP_ADD_NTE_REQUEST32,
  265. InterfaceNameBuffer);
  266. }
  267. } else {
  268. #endif // _WIN64
  269. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  270. sizeof(IP_ADD_NTE_REQUEST)) {
  271. requestValid = TRUE;
  272. InterfaceName = request->InterfaceName;
  273. InterfaceName.Buffer = (PWCHAR)request->InterfaceNameBuffer;
  274. InterfaceNameLen =
  275. IrpSp->Parameters.DeviceIoControl.InputBufferLength -
  276. FIELD_OFFSET(IP_ADD_NTE_REQUEST, InterfaceNameBuffer);
  277. }
  278. #if defined(_WIN64)
  279. }
  280. #endif // _WIN64
  281. if (requestValid) {
  282. ipStatus = IPAddDynamicNTE(
  283. request->InterfaceContext,
  284. &InterfaceName,
  285. InterfaceNameLen,
  286. request->Address,
  287. request->SubnetMask,
  288. &(response->Context),
  289. &(response->Instance)
  290. );
  291. } else {
  292. ipStatus = IPAddDynamicNTE(
  293. request->InterfaceContext,
  294. NULL,
  295. 0,
  296. request->Address,
  297. request->SubnetMask,
  298. &(response->Context),
  299. &(response->Instance)
  300. );
  301. }
  302. status = IPStatusToNTStatus(ipStatus);
  303. if (status == STATUS_SUCCESS) {
  304. Irp->IoStatus.Information = sizeof(IP_ADD_NTE_RESPONSE);
  305. }
  306. } else {
  307. status = STATUS_INVALID_PARAMETER;
  308. }
  309. }
  310. break;
  311. case IOCTL_IP_DELETE_NTE:
  312. {
  313. PIP_DELETE_NTE_REQUEST request;
  314. IP_STATUS ipStatus;
  315. request = Irp->AssociatedIrp.SystemBuffer;
  316. //
  317. // Validate input parameters
  318. //
  319. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  320. sizeof(IP_DELETE_NTE_REQUEST)
  321. ) {
  322. ipStatus = IPDeleteDynamicNTE(
  323. request->Context
  324. );
  325. status = IPStatusToNTStatus(ipStatus);
  326. } else {
  327. status = STATUS_INVALID_PARAMETER;
  328. }
  329. }
  330. break;
  331. case IOCTL_IP_GET_NTE_INFO:
  332. {
  333. PIP_GET_NTE_INFO_REQUEST request;
  334. PIP_GET_NTE_INFO_RESPONSE response;
  335. BOOLEAN retval;
  336. ushort nteFlags;
  337. request = Irp->AssociatedIrp.SystemBuffer;
  338. response = (PIP_GET_NTE_INFO_RESPONSE) request;
  339. //
  340. // Validate input parameters
  341. //
  342. if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  343. sizeof(IP_GET_NTE_INFO_REQUEST)
  344. )
  345. &&
  346. (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
  347. sizeof(IP_GET_NTE_INFO_RESPONSE))
  348. ) {
  349. retval = (BOOLEAN) IPGetNTEInfo(
  350. request->Context,
  351. &(response->Instance),
  352. &(response->Address),
  353. &(response->SubnetMask),
  354. &nteFlags
  355. );
  356. if (retval == FALSE) {
  357. status = STATUS_UNSUCCESSFUL;
  358. } else {
  359. status = STATUS_SUCCESS;
  360. Irp->IoStatus.Information =
  361. sizeof(IP_GET_NTE_INFO_RESPONSE);
  362. response->Flags = 0;
  363. if (nteFlags & NTE_DYNAMIC) {
  364. response->Flags |= IP_NTE_DYNAMIC;
  365. }
  366. }
  367. } else {
  368. status = STATUS_INVALID_PARAMETER;
  369. }
  370. }
  371. break;
  372. case IOCTL_IP_SET_DHCP_INTERFACE:
  373. {
  374. PIP_SET_DHCP_INTERFACE_REQUEST request;
  375. BOOLEAN retval;
  376. request = Irp->AssociatedIrp.SystemBuffer;
  377. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IP_SET_DHCP_INTERFACE_REQUEST)) {
  378. retval = (BOOLEAN) SetDHCPNTE(
  379. request->Context
  380. );
  381. if (retval == FALSE) {
  382. status = STATUS_UNSUCCESSFUL;
  383. } else {
  384. status = STATUS_SUCCESS;
  385. }
  386. } else {
  387. status = STATUS_INVALID_PARAMETER;
  388. }
  389. }
  390. break;
  391. case IOCTL_IP_SET_IF_CONTEXT:
  392. {
  393. status = STATUS_NOT_SUPPORTED;
  394. }
  395. break;
  396. case IOCTL_IP_SET_IF_PROMISCUOUS:
  397. {
  398. PIP_SET_IF_PROMISCUOUS_INFO info;
  399. info = Irp->AssociatedIrp.SystemBuffer;
  400. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IP_SET_IF_PROMISCUOUS_INFO)) {
  401. status = SetIFPromiscuous(info->Index,
  402. info->Type,
  403. info->Add);
  404. } else {
  405. status = STATUS_BUFFER_TOO_SMALL;
  406. }
  407. break;
  408. }
  409. case IOCTL_IP_GET_BESTINTFC_FUNC_ADDR:
  410. if (Irp->RequestorMode != KernelMode) {
  411. status = STATUS_ACCESS_DENIED;
  412. break;
  413. }
  414. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "ip:Getbestinterfacequery\n"));
  415. status = STATUS_INVALID_PARAMETER;
  416. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ulong)) {
  417. PULONG_PTR ptr;
  418. ptr = Irp->AssociatedIrp.SystemBuffer;
  419. if (ptr) {
  420. *ptr = (ULONG_PTR) IPGetBestInterfaceIndex;
  421. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "ip:returning address of Getbestinterface %x\n", *ptr));
  422. Irp->IoStatus.Information = sizeof(ULONG_PTR);
  423. status = STATUS_SUCCESS;
  424. }
  425. }
  426. break;
  427. case IOCTL_IP_SET_FILTER_POINTER:
  428. {
  429. PIP_SET_FILTER_HOOK_INFO info;
  430. if (Irp->RequestorMode != KernelMode) {
  431. status = STATUS_ACCESS_DENIED;
  432. break;
  433. }
  434. info = Irp->AssociatedIrp.SystemBuffer;
  435. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IP_SET_FILTER_HOOK_INFO)) {
  436. status = (NTSTATUS) SetFilterPtr(info->FilterPtr);
  437. if (status != IP_SUCCESS) {
  438. ASSERT(status != IP_PENDING);
  439. //
  440. // Map status
  441. //
  442. status = STATUS_UNSUCCESSFUL;
  443. } else {
  444. status = STATUS_SUCCESS;
  445. }
  446. } else {
  447. status = STATUS_INVALID_PARAMETER;
  448. }
  449. }
  450. break;
  451. case IOCTL_IP_SET_FIREWALL_HOOK:
  452. {
  453. PIP_SET_FIREWALL_HOOK_INFO info;
  454. if (Irp->RequestorMode != KernelMode) {
  455. status = STATUS_ACCESS_DENIED;
  456. break;
  457. }
  458. info = Irp->AssociatedIrp.SystemBuffer;
  459. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IP_SET_FIREWALL_HOOK_INFO)) {
  460. status = (NTSTATUS) SetFirewallHook(info);
  461. if (status != IP_SUCCESS) {
  462. ASSERT(status != IP_PENDING);
  463. //
  464. // Map status
  465. //
  466. status = STATUS_UNSUCCESSFUL;
  467. } else {
  468. status = STATUS_SUCCESS;
  469. }
  470. } else {
  471. status = STATUS_INVALID_PARAMETER;
  472. }
  473. }
  474. break;
  475. case IOCTL_IP_SET_MAP_ROUTE_POINTER:
  476. {
  477. PIP_SET_MAP_ROUTE_HOOK_INFO info;
  478. if (Irp->RequestorMode != KernelMode) {
  479. status = STATUS_ACCESS_DENIED;
  480. break;
  481. }
  482. info = Irp->AssociatedIrp.SystemBuffer;
  483. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IP_SET_MAP_ROUTE_HOOK_INFO)) {
  484. status = (NTSTATUS) SetMapRoutePtr(info->MapRoutePtr);
  485. if (status != IP_SUCCESS) {
  486. ASSERT(status != IP_PENDING);
  487. //
  488. // Map status
  489. //
  490. status = STATUS_UNSUCCESSFUL;
  491. } else {
  492. status = STATUS_SUCCESS;
  493. }
  494. } else {
  495. status = STATUS_INVALID_PARAMETER;
  496. }
  497. }
  498. break;
  499. case IOCTL_IP_RTCHANGE_NOTIFY_REQUEST:
  500. {
  501. status = RtChangeNotifyRequest(Irp, IrpSp);
  502. break;
  503. }
  504. case IOCTL_IP_RTCHANGE_NOTIFY_REQUEST_EX:
  505. {
  506. status = RtChangeNotifyRequestEx(Irp, IrpSp);
  507. break;
  508. }
  509. case IOCTL_IP_ADDCHANGE_NOTIFY_REQUEST:
  510. {
  511. status = AddrChangeNotifyRequest(Irp, IrpSp);
  512. break;
  513. }
  514. #if MILLEN
  515. case IOCTL_IP_IFCHANGE_NOTIFY_REQUEST:
  516. {
  517. status = IfChangeNotifyRequest(Irp, IrpSp);
  518. break;
  519. }
  520. // For non-MILLEN, will default and return NOT_IMPLEMENTED.
  521. #endif // MILLEN
  522. case IOCTL_IP_UNIDIRECTIONAL_ADAPTER_ADDRESS:
  523. {
  524. Interface *pIf;
  525. ULONG cUniIF;
  526. ULONG cbRequired;
  527. PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pUniAdapterAddress;
  528. IPAddr *pUniIpAddr;
  529. CTELockHandle Handle;
  530. CTEGetLock(&RouteTableLock.Lock, &Handle);
  531. //
  532. // First off, count the number of unidirectional interfaces
  533. // and bytes required.
  534. //
  535. cUniIF = 0;
  536. cbRequired = FIELD_OFFSET(IP_UNIDIRECTIONAL_ADAPTER_ADDRESS, Address);
  537. for (pIf = IFList; pIf != NULL; pIf = pIf->if_next) {
  538. if (pIf->if_flags & IF_FLAGS_UNI) {
  539. cUniIF++;
  540. }
  541. }
  542. cbRequired = FIELD_OFFSET(IP_UNIDIRECTIONAL_ADAPTER_ADDRESS, Address[cUniIF]);
  543. if (cUniIF == 0) {
  544. cbRequired = sizeof(IP_UNIDIRECTIONAL_ADAPTER_ADDRESS);
  545. }
  546. //
  547. // Validate output buffer length and copy.
  548. //
  549. if (cbRequired <= IrpSp->Parameters.DeviceIoControl.OutputBufferLength) {
  550. pUniAdapterAddress = Irp->AssociatedIrp.SystemBuffer;
  551. pUniAdapterAddress->NumAdapters = cUniIF;
  552. pUniIpAddr = &pUniAdapterAddress->Address[0];
  553. if (cUniIF) {
  554. for (pIf = IFList; pIf != NULL; pIf = pIf->if_next) {
  555. if (pIf->if_flags & IF_FLAGS_UNI) {
  556. *pUniIpAddr++ = pIf->if_index;
  557. }
  558. }
  559. }
  560. Irp->IoStatus.Information = cbRequired;
  561. status = STATUS_SUCCESS;
  562. } else {
  563. Irp->IoStatus.Information = 0;
  564. status = STATUS_BUFFER_OVERFLOW;
  565. }
  566. CTEFreeLock(&RouteTableLock.Lock, Handle);
  567. break;
  568. }
  569. case IOCTL_IP_GET_PNP_ARP_POINTERS:
  570. {
  571. PIP_GET_PNP_ARP_POINTERS info = (PIP_GET_PNP_ARP_POINTERS) Irp->AssociatedIrp.SystemBuffer;
  572. if (Irp->RequestorMode != KernelMode) {
  573. status = STATUS_ACCESS_DENIED;
  574. break;
  575. }
  576. info->IPAddInterface = (IPAddInterfacePtr) IPAddInterface;
  577. info->IPDelInterface = (IPDelInterfacePtr) IPDelInterface;
  578. Irp->IoStatus.Status = STATUS_SUCCESS;
  579. Irp->IoStatus.Information = sizeof(IP_GET_PNP_ARP_POINTERS);
  580. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  581. return STATUS_SUCCESS;;
  582. }
  583. break;
  584. case IOCTL_IP_WAKEUP_PATTERN:
  585. {
  586. PIP_WAKEUP_PATTERN_REQUEST Info = (PIP_WAKEUP_PATTERN_REQUEST) Irp->AssociatedIrp.SystemBuffer;
  587. if (Irp->RequestorMode != KernelMode) {
  588. status = STATUS_ACCESS_DENIED;
  589. break;
  590. }
  591. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  592. sizeof(IP_WAKEUP_PATTERN_REQUEST)) {
  593. status = IPWakeupPattern(
  594. Info->InterfaceContext,
  595. Info->PtrnDesc,
  596. Info->AddPattern);
  597. } else {
  598. status = STATUS_INVALID_PARAMETER;
  599. }
  600. }
  601. break;
  602. case IOCTL_IP_GET_WOL_CAPABILITY:
  603. case IOCTL_IP_GET_OFFLOAD_CAPABILITY:
  604. {
  605. PULONG request, response;
  606. request = Irp->AssociatedIrp.SystemBuffer;
  607. response = (PULONG) request;
  608. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  609. sizeof(ULONG) &&
  610. IrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
  611. sizeof(ULONG)) {
  612. uint cap;
  613. if (code == IOCTL_IP_GET_WOL_CAPABILITY) {
  614. cap = IF_WOL_CAP;
  615. } else {
  616. cap = IF_OFFLOAD_CAP;
  617. }
  618. status = IPGetCapability(*request, response, cap);
  619. } else {
  620. status = STATUS_INVALID_PARAMETER;
  621. }
  622. if (status == STATUS_SUCCESS) {
  623. Irp->IoStatus.Information = sizeof(ULONG);
  624. }
  625. }
  626. break;
  627. case IOCTL_IP_GET_IP_EVENT:
  628. return (DispatchIPGetIPEvent(Irp, IrpSp));
  629. case IOCTL_IP_FLUSH_ARP_TABLE:
  630. status = FlushArpTable(Irp, IrpSp);
  631. break;
  632. case IOCTL_IP_GET_IF_INDEX:
  633. status = IPGetIfIndex(Irp,
  634. IrpSp);
  635. break;
  636. case IOCTL_IP_GET_IF_NAME:
  637. status = IPGetIfName(Irp,
  638. IrpSp);
  639. break;
  640. case IOCTL_IP_GET_MCAST_COUNTERS:
  641. return (IPGetMcastCounters(Irp,IrpSp));
  642. case IOCTL_IP_ENABLE_ROUTER_REQUEST:
  643. status = IPEnableRouterRequest(Irp, IrpSp);
  644. break;
  645. case IOCTL_IP_UNENABLE_ROUTER_REQUEST: {
  646. PVOID ApcContext;
  647. status = STATUS_SUCCESS;
  648. #if defined(_WIN64)
  649. if (IoIs32bitProcess(Irp)) {
  650. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength !=
  651. sizeof(VOID * POINTER_32) ||
  652. IrpSp->Parameters.DeviceIoControl.OutputBufferLength !=
  653. sizeof(ULONG)) {
  654. status = STATUS_INVALID_BUFFER_SIZE;
  655. } else {
  656. ApcContext =
  657. (PVOID)*(VOID * POINTER_32 *)
  658. Irp->AssociatedIrp.SystemBuffer;
  659. }
  660. } else {
  661. #endif // _WIN64
  662. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength !=
  663. sizeof(PVOID) ||
  664. IrpSp->Parameters.DeviceIoControl.OutputBufferLength !=
  665. sizeof(ULONG)) {
  666. status = STATUS_INVALID_BUFFER_SIZE;
  667. } else {
  668. ApcContext = *(PVOID*)Irp->AssociatedIrp.SystemBuffer;
  669. }
  670. #if defined(_WIN64)
  671. }
  672. #endif // _WIN64
  673. if (NT_SUCCESS(status)) {
  674. status = IPUnenableRouterRequest(Irp, IrpSp, ApcContext);
  675. }
  676. break;
  677. }
  678. #if DBG_MAP_BUFFER
  679. case IOCTL_IP_DBG_TEST_FAIL_MAP_BUFFER:
  680. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(ULONG)) {
  681. status = STATUS_INVALID_BUFFER_SIZE;
  682. } else {
  683. PULONG pBuf = (PULONG) Irp->AssociatedIrp.SystemBuffer;
  684. status = DbgTestFailMapBuffers(
  685. *pBuf);
  686. }
  687. break;
  688. #endif // DBG_MAP_BUFFER
  689. case IOCTL_IP_ENABLE_MEDIA_SENSE_REQUEST:
  690. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength !=
  691. sizeof(PVOID) ||
  692. IrpSp->Parameters.DeviceIoControl.OutputBufferLength !=
  693. sizeof(ULONG)) {
  694. status = STATUS_INVALID_BUFFER_SIZE;
  695. } else {
  696. status = IPEnableMediaSenseRequest(Irp, IrpSp);
  697. }
  698. break;
  699. case IOCTL_IP_DISABLE_MEDIA_SENSE_REQUEST:
  700. status = IPDisableMediaSenseRequest(Irp, IrpSp);
  701. break;
  702. default:
  703. status = STATUS_NOT_IMPLEMENTED;
  704. break;
  705. }
  706. if ((status != IP_PENDING) && (status != STATUS_PENDING)) {
  707. Irp->IoStatus.Status = status;
  708. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  709. }
  710. return status;
  711. }
  712. NTSTATUS
  713. IPDispatchInternalDeviceControl(
  714. IN PIRP Irp,
  715. IN PIO_STACK_LOCATION IrpSp
  716. )
  717. /*++
  718. Routine Description:
  719. Arguments:
  720. Irp - Pointer to I/O request packet
  721. IrpSp - Pointer to the current stack location in the Irp.
  722. Return Value:
  723. NTSTATUS -- Indicates whether the request was successfully queued.
  724. --*/
  725. {
  726. NTSTATUS status;
  727. PAGED_CODE();
  728. status = STATUS_SUCCESS;
  729. Irp->IoStatus.Status = status;
  730. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  731. return status;
  732. }
  733. NTSTATUS
  734. IPCreate(
  735. IN PIRP Irp,
  736. IN PIO_STACK_LOCATION IrpSp
  737. )
  738. /*++
  739. Routine Description:
  740. Arguments:
  741. Irp - Pointer to I/O request packet
  742. IrpSp - Pointer to the current stack location in the Irp.
  743. Return Value:
  744. NTSTATUS -- Indicates whether the request was successfully queued.
  745. --*/
  746. {
  747. PAGED_CODE();
  748. return (STATUS_SUCCESS);
  749. }
  750. NTSTATUS
  751. IPCleanup(
  752. IN PIRP Irp,
  753. IN PIO_STACK_LOCATION IrpSp
  754. )
  755. /*++
  756. Routine Description:
  757. Arguments:
  758. Irp - Pointer to I/O request packet
  759. IrpSp - Pointer to the current stack location in the Irp.
  760. Return Value:
  761. NTSTATUS -- Indicates whether the request was successfully queued.
  762. --*/
  763. {
  764. PPENDING_IRP pendingIrp;
  765. PLIST_ENTRY entry, nextEntry;
  766. KIRQL oldIrql;
  767. LIST_ENTRY completeList;
  768. PIRP cancelledIrp;
  769. InitializeListHead(&completeList);
  770. //
  771. // Collect all of the pending IRPs on this file object.
  772. //
  773. IoAcquireCancelSpinLock(&oldIrql);
  774. entry = PendingArpSendList.Flink;
  775. while (entry != &PendingArpSendList) {
  776. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  777. if (pendingIrp->FileObject == IrpSp->FileObject) {
  778. nextEntry = entry->Flink;
  779. RemoveEntryList(entry);
  780. IoSetCancelRoutine(pendingIrp->Irp, NULL);
  781. InsertTailList(&completeList, &(pendingIrp->Linkage));
  782. entry = nextEntry;
  783. } else {
  784. entry = entry->Flink;
  785. }
  786. }
  787. IoReleaseCancelSpinLock(oldIrql);
  788. //
  789. // Complete them.
  790. //
  791. entry = completeList.Flink;
  792. while (entry != &completeList) {
  793. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  794. cancelledIrp = pendingIrp->Irp;
  795. entry = entry->Flink;
  796. //
  797. // Free the PENDING_IRP structure. The control block will be freed
  798. // when the request completes.
  799. //
  800. CTEFreeMem(pendingIrp);
  801. //
  802. // Complete the IRP.
  803. //
  804. cancelledIrp->IoStatus.Information = 0;
  805. cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
  806. IoCompleteRequest(cancelledIrp, IO_NETWORK_INCREMENT);
  807. }
  808. InitializeListHead(&completeList);
  809. //
  810. // Collect all of the pending IRPs on this file object.
  811. //
  812. IoAcquireCancelSpinLock(&oldIrql);
  813. entry = PendingEchoList.Flink;
  814. while (entry != &PendingEchoList) {
  815. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  816. if (pendingIrp->FileObject == IrpSp->FileObject) {
  817. nextEntry = entry->Flink;
  818. RemoveEntryList(entry);
  819. IoSetCancelRoutine(pendingIrp->Irp, NULL);
  820. InsertTailList(&completeList, &(pendingIrp->Linkage));
  821. entry = nextEntry;
  822. } else {
  823. entry = entry->Flink;
  824. }
  825. }
  826. IoReleaseCancelSpinLock(oldIrql);
  827. //
  828. // Complete them.
  829. //
  830. entry = completeList.Flink;
  831. while (entry != &completeList) {
  832. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  833. cancelledIrp = pendingIrp->Irp;
  834. entry = entry->Flink;
  835. //
  836. // Free the PENDING_IRP structure. The control block will be freed
  837. // when the request completes.
  838. //
  839. CTEFreeMem(pendingIrp);
  840. //
  841. // Complete the IRP.
  842. //
  843. cancelledIrp->IoStatus.Information = 0;
  844. cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
  845. IoCompleteRequest(cancelledIrp, IO_NETWORK_INCREMENT);
  846. }
  847. InitializeListHead(&completeList);
  848. //
  849. // Collect all of the pending IRPs on this file object.
  850. //
  851. IoAcquireCancelSpinLock(&oldIrql);
  852. entry = PendingIPSetNTEAddrList.Flink;
  853. while (entry != &PendingIPSetNTEAddrList) {
  854. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  855. if (pendingIrp->FileObject == IrpSp->FileObject) {
  856. nextEntry = entry->Flink;
  857. RemoveEntryList(entry);
  858. IoSetCancelRoutine(pendingIrp->Irp, NULL);
  859. InsertTailList(&completeList, &(pendingIrp->Linkage));
  860. entry = nextEntry;
  861. } else {
  862. entry = entry->Flink;
  863. }
  864. }
  865. IoReleaseCancelSpinLock(oldIrql);
  866. //
  867. // Complete them.
  868. //
  869. entry = completeList.Flink;
  870. while (entry != &completeList) {
  871. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  872. cancelledIrp = pendingIrp->Irp;
  873. entry = entry->Flink;
  874. //
  875. // Free the PENDING_IRP structure. The control block will be freed
  876. // when the request completes.
  877. //
  878. CTEFreeMem(pendingIrp);
  879. //
  880. // Complete the IRP.
  881. //
  882. cancelledIrp->IoStatus.Information = 0;
  883. cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
  884. IoCompleteRequest(cancelledIrp, IO_NETWORK_INCREMENT);
  885. }
  886. //
  887. // complete the pending irp for media sense
  888. //
  889. cancelledIrp = NULL;
  890. IoAcquireCancelSpinLock(&oldIrql);
  891. if (PendingIPGetIPEventRequest && IoGetCurrentIrpStackLocation(PendingIPGetIPEventRequest)->FileObject == IrpSp->FileObject) {
  892. cancelledIrp = PendingIPGetIPEventRequest;
  893. PendingIPGetIPEventRequest = NULL;
  894. IoSetCancelRoutine(cancelledIrp, NULL);
  895. }
  896. IoReleaseCancelSpinLock(oldIrql);
  897. if (cancelledIrp) {
  898. cancelledIrp->IoStatus.Information = 0;
  899. cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
  900. IoCompleteRequest(cancelledIrp, IO_NETWORK_INCREMENT);
  901. }
  902. return (STATUS_SUCCESS);
  903. }
  904. NTSTATUS
  905. IPClose(
  906. IN PIRP Irp,
  907. IN PIO_STACK_LOCATION IrpSp
  908. )
  909. /*++
  910. Routine Description:
  911. Arguments:
  912. Irp - Pointer to I/O request packet
  913. IrpSp - Pointer to the current stack location in the Irp.
  914. Return Value:
  915. NTSTATUS -- Indicates whether the request was successfully queued.
  916. --*/
  917. {
  918. PAGED_CODE();
  919. return (STATUS_SUCCESS);
  920. }
  921. //
  922. // ARP send function definitions
  923. //
  924. VOID
  925. CancelArpSendRequest(
  926. IN PDEVICE_OBJECT Device,
  927. IN PIRP Irp
  928. )
  929. /*++
  930. Routine Description:
  931. Cancels an outstanding ARP request Irp.
  932. Arguments:
  933. Device - The device on which the request was issued.
  934. Irp - Pointer to I/O request packet to cancel.
  935. Return Value:
  936. None.
  937. Notes:
  938. This function is called with cancel spinlock held. It must be
  939. released before the function returns.
  940. The ARP control block associated with this request cannot be
  941. freed until the request completes. The completion routine will
  942. free it.
  943. --*/
  944. {
  945. PPENDING_IRP pendingIrp = NULL;
  946. PPENDING_IRP item;
  947. PLIST_ENTRY entry;
  948. for (entry = PendingArpSendList.Flink;
  949. entry != &PendingArpSendList;
  950. entry = entry->Flink
  951. ) {
  952. item = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  953. if (item->Irp == Irp) {
  954. pendingIrp = item;
  955. RemoveEntryList(entry);
  956. break;
  957. }
  958. }
  959. IoReleaseCancelSpinLock(Irp->CancelIrql);
  960. if (pendingIrp != NULL) {
  961. //
  962. // Free the PENDING_IRP structure. The control block will be freed
  963. // when the request completes.
  964. //
  965. CTEFreeMem(pendingIrp);
  966. //
  967. // Complete the IRP.
  968. //
  969. Irp->IoStatus.Information = 0;
  970. Irp->IoStatus.Status = STATUS_CANCELLED;
  971. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  972. }
  973. return;
  974. }
  975. NTSTATUS
  976. RtChangeNotifyRequest(
  977. PIRP Irp,
  978. IN PIO_STACK_LOCATION IrpSp
  979. )
  980. {
  981. CTELockHandle TableHandle;
  982. KIRQL OldIrq;
  983. NTSTATUS status;
  984. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength &&
  985. IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  986. sizeof(IPNotifyData)) {
  987. status = STATUS_INVALID_PARAMETER;
  988. goto done;
  989. }
  990. #if MILLEN
  991. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength &&
  992. IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  993. sizeof(IP_RTCHANGE_NOTIFY)) {
  994. status = STATUS_INVALID_PARAMETER;
  995. goto done;
  996. }
  997. #endif // MILLEN
  998. IoAcquireCancelSpinLock(&OldIrq);
  999. CTEGetLock(&RouteTableLock.Lock, &TableHandle);
  1000. InsertTailList(&RtChangeNotifyQueue, &Irp->Tail.Overlay.ListEntry);
  1001. if (Irp->Cancel) {
  1002. RemoveTailList(&RtChangeNotifyQueue);
  1003. status = STATUS_CANCELLED;
  1004. } else {
  1005. IoMarkIrpPending(Irp);
  1006. IoSetCancelRoutine(Irp, RtChangeNotifyCancel);
  1007. status = STATUS_PENDING;
  1008. }
  1009. Irp->IoStatus.Information = 0;
  1010. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  1011. IoReleaseCancelSpinLock(OldIrq);
  1012. done:
  1013. return status;
  1014. }
  1015. NTSTATUS
  1016. RtChangeNotifyRequestEx(
  1017. PIRP Irp,
  1018. IN PIO_STACK_LOCATION IrpSp
  1019. )
  1020. {
  1021. CTELockHandle TableHandle;
  1022. KIRQL OldIrq;
  1023. NTSTATUS status;
  1024. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength &&
  1025. IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  1026. sizeof(IPNotifyData)) {
  1027. status = STATUS_INVALID_PARAMETER;
  1028. goto done;
  1029. }
  1030. #if MILLEN
  1031. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength &&
  1032. IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1033. sizeof(IP_RTCHANGE_NOTIFY)) {
  1034. status = STATUS_INVALID_PARAMETER;
  1035. goto done;
  1036. }
  1037. #endif // MILLEN
  1038. IoAcquireCancelSpinLock(&OldIrq);
  1039. CTEGetLock(&RouteTableLock.Lock, &TableHandle);
  1040. InsertTailList(&RtChangeNotifyQueueEx, &Irp->Tail.Overlay.ListEntry);
  1041. if (Irp->Cancel) {
  1042. RemoveTailList(&RtChangeNotifyQueueEx);
  1043. status = STATUS_CANCELLED;
  1044. } else {
  1045. IoMarkIrpPending(Irp);
  1046. IoSetCancelRoutine(Irp, RtChangeNotifyCancelEx);
  1047. status = STATUS_PENDING;
  1048. }
  1049. Irp->IoStatus.Information = 0;
  1050. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  1051. IoReleaseCancelSpinLock(OldIrq);
  1052. done:
  1053. return status;
  1054. }
  1055. NTSTATUS
  1056. AddrChangeNotifyRequest(PIRP Irp, PIO_STACK_LOCATION pIrpSp)
  1057. {
  1058. CTELockHandle TableHandle;
  1059. KIRQL OldIrq;
  1060. NTSTATUS status;
  1061. DEBUGMSG(DBG_TRACE && DBG_NOTIFY,
  1062. (DTEXT("AddrChangeNotifyRequest(%x, %x)\n"), Irp, pIrpSp));
  1063. #if MILLEN
  1064. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength) {
  1065. PIP_ADDCHANGE_NOTIFY pNotify = Irp->AssociatedIrp.SystemBuffer;
  1066. DEBUGMSG(DBG_INFO && DBG_NOTIFY,
  1067. (DTEXT("AddrChangeNotifyRequest OutputLen %d, MaxCfgName %d\n"),
  1068. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  1069. pNotify->ConfigName.MaximumLength));
  1070. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1071. (FIELD_OFFSET(IP_ADDCHANGE_NOTIFY, NameData) + (ULONG) pNotify->ConfigName.MaximumLength)) {
  1072. DEBUGMSG(DBG_ERROR,
  1073. (DTEXT("AddrChangeNotifyRequest: INVALID output buffer length.\n")));
  1074. status = STATUS_INVALID_PARAMETER;
  1075. goto done;
  1076. }
  1077. }
  1078. #endif // MILLEN
  1079. IoAcquireCancelSpinLock(&OldIrq);
  1080. CTEGetLock(&AddChangeLock, &TableHandle);
  1081. InsertTailList(
  1082. &AddChangeNotifyQueue,
  1083. &(Irp->Tail.Overlay.ListEntry)
  1084. );
  1085. if (Irp->Cancel) {
  1086. (VOID) RemoveTailList(&AddChangeNotifyQueue);
  1087. status = STATUS_CANCELLED;
  1088. } else {
  1089. IoMarkIrpPending(Irp);
  1090. IoSetCancelRoutine(Irp, AddChangeNotifyCancel);
  1091. status = STATUS_PENDING;
  1092. }
  1093. Irp->IoStatus.Information = 0;
  1094. CTEFreeLock(&AddChangeLock, TableHandle);
  1095. IoReleaseCancelSpinLock(OldIrq);
  1096. #if MILLEN
  1097. done:
  1098. #endif // MILLEN
  1099. DEBUGMSG(DBG_TRACE && DBG_NOTIFY,
  1100. (DTEXT("-AddrChangeNotifyRequest [%x]\n"), status));
  1101. return status;
  1102. }
  1103. #if MILLEN
  1104. void
  1105. IfChangeNotifyCancel(
  1106. IN PDEVICE_OBJECT pDeviceObject,
  1107. IN PIRP pIrp
  1108. )
  1109. {
  1110. DEBUGMSG(DBG_TRACE && DBG_NOTIFY,
  1111. (DTEXT("IfChangeNotifyCancel(%x, %x)\n"), pDeviceObject, pIrp));
  1112. CancelNotify(pIrp, &IfChangeNotifyQueue, &IfChangeLock);
  1113. return;
  1114. }
  1115. NTSTATUS
  1116. IfChangeNotifyRequest(
  1117. PIRP pIrp,
  1118. PIO_STACK_LOCATION pIrpSp
  1119. )
  1120. {
  1121. CTELockHandle TableHandle;
  1122. KIRQL OldIrq;
  1123. NTSTATUS NtStatus;
  1124. DEBUGMSG(DBG_TRACE && DBG_NOTIFY,
  1125. (DTEXT("+IfChangeNotifyRequest(%x, %x)\n"), pIrp, pIrpSp));
  1126. //
  1127. // Check output buffer length. Output buffer will store the
  1128. // NTE context and whether the interface was added or deleted.
  1129. //
  1130. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(IP_IFCHANGE_NOTIFY)) {
  1131. NtStatus = STATUS_INVALID_PARAMETER;
  1132. pIrp->IoStatus.Status = NtStatus;
  1133. pIrp->IoStatus.Information = 0;
  1134. goto done;
  1135. }
  1136. //
  1137. // Set cancel routine, mark IRP as pending and put on our interface
  1138. // notify list.
  1139. //
  1140. IoAcquireCancelSpinLock(&OldIrq);
  1141. IoMarkIrpPending(pIrp);
  1142. CTEGetLock(&IfChangeLock, &TableHandle);
  1143. InsertTailList(
  1144. &IfChangeNotifyQueue,
  1145. &(pIrp->Tail.Overlay.ListEntry)
  1146. );
  1147. if (pIrp->Cancel) {
  1148. RemoveTailList(&IfChangeNotifyQueue);
  1149. NtStatus = STATUS_CANCELLED;
  1150. } else {
  1151. IoSetCancelRoutine(pIrp, IfChangeNotifyCancel);
  1152. NtStatus = STATUS_PENDING;
  1153. }
  1154. pIrp->IoStatus.Information = 0;
  1155. CTEFreeLock(&IfChangeLock, TableHandle);
  1156. IoReleaseCancelSpinLock(OldIrq);
  1157. done:
  1158. DEBUGMSG(DBG_TRACE && DBG_NOTIFY,
  1159. (DTEXT("-IfChangeNotifyRequest [%x]\n"), NtStatus));
  1160. return NtStatus;
  1161. }
  1162. #endif // MILLEN
  1163. NTSTATUS
  1164. IPEnableRouterRequest(
  1165. PIRP Irp,
  1166. PIO_STACK_LOCATION IrpSp
  1167. )
  1168. {
  1169. KIRQL OldIrql;
  1170. NTSTATUS status;
  1171. CTELockHandle TableHandle;
  1172. IoAcquireCancelSpinLock(&OldIrql);
  1173. if (Irp->Cancel) {
  1174. status = STATUS_CANCELLED;
  1175. } else {
  1176. IoMarkIrpPending(Irp);
  1177. IoSetCancelRoutine(Irp, CancelIPEnableRouterRequest);
  1178. // Increment the routing-enabled reference count.
  1179. // When the count rises above zero routing is enabled.
  1180. // This reference will be dropped when the IRP is cancelled.
  1181. CTEGetLockAtDPC(&RouteTableLock.Lock, &TableHandle);
  1182. Irp->Tail.Overlay.DriverContext[0] = IrpSp->FileObject;
  1183. InsertTailList(&PendingEnableRouterList, &Irp->Tail.Overlay.ListEntry);
  1184. IPEnableRouterWithRefCount(TRUE);
  1185. CTEFreeLockFromDPC(&RouteTableLock.Lock, TableHandle);
  1186. status = STATUS_PENDING;
  1187. }
  1188. Irp->IoStatus.Information = 0;
  1189. IoReleaseCancelSpinLock(OldIrql);
  1190. return status;
  1191. }
  1192. VOID
  1193. CancelIPEnableRouterRequest(
  1194. IN PDEVICE_OBJECT Device,
  1195. IN PIRP Irp
  1196. )
  1197. {
  1198. CTELockHandle TableHandle;
  1199. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1200. // Decrement the routing-enabled reference count.
  1201. // If the count drops to zero routing is disabled.
  1202. CTEGetLock(&RouteTableLock.Lock, &TableHandle);
  1203. RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
  1204. IPEnableRouterWithRefCount(FALSE);
  1205. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  1206. Irp->IoStatus.Information = 0;
  1207. Irp->IoStatus.Status = STATUS_CANCELLED;
  1208. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  1209. }
  1210. NTSTATUS
  1211. IPUnenableRouterRequest(
  1212. PIRP Irp,
  1213. PIO_STACK_LOCATION IrpSp,
  1214. PVOID ApcContext
  1215. )
  1216. {
  1217. PLIST_ENTRY entry;
  1218. KIRQL CancelIrql;
  1219. int RefCount;
  1220. CTELockHandle TableHandle;
  1221. // Locate the pending IRP for the request corresponding to the caller's
  1222. // disable-request. Drop the routing-enabled reference-count, complete
  1223. // the corresponding IRP, and tell the caller what the reference-count's
  1224. // current value is.
  1225. IoAcquireCancelSpinLock(&CancelIrql);
  1226. CTEGetLock(&RouteTableLock.Lock, &TableHandle);
  1227. for (entry = PendingEnableRouterList.Flink;
  1228. entry != &PendingEnableRouterList;
  1229. entry = entry->Flink
  1230. ) {
  1231. PIRP EnableIrp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
  1232. if (EnableIrp->Tail.Overlay.DriverContext[0] == IrpSp->FileObject &&
  1233. EnableIrp->Overlay.AsynchronousParameters.UserApcContext ==
  1234. ApcContext) {
  1235. RemoveEntryList(&EnableIrp->Tail.Overlay.ListEntry);
  1236. RefCount = IPEnableRouterWithRefCount(FALSE);
  1237. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  1238. IoSetCancelRoutine(EnableIrp, NULL);
  1239. IoReleaseCancelSpinLock(CancelIrql);
  1240. EnableIrp->IoStatus.Status = STATUS_SUCCESS;
  1241. EnableIrp->IoStatus.Information = 0;
  1242. IoCompleteRequest(EnableIrp, IO_NETWORK_INCREMENT);
  1243. *(PULONG)Irp->AssociatedIrp.SystemBuffer = (ULONG)RefCount;
  1244. Irp->IoStatus.Information = sizeof(ULONG);
  1245. return STATUS_SUCCESS;
  1246. }
  1247. }
  1248. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  1249. IoReleaseCancelSpinLock(CancelIrql);
  1250. return STATUS_INVALID_PARAMETER;
  1251. }
  1252. //
  1253. // ICMP Echo function definitions
  1254. //
  1255. VOID
  1256. CancelEchoRequest(
  1257. IN PDEVICE_OBJECT Device,
  1258. IN PIRP Irp
  1259. )
  1260. /*++
  1261. Routine Description:
  1262. Cancels an outstanding Echo request Irp.
  1263. Arguments:
  1264. Device - The device on which the request was issued.
  1265. Irp - Pointer to I/O request packet to cancel.
  1266. Return Value:
  1267. None.
  1268. Notes:
  1269. This function is called with cancel spinlock held. It must be
  1270. released before the function returns.
  1271. The echo control block associated with this request cannot be
  1272. freed until the request completes. The completion routine will
  1273. free it.
  1274. --*/
  1275. {
  1276. PPENDING_IRP pendingIrp = NULL;
  1277. PPENDING_IRP item;
  1278. PLIST_ENTRY entry;
  1279. for (entry = PendingEchoList.Flink;
  1280. entry != &PendingEchoList;
  1281. entry = entry->Flink
  1282. ) {
  1283. item = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1284. if (item->Irp == Irp) {
  1285. pendingIrp = item;
  1286. RemoveEntryList(entry);
  1287. break;
  1288. }
  1289. }
  1290. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1291. if (pendingIrp != NULL) {
  1292. //
  1293. // Free the PENDING_IRP structure. The control block will be freed
  1294. // when the request completes.
  1295. //
  1296. CTEFreeMem(pendingIrp);
  1297. //
  1298. // Complete the IRP.
  1299. //
  1300. Irp->IoStatus.Information = 0;
  1301. Irp->IoStatus.Status = STATUS_CANCELLED;
  1302. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  1303. }
  1304. return;
  1305. }
  1306. //
  1307. // IP Set Addr function definitions
  1308. //
  1309. VOID
  1310. CancelIPSetNTEAddrRequest(
  1311. IN PDEVICE_OBJECT Device,
  1312. IN PIRP Irp
  1313. )
  1314. /*++
  1315. Routine Description:
  1316. Cancels an outstanding IP Set Addr request Irp.
  1317. Arguments:
  1318. Device - The device on which the request was issued.
  1319. Irp - Pointer to I/O request packet to cancel.
  1320. Return Value:
  1321. None.
  1322. Notes:
  1323. This function is called with cancel spinlock held. It must be
  1324. released before the function returns.
  1325. The IP Set Addr control block associated with this request cannot be
  1326. freed until the request completes. The completion routine will
  1327. free it.
  1328. --*/
  1329. {
  1330. PPENDING_IRP pendingIrp = NULL;
  1331. PPENDING_IRP item;
  1332. PLIST_ENTRY entry;
  1333. for (entry = PendingIPSetNTEAddrList.Flink;
  1334. entry != &PendingIPSetNTEAddrList;
  1335. entry = entry->Flink
  1336. ) {
  1337. item = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1338. if (item->Irp == Irp) {
  1339. pendingIrp = item;
  1340. RemoveEntryList(entry);
  1341. break;
  1342. }
  1343. }
  1344. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1345. if (pendingIrp != NULL) {
  1346. //
  1347. // Free the PENDING_IRP structure. The control block will be freed
  1348. // when the request completes.
  1349. //
  1350. CTEFreeMem(pendingIrp);
  1351. //
  1352. // Complete the IRP.
  1353. //
  1354. Irp->IoStatus.Information = 0;
  1355. Irp->IoStatus.Status = STATUS_CANCELLED;
  1356. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  1357. }
  1358. return;
  1359. }
  1360. VOID
  1361. CancelIPGetIPEventRequest(
  1362. IN PDEVICE_OBJECT Device,
  1363. IN PIRP Irp
  1364. )
  1365. /*++
  1366. Routine Description:
  1367. Cancels IPGetIPEvent function.
  1368. Arguments:
  1369. Device - The device on which the request was issued.
  1370. Irp - Pointer to I/O request packet to cancel.
  1371. Return Value:
  1372. None.
  1373. Notes:
  1374. This function is called with cancel spinlock held. It must be
  1375. released before the function returns.
  1376. The IP Set Addr control block associated with this request cannot be
  1377. freed until the request completes. The completion routine will
  1378. free it.
  1379. --*/
  1380. {
  1381. PIRP pendingIrp = NULL;
  1382. //
  1383. // We need to make sure that we are not completing this irp
  1384. // while we are in this cancel code. If we are completing
  1385. // this irp, the PendingIPGetIPEventRequest will either be
  1386. // NULL or contain next irp.
  1387. //
  1388. if (PendingIPGetIPEventRequest == Irp) {
  1389. pendingIrp = Irp;
  1390. PendingIPGetIPEventRequest = NULL;
  1391. }
  1392. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1393. if (pendingIrp != NULL) {
  1394. pendingIrp->IoStatus.Information = 0;
  1395. pendingIrp->IoStatus.Status = STATUS_CANCELLED;
  1396. IoCompleteRequest(pendingIrp, IO_NETWORK_INCREMENT);
  1397. }
  1398. return;
  1399. }
  1400. void
  1401. CompleteEchoRequest(
  1402. EchoControl *controlBlock,
  1403. IP_STATUS Status,
  1404. void *Data, OPTIONAL
  1405. uint DataSize,
  1406. struct IPOptInfo *OptionInfo OPTIONAL
  1407. )
  1408. /*++
  1409. Routine Description:
  1410. Handles the completion of an ICMP Echo request
  1411. Arguments:
  1412. Context - Pointer to the EchoControl structure for this request.
  1413. Status - The IP status of the transmission.
  1414. Data - A pointer to data returned in the echo reply.
  1415. DataSize - The length of the returned data.
  1416. OptionInfo - A pointer to the IP options in the echo reply.
  1417. Return Value:
  1418. None.
  1419. --*/
  1420. {
  1421. KIRQL oldIrql;
  1422. PIRP irp;
  1423. PIO_STACK_LOCATION irpSp;
  1424. PPENDING_IRP pendingIrp = NULL;
  1425. PPENDING_IRP item;
  1426. PLIST_ENTRY entry;
  1427. ULONG bytesReturned;
  1428. //
  1429. // Find the echo request IRP on the pending list.
  1430. //
  1431. IoAcquireCancelSpinLock(&oldIrql);
  1432. for (entry = PendingEchoList.Flink;
  1433. entry != &PendingEchoList;
  1434. entry = entry->Flink
  1435. ) {
  1436. item = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1437. if (item->Context == controlBlock) {
  1438. pendingIrp = item;
  1439. irp = pendingIrp->Irp;
  1440. IoSetCancelRoutine(irp, NULL);
  1441. RemoveEntryList(entry);
  1442. break;
  1443. }
  1444. }
  1445. IoReleaseCancelSpinLock(oldIrql);
  1446. if (pendingIrp == NULL) {
  1447. //
  1448. // IRP must have been cancelled. PENDING_IRP struct
  1449. // was freed by cancel routine. Free control block.
  1450. //
  1451. CTEFreeMem(controlBlock);
  1452. return;
  1453. }
  1454. irpSp = IoGetCurrentIrpStackLocation(irp);
  1455. #if defined(_WIN64)
  1456. if (IoIs32bitProcess(irp)) {
  1457. bytesReturned = ICMPEchoComplete32(controlBlock, Status, Data, DataSize,
  1458. OptionInfo);
  1459. } else {
  1460. #endif // _WIN64
  1461. bytesReturned = ICMPEchoComplete(controlBlock, Status, Data, DataSize,
  1462. OptionInfo);
  1463. #if defined(_WIN64)
  1464. }
  1465. #endif // _WIN64
  1466. CTEFreeMem(pendingIrp);
  1467. CTEFreeMem(controlBlock);
  1468. //
  1469. // Complete the IRP.
  1470. //
  1471. irp->IoStatus.Information = (ULONG) bytesReturned;
  1472. irp->IoStatus.Status = STATUS_SUCCESS;
  1473. IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
  1474. return;
  1475. }
  1476. void
  1477. CompleteIPSetNTEAddrRequest(
  1478. void *Context,
  1479. IP_STATUS Status
  1480. )
  1481. /*++
  1482. Routine Description:
  1483. Handles the completion of an IP Set Addr request
  1484. Arguments:
  1485. Context - Pointer to the SetAddrControl structure for this request.
  1486. Status - The IP status of the transmission.
  1487. Return Value:
  1488. None.
  1489. --*/
  1490. {
  1491. KIRQL oldIrql;
  1492. PIRP irp;
  1493. PIO_STACK_LOCATION irpSp;
  1494. SetAddrControl *controlBlock;
  1495. PPENDING_IRP pendingIrp = NULL;
  1496. PPENDING_IRP item;
  1497. PLIST_ENTRY entry;
  1498. ULONG bytesReturned;
  1499. Interface *IF;
  1500. controlBlock = (SetAddrControl *) Context;
  1501. //
  1502. // Find the echo request IRP on the pending list.
  1503. //
  1504. IoAcquireCancelSpinLock(&oldIrql);
  1505. for (entry = PendingIPSetNTEAddrList.Flink;
  1506. entry != &PendingIPSetNTEAddrList;
  1507. entry = entry->Flink
  1508. ) {
  1509. item = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1510. if (item->Context == controlBlock) {
  1511. pendingIrp = item;
  1512. irp = pendingIrp->Irp;
  1513. IoSetCancelRoutine(irp, NULL);
  1514. RemoveEntryList(entry);
  1515. break;
  1516. }
  1517. }
  1518. IoReleaseCancelSpinLock(oldIrql);
  1519. if (pendingIrp == NULL) {
  1520. //
  1521. // IRP must have been cancelled. PENDING_IRP struct
  1522. // was freed by cancel routine. Free control block.
  1523. //
  1524. CTEFreeMem(controlBlock);
  1525. return;
  1526. }
  1527. CTEFreeMem(pendingIrp);
  1528. //
  1529. // Complete the IRP.
  1530. //
  1531. irp->IoStatus.Information = 0;
  1532. Status = IPStatusToNTStatus(Status);
  1533. irp->IoStatus.Status = Status;
  1534. CTEFreeMem(controlBlock);
  1535. IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
  1536. return;
  1537. }
  1538. void
  1539. CheckSetAddrRequestOnInterface(
  1540. Interface *IF
  1541. )
  1542. /*++
  1543. Routine Description:
  1544. Handles the completion of an IP Set Addr request on an interface
  1545. that is getting unbound
  1546. Arguments:
  1547. IF - Pointer to the interface whish is getting deleted
  1548. Return Value:
  1549. None.
  1550. --*/
  1551. {
  1552. KIRQL oldIrql;
  1553. PIRP irp;
  1554. PIO_STACK_LOCATION irpSp;
  1555. PPENDING_IRP pendingIrp = NULL;
  1556. PLIST_ENTRY entry, nextEntry;
  1557. LIST_ENTRY completeList;
  1558. SetAddrControl *controlBlock;
  1559. InitializeListHead(&completeList);
  1560. //
  1561. // Find pending set addr requests on this interface
  1562. //
  1563. IoAcquireCancelSpinLock(&oldIrql);
  1564. entry = PendingIPSetNTEAddrList.Flink;
  1565. while (entry != &PendingIPSetNTEAddrList) {
  1566. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1567. controlBlock = pendingIrp->Context;
  1568. if (controlBlock->interface == IF) {
  1569. // remove this entry
  1570. nextEntry = entry->Flink;
  1571. irp = pendingIrp->Irp;
  1572. IoSetCancelRoutine(irp, NULL);
  1573. RemoveEntryList(entry);
  1574. // reinsert this in to completelist
  1575. InsertTailList(&completeList, &(pendingIrp->Linkage));
  1576. entry = nextEntry;
  1577. } else {
  1578. entry = entry->Flink;
  1579. }
  1580. }
  1581. IoReleaseCancelSpinLock(oldIrql);
  1582. //
  1583. // Complete them.
  1584. //
  1585. entry = completeList.Flink;
  1586. while (entry != &completeList) {
  1587. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1588. irp = pendingIrp->Irp;
  1589. entry = entry->Flink;
  1590. //
  1591. // Free the PENDING_IRP structure
  1592. // control block will be freed
  1593. // when addaddrcomplete is called
  1594. CTEFreeMem(pendingIrp);
  1595. //
  1596. // Complete the IRP.
  1597. //
  1598. irp->IoStatus.Information = 0;
  1599. irp->IoStatus.Status = STATUS_CANCELLED;
  1600. IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
  1601. }
  1602. return;
  1603. }
  1604. BOOLEAN
  1605. PrepareArpSendIrpForCancel(
  1606. PIRP Irp,
  1607. PPENDING_IRP PendingIrp
  1608. )
  1609. /*++
  1610. Routine Description:
  1611. Prepares an Arp Send IRP for cancellation.
  1612. Arguments:
  1613. Irp - Pointer to I/O request packet to initialize for cancellation.
  1614. PendingIrp - Pointer to the PENDING_IRP structure for this IRP.
  1615. Return Value:
  1616. TRUE if the IRP was cancelled before this routine was called.
  1617. FALSE otherwise.
  1618. --*/
  1619. {
  1620. BOOLEAN cancelled = TRUE;
  1621. KIRQL oldIrql;
  1622. IoAcquireCancelSpinLock(&oldIrql);
  1623. ASSERT(Irp->CancelRoutine == NULL);
  1624. if (!Irp->Cancel) {
  1625. IoSetCancelRoutine(Irp, CancelArpSendRequest);
  1626. InsertTailList(&PendingArpSendList, &(PendingIrp->Linkage));
  1627. cancelled = FALSE;
  1628. }
  1629. IoReleaseCancelSpinLock(oldIrql);
  1630. return (cancelled);
  1631. }
  1632. void
  1633. CompleteArpResolveRequest(
  1634. void *Context,
  1635. IP_STATUS Status
  1636. )
  1637. /*++
  1638. Routine Description:
  1639. Handles the completion of an ICMP Echo request
  1640. Arguments:
  1641. Context - Pointer to the EchoControl structure for this request.
  1642. Status - The IP status of the transmission.
  1643. Return Value:
  1644. None.
  1645. --*/
  1646. {
  1647. KIRQL oldIrql;
  1648. PIRP irp;
  1649. PIO_STACK_LOCATION irpSp;
  1650. ARPControlBlock *controlBlock;
  1651. PPENDING_IRP pendingIrp = NULL;
  1652. PPENDING_IRP item;
  1653. PLIST_ENTRY entry;
  1654. controlBlock = (ARPControlBlock *) Context;
  1655. //
  1656. // Find the echo request IRP on the pending list.
  1657. //
  1658. IoAcquireCancelSpinLock(&oldIrql);
  1659. for (entry = PendingArpSendList.Flink;
  1660. entry != &PendingArpSendList;
  1661. entry = entry->Flink
  1662. ) {
  1663. item = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1664. if (item->Context == controlBlock) {
  1665. pendingIrp = item;
  1666. irp = pendingIrp->Irp;
  1667. IoSetCancelRoutine(irp, NULL);
  1668. RemoveEntryList(entry);
  1669. break;
  1670. }
  1671. }
  1672. IoReleaseCancelSpinLock(oldIrql);
  1673. if (pendingIrp == NULL) {
  1674. //
  1675. // IRP must have been cancelled. PENDING_IRP struct
  1676. // was freed by cancel routine. Free control block.
  1677. //
  1678. CTEFreeMem(controlBlock);
  1679. return;
  1680. }
  1681. irpSp = IoGetCurrentIrpStackLocation(irp);
  1682. //set the right length
  1683. //
  1684. // Complete the IRP.
  1685. //
  1686. irp->IoStatus.Status = IPStatusToNTStatus(Status);
  1687. irp->IoStatus.Information = controlBlock->PhyAddrLen;
  1688. CTEFreeMem(pendingIrp);
  1689. CTEFreeMem(controlBlock);
  1690. if (Status != IP_SUCCESS) {
  1691. irp->IoStatus.Information = 0;
  1692. }
  1693. IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
  1694. return;
  1695. }
  1696. BOOLEAN
  1697. PrepareEchoIrpForCancel(
  1698. PIRP Irp,
  1699. PPENDING_IRP PendingIrp
  1700. )
  1701. /*++
  1702. Routine Description:
  1703. Prepares an Echo IRP for cancellation.
  1704. Arguments:
  1705. Irp - Pointer to I/O request packet to initialize for cancellation.
  1706. PendingIrp - Pointer to the PENDING_IRP structure for this IRP.
  1707. Return Value:
  1708. TRUE if the IRP was cancelled before this routine was called.
  1709. FALSE otherwise.
  1710. --*/
  1711. {
  1712. BOOLEAN cancelled = TRUE;
  1713. KIRQL oldIrql;
  1714. IoAcquireCancelSpinLock(&oldIrql);
  1715. ASSERT(Irp->CancelRoutine == NULL);
  1716. if (!Irp->Cancel) {
  1717. IoSetCancelRoutine(Irp, CancelEchoRequest);
  1718. InsertTailList(&PendingEchoList, &(PendingIrp->Linkage));
  1719. cancelled = FALSE;
  1720. }
  1721. IoReleaseCancelSpinLock(oldIrql);
  1722. return (cancelled);
  1723. }
  1724. BOOLEAN
  1725. PrepareIPSetNTEAddrIrpForCancel(
  1726. PIRP Irp,
  1727. PPENDING_IRP PendingIrp
  1728. )
  1729. /*++
  1730. Routine Description:
  1731. Prepares an IPSetNTEAddr IRP for cancellation.
  1732. Arguments:
  1733. Irp - Pointer to I/O request packet to initialize for cancellation.
  1734. PendingIrp - Pointer to the PENDING_IRP structure for this IRP.
  1735. Return Value:
  1736. TRUE if the IRP was cancelled before this routine was called.
  1737. FALSE otherwise.
  1738. --*/
  1739. {
  1740. BOOLEAN cancelled = TRUE;
  1741. KIRQL oldIrql;
  1742. IoAcquireCancelSpinLock(&oldIrql);
  1743. ASSERT(Irp->CancelRoutine == NULL);
  1744. if (!Irp->Cancel) {
  1745. IoSetCancelRoutine(Irp, CancelIPSetNTEAddrRequest);
  1746. InsertTailList(&PendingIPSetNTEAddrList, &(PendingIrp->Linkage));
  1747. cancelled = FALSE;
  1748. }
  1749. IoReleaseCancelSpinLock(oldIrql);
  1750. return (cancelled);
  1751. }
  1752. NTSTATUS
  1753. DispatchARPRequest(
  1754. IN PIRP Irp,
  1755. IN PIO_STACK_LOCATION IrpSp
  1756. )
  1757. {
  1758. NTSTATUS ntStatus = STATUS_SUCCESS;
  1759. IP_STATUS ipStatus;
  1760. PPENDING_IRP pendingIrp, item;
  1761. ARPControlBlock *controlBlock;
  1762. IPAddr DestAddress, SourceAddress;
  1763. BOOLEAN cancelled;
  1764. PARP_SEND_REPLY RequestBuffer;
  1765. PLIST_ENTRY entry;
  1766. PAGED_CODE();
  1767. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(ARP_SEND_REPLY)) {
  1768. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  1769. goto arp_error;
  1770. }
  1771. pendingIrp = CTEAllocMemN(sizeof(PENDING_IRP), 'gICT');
  1772. if (pendingIrp == NULL) {
  1773. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1774. goto arp_error;
  1775. }
  1776. controlBlock = CTEAllocMemN(sizeof(ARPControlBlock), 'hICT');
  1777. if (controlBlock == NULL) {
  1778. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1779. CTEFreeMem(pendingIrp);
  1780. goto arp_error;
  1781. }
  1782. pendingIrp->Irp = Irp;
  1783. pendingIrp->FileObject = IrpSp->FileObject;
  1784. pendingIrp->Context = controlBlock;
  1785. controlBlock->PhyAddrLen =
  1786. IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  1787. RequestBuffer = Irp->AssociatedIrp.SystemBuffer;
  1788. controlBlock->PhyAddr = Irp->AssociatedIrp.SystemBuffer;
  1789. controlBlock->next = 0;
  1790. DestAddress = RequestBuffer->DestAddress;
  1791. SourceAddress = RequestBuffer->SrcAddress;
  1792. IoMarkIrpPending(Irp);
  1793. cancelled = PrepareArpSendIrpForCancel(Irp, pendingIrp);
  1794. if (!cancelled) {
  1795. ipStatus = ARPResolve(
  1796. DestAddress,
  1797. SourceAddress,
  1798. controlBlock,
  1799. CompleteArpResolveRequest
  1800. );
  1801. if (ipStatus != IP_PENDING) {
  1802. //
  1803. // An internal error of some kind occurred. Complete the
  1804. // request.
  1805. //
  1806. CompleteArpResolveRequest(controlBlock, ipStatus);
  1807. }
  1808. return STATUS_PENDING;
  1809. }
  1810. //
  1811. // Irp has already been cancelled.
  1812. //
  1813. ntStatus = STATUS_CANCELLED;
  1814. CTEFreeMem(pendingIrp);
  1815. CTEFreeMem(controlBlock);
  1816. arp_error:
  1817. Irp->IoStatus.Information = 0;
  1818. Irp->IoStatus.Status = ntStatus;
  1819. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  1820. return (ntStatus);
  1821. }
  1822. NTSTATUS
  1823. DispatchEchoRequest(
  1824. IN PIRP Irp,
  1825. IN PIO_STACK_LOCATION IrpSp
  1826. )
  1827. /*++
  1828. Routine Description:
  1829. Processes an ICMP request.
  1830. Arguments:
  1831. Irp - Pointer to I/O request packet
  1832. IrpSp - Pointer to the current stack location in the Irp.
  1833. Return Value:
  1834. NTSTATUS -- Indicates whether NT-specific processing of the request was
  1835. successful. The status of the actual request is returned in
  1836. the request buffers.
  1837. --*/
  1838. {
  1839. NTSTATUS ntStatus = STATUS_SUCCESS;
  1840. IP_STATUS ipStatus;
  1841. PPENDING_IRP pendingIrp;
  1842. EchoControl *controlBlock;
  1843. BOOLEAN cancelled;
  1844. PAGED_CODE();
  1845. pendingIrp = CTEAllocMemN(sizeof(PENDING_IRP), 'iICT');
  1846. if (pendingIrp == NULL) {
  1847. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1848. goto echo_error;
  1849. }
  1850. controlBlock = CTEAllocMemN(sizeof(EchoControl), 'jICT');
  1851. if (controlBlock == NULL) {
  1852. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1853. CTEFreeMem(pendingIrp);
  1854. goto echo_error;
  1855. }
  1856. #if defined(_WIN64)
  1857. if (IoIs32bitProcess(Irp)) {
  1858. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1859. sizeof(ICMP_ECHO_REPLY32)) {
  1860. ntStatus = STATUS_INVALID_PARAMETER;
  1861. CTEFreeMem(controlBlock);
  1862. CTEFreeMem(pendingIrp);
  1863. goto echo_error;
  1864. }
  1865. } else {
  1866. #endif // _WIN64
  1867. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1868. sizeof(ICMP_ECHO_REPLY)) {
  1869. ntStatus = STATUS_INVALID_PARAMETER;
  1870. CTEFreeMem(controlBlock);
  1871. CTEFreeMem(pendingIrp);
  1872. goto echo_error;
  1873. }
  1874. #if defined(_WIN64)
  1875. }
  1876. #endif // _WIN64
  1877. pendingIrp->Irp = Irp;
  1878. pendingIrp->FileObject = IrpSp->FileObject;
  1879. pendingIrp->Context = controlBlock;
  1880. controlBlock->ec_starttime = KeQueryPerformanceCounter(NULL);
  1881. controlBlock->ec_replybuf = Irp->AssociatedIrp.SystemBuffer;
  1882. controlBlock->ec_replybuflen =
  1883. IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  1884. controlBlock->ec_src = 0;
  1885. IoMarkIrpPending(Irp);
  1886. cancelled = PrepareEchoIrpForCancel(Irp, pendingIrp);
  1887. if (!cancelled) {
  1888. ipStatus =
  1889. ICMPEchoRequest(Irp->AssociatedIrp.SystemBuffer,
  1890. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  1891. controlBlock, CompleteEchoRequest);
  1892. if (ipStatus != IP_PENDING) {
  1893. //
  1894. // An internal error of some kind occurred. Complete the
  1895. // request.
  1896. //
  1897. CompleteEchoRequest(controlBlock, ipStatus, NULL, 0, NULL);
  1898. }
  1899. return STATUS_PENDING;
  1900. }
  1901. //
  1902. // Irp has already been cancelled.
  1903. //
  1904. ntStatus = STATUS_CANCELLED;
  1905. CTEFreeMem(pendingIrp);
  1906. CTEFreeMem(controlBlock);
  1907. echo_error:
  1908. Irp->IoStatus.Information = 0;
  1909. Irp->IoStatus.Status = ntStatus;
  1910. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  1911. return (ntStatus);
  1912. }
  1913. NTSTATUS
  1914. DispatchIPSetNTEAddrRequest(
  1915. IN PIRP Irp,
  1916. IN PIO_STACK_LOCATION IrpSp
  1917. )
  1918. /*++
  1919. Routine Description:
  1920. Processes an IP Set Addr request.
  1921. Arguments:
  1922. Irp - Pointer to I/O request packet
  1923. IrpSp - Pointer to the current stack location in the Irp.
  1924. Return Value:
  1925. NTSTATUS -- Indicates whether NT-specific processing of the request was
  1926. successful. The status of the actual request is returned in
  1927. the request buffers.
  1928. --*/
  1929. {
  1930. NTSTATUS ntStatus = STATUS_SUCCESS;
  1931. IP_STATUS ipStatus;
  1932. PPENDING_IRP pendingIrp;
  1933. SetAddrControl *controlBlock;
  1934. BOOLEAN cancelled;
  1935. PAGED_CODE();
  1936. pendingIrp = CTEAllocMemN(sizeof(PENDING_IRP), 'kICT');
  1937. if (pendingIrp == NULL) {
  1938. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1939. goto setnteaddr_error;
  1940. }
  1941. controlBlock = CTEAllocMemN(sizeof(SetAddrControl), 'lICT');
  1942. if (controlBlock == NULL) {
  1943. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1944. CTEFreeMem(pendingIrp);
  1945. goto setnteaddr_error;
  1946. }
  1947. RtlZeroMemory(controlBlock, sizeof(SetAddrControl));
  1948. if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_IP_SET_ADDRESS_DUP) {
  1949. controlBlock->bugcheck_on_duplicate = 1;
  1950. }
  1951. pendingIrp->Irp = Irp;
  1952. pendingIrp->FileObject = IrpSp->FileObject;
  1953. pendingIrp->Context = controlBlock;
  1954. IoMarkIrpPending(Irp);
  1955. cancelled = PrepareIPSetNTEAddrIrpForCancel(Irp, pendingIrp);
  1956. if (!cancelled) {
  1957. PIP_SET_ADDRESS_REQUEST request;
  1958. USHORT AddrType = 0;
  1959. request = Irp->AssociatedIrp.SystemBuffer;
  1960. if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_IP_SET_ADDRESS_EX) {
  1961. AddrType = ((PIP_SET_ADDRESS_REQUEST_EX)request)->Type;
  1962. }
  1963. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IP_SET_ADDRESS_REQUEST)) {
  1964. ipStatus = IPSetNTEAddrEx(
  1965. request->Context,
  1966. request->Address,
  1967. request->SubnetMask,
  1968. controlBlock,
  1969. CompleteIPSetNTEAddrRequest,
  1970. AddrType
  1971. );
  1972. } else {
  1973. ipStatus = IP_GENERAL_FAILURE;
  1974. }
  1975. if (ipStatus != IP_PENDING) {
  1976. //
  1977. // A request completed which did not pend.
  1978. //
  1979. CompleteIPSetNTEAddrRequest(controlBlock, ipStatus);
  1980. }
  1981. // Since IoMarkIrpPending was called, return pending.
  1982. return STATUS_PENDING;
  1983. }
  1984. //
  1985. // Irp has already been cancelled.
  1986. //
  1987. ntStatus = STATUS_CANCELLED;
  1988. CTEFreeMem(pendingIrp);
  1989. CTEFreeMem(controlBlock);
  1990. setnteaddr_error:
  1991. Irp->IoStatus.Information = 0;
  1992. Irp->IoStatus.Status = ntStatus;
  1993. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  1994. return (ntStatus);
  1995. }
  1996. NTSTATUS
  1997. DispatchIPGetIPEvent(
  1998. IN PIRP Irp,
  1999. IN PIO_STACK_LOCATION IrpSp
  2000. )
  2001. /*++
  2002. Routine Description:
  2003. Registers the ioctl for the clients to receive the media sense
  2004. events.
  2005. Arguments:
  2006. Irp - Pointer to I/O request packet
  2007. IrpSp - Pointer to the current stack location in the Irp.
  2008. Return Value:
  2009. NTSTATUS -- Indicates whether NT-specific processing of the request was
  2010. successful. The status of the actual request is returned in
  2011. the request buffers.
  2012. --*/
  2013. {
  2014. NTSTATUS ntStatus = STATUS_SUCCESS;
  2015. KIRQL oldIrql;
  2016. //
  2017. // Mark the irp as pending, later when we complete this irp in
  2018. // the same thread, we will unmark it.
  2019. //
  2020. MARK_REQUEST_PENDING(Irp);
  2021. Irp->IoStatus.Information = 0;
  2022. Irp->IoStatus.Status = STATUS_PENDING;
  2023. //
  2024. // Make sure the buffer size is valid.
  2025. //
  2026. #if defined(_WIN64)
  2027. if (IoIs32bitProcess(Irp)) {
  2028. ntStatus = STATUS_NOT_IMPLEMENTED;
  2029. } else {
  2030. #endif // _WIN64
  2031. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  2032. sizeof(IP_GET_IP_EVENT_RESPONSE)) {
  2033. ntStatus = STATUS_INVALID_PARAMETER;
  2034. } else {
  2035. IoAcquireCancelSpinLock(&oldIrql);
  2036. ASSERT(Irp->CancelRoutine == NULL);
  2037. //
  2038. // Check if the irp is already cancelled or not.
  2039. //
  2040. if (Irp->Cancel) {
  2041. ntStatus = STATUS_CANCELLED;
  2042. //
  2043. // We only allow one irp pending.
  2044. //
  2045. } else if (PendingIPGetIPEventRequest) {
  2046. ntStatus = STATUS_DEVICE_BUSY;
  2047. } else {
  2048. IoSetCancelRoutine(Irp, CancelIPGetIPEventRequest);
  2049. PendingIPGetIPEventRequest = Irp;
  2050. ntStatus = STATUS_SUCCESS;
  2051. }
  2052. IoReleaseCancelSpinLock(oldIrql);
  2053. if (STATUS_SUCCESS == ntStatus) {
  2054. //
  2055. // IPGetIPEventEx will either complete the request
  2056. // or return pending.
  2057. //
  2058. ntStatus = IPGetIPEventEx(Irp, IrpSp);
  2059. if (ntStatus == STATUS_CANCELLED) {
  2060. //
  2061. // Since the cancel routine has been installed at this point,
  2062. // the IRP will have already been completed, and can no longer
  2063. // be referenced.
  2064. //
  2065. ntStatus = STATUS_PENDING;
  2066. }
  2067. }
  2068. }
  2069. #if defined(_WIN64)
  2070. }
  2071. #endif // _WIN64
  2072. if (ntStatus != STATUS_PENDING) {
  2073. UNMARK_REQUEST_PENDING(Irp);
  2074. Irp->IoStatus.Status = ntStatus;
  2075. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  2076. }
  2077. return (ntStatus);
  2078. }
  2079. VOID
  2080. CancelIPEnableMediaSenseRequest(
  2081. IN PDEVICE_OBJECT Device,
  2082. IN PIRP Irp
  2083. )
  2084. {
  2085. CTELockHandle TableHandle;
  2086. IoSetCancelRoutine(Irp, NULL);
  2087. IoReleaseCancelSpinLock(Irp->CancelIrql);
  2088. // Decrement the mediasense-enabled reference count.
  2089. // If the count drops to zero media-sense is disabled.
  2090. CTEGetLock(&RouteTableLock.Lock, &TableHandle);
  2091. RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
  2092. IPEnableMediaSense(TRUE, &TableHandle);
  2093. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  2094. Irp->IoStatus.Information = 0;
  2095. Irp->IoStatus.Status = STATUS_CANCELLED;
  2096. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  2097. }
  2098. NTSTATUS
  2099. IPDisableMediaSenseRequest(
  2100. PIRP Irp,
  2101. PIO_STACK_LOCATION IrpSp
  2102. )
  2103. {
  2104. KIRQL OldIrql;
  2105. NTSTATUS status;
  2106. CTELockHandle TableHandle;
  2107. IoAcquireCancelSpinLock(&OldIrql);
  2108. IoMarkIrpPending(Irp);
  2109. IoSetCancelRoutine(Irp, CancelIPEnableMediaSenseRequest);
  2110. if (Irp->Cancel) {
  2111. IoSetCancelRoutine(Irp, NULL);
  2112. status = STATUS_CANCELLED;
  2113. Irp->IoStatus.Information = 0;
  2114. IoReleaseCancelSpinLock(OldIrql);
  2115. } else {
  2116. // Increment the mediasense-enabled reference count.
  2117. // When the count rises above zero media-sense is enabled.
  2118. // This reference will be dropped when the IRP is cancelled.
  2119. CTEGetLockAtDPC(&RouteTableLock.Lock, &TableHandle);
  2120. Irp->Tail.Overlay.DriverContext[0] = IrpSp->FileObject;
  2121. InsertTailList(&PendingMediaSenseRequestList, &Irp->Tail.Overlay.ListEntry);
  2122. Irp->IoStatus.Information = 0;
  2123. IoReleaseCancelSpinLock(DISPATCH_LEVEL);
  2124. IPEnableMediaSense(FALSE, &OldIrql);
  2125. CTEFreeLock(&RouteTableLock.Lock, OldIrql);
  2126. status = STATUS_PENDING;
  2127. }
  2128. return status;
  2129. }
  2130. NTSTATUS
  2131. IPEnableMediaSenseRequest(
  2132. PIRP Irp,
  2133. PIO_STACK_LOCATION IrpSp
  2134. )
  2135. {
  2136. PLIST_ENTRY entry;
  2137. KIRQL CancelIrql;
  2138. int RefCount;
  2139. CTELockHandle TableHandle;
  2140. // Locate the pending IRP for the request corresponding to the caller's
  2141. // disable-request. Drop the mediasense-enabled reference-count, complete
  2142. // the corresponding IRP, and tell the caller what the reference-count's
  2143. // current value is.
  2144. IoAcquireCancelSpinLock(&CancelIrql);
  2145. CTEGetLockAtDPC(&RouteTableLock.Lock, &TableHandle);
  2146. for (entry = PendingMediaSenseRequestList.Flink;
  2147. entry != &PendingMediaSenseRequestList;
  2148. entry = entry->Flink
  2149. ) {
  2150. PIRP EnableIrp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
  2151. if (EnableIrp->Tail.Overlay.DriverContext[0] == IrpSp->FileObject &&
  2152. EnableIrp->Overlay.AsynchronousParameters.UserApcContext ==
  2153. *(PVOID *) Irp->AssociatedIrp.SystemBuffer) {
  2154. RemoveEntryList(&EnableIrp->Tail.Overlay.ListEntry);
  2155. IoSetCancelRoutine(EnableIrp, NULL);
  2156. EnableIrp->IoStatus.Status = STATUS_SUCCESS;
  2157. EnableIrp->IoStatus.Information = 0;
  2158. *(PULONG) Irp->AssociatedIrp.SystemBuffer = (ULONG) DisableMediaSense+1;
  2159. Irp->IoStatus.Information = sizeof(ULONG);
  2160. IoReleaseCancelSpinLock(DISPATCH_LEVEL);
  2161. IoCompleteRequest(EnableIrp, IO_NETWORK_INCREMENT);
  2162. RefCount = IPEnableMediaSense(TRUE, &CancelIrql);
  2163. CTEFreeLock(&RouteTableLock.Lock, CancelIrql);
  2164. return STATUS_SUCCESS;
  2165. }
  2166. }
  2167. CTEFreeLockFromDPC(&RouteTableLock.Lock, TableHandle);
  2168. IoReleaseCancelSpinLock(CancelIrql);
  2169. return STATUS_INVALID_PARAMETER;
  2170. }