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.

1788 lines
61 KiB

  1. /*++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. bind.c
  5. Abstract:
  6. Contains AfdBind for binding an endpoint to a transport address.
  7. Author:
  8. David Treadwell (davidtr) 25-Feb-1992
  9. Revision History:
  10. Vadim Eydelman (vadime) 1999 - C_ROOT endpoint handling,
  11. exclusive access endpoints.
  12. --*/
  13. #include "afdp.h"
  14. NTSTATUS
  15. AfdRestartGetAddress (
  16. IN PDEVICE_OBJECT DeviceObject,
  17. IN PIRP Irp,
  18. IN PVOID Context
  19. );
  20. NTSTATUS
  21. AfdRestartBindGetAddress (
  22. IN PDEVICE_OBJECT DeviceObject,
  23. IN PIRP Irp,
  24. IN PVOID Context
  25. );
  26. BOOLEAN
  27. AfdIsAddressInUse (
  28. PAFD_ENDPOINT Endpoint,
  29. BOOLEAN OtherProcessesOnly
  30. );
  31. PFILE_OBJECT
  32. AfdGetAddressFileReference (
  33. PAFD_ENDPOINT Endpoint
  34. );
  35. #ifdef ALLOC_PRAGMA
  36. #pragma alloc_text( PAGE, AfdBind )
  37. #pragma alloc_text( PAGE, AfdIsAddressInUse )
  38. #pragma alloc_text( PAGE, AfdGetAddress )
  39. #pragma alloc_text( PAGEAFD, AfdAreTransportAddressesEqual )
  40. #pragma alloc_text( PAGEAFD, AfdGetAddressFileReference )
  41. #pragma alloc_text( PAGEAFD, AfdRestartGetAddress )
  42. #pragma alloc_text( PAGEAFD, AfdRestartBindGetAddress )
  43. #if NOT_YET
  44. NTSTATUS
  45. AfdStealClosedEnpointAddress (
  46. PAFD_ENDPOINT Endpoint,
  47. NTSTATUS Status
  48. );
  49. #pragma alloc_text( PAGE, AfdStealClosedEnpointAddress )
  50. #endif // NOT_YET
  51. #endif
  52. NTSTATUS
  53. FASTCALL
  54. AfdBind (
  55. IN PIRP Irp,
  56. IN PIO_STACK_LOCATION IrpSp
  57. )
  58. /*++
  59. Routine Description:
  60. Handles the IOCTL_AFD_BIND IOCTL.
  61. Arguments:
  62. Irp - Pointer to I/O request packet.
  63. IrpSp - pointer to the IO stack location to use for this request.
  64. Return Value:
  65. NTSTATUS -- Indicates whether the request was successfully queued.
  66. --*/
  67. {
  68. NTSTATUS status;
  69. ULONG shareAccess, afdShareAccess;
  70. ULONG tdiAddressLength;
  71. PAFD_ENDPOINT endpoint;
  72. PSECURITY_DESCRIPTOR sd = NULL; // Use endpoint sd for secure transports
  73. PSECURITY_DESCRIPTOR oldSd;
  74. ULONG options;
  75. PTRANSPORT_ADDRESS localAddress;
  76. HANDLE addressHandle;
  77. OBJECT_ATTRIBUTES objectAttributes;
  78. IO_STATUS_BLOCK iosb;
  79. PFILE_FULL_EA_INFORMATION eaInfo;
  80. ULONG eaLength;
  81. // Local buffer to avoid memory allocation
  82. PCHAR eaBuffer[sizeof(FILE_FULL_EA_INFORMATION) - 1 +
  83. TDI_TRANSPORT_ADDRESS_LENGTH + 1 +
  84. AFD_MAX_FAST_TRANSPORT_ADDRESS];
  85. PAGED_CODE( );
  86. //
  87. // Initialize returned parameter
  88. //
  89. Irp->IoStatus.Information = 0;
  90. //
  91. // Need to have output buffer at least as long as input buffer
  92. // to pass the address that was actually used by the transport
  93. // back.
  94. //
  95. if ( (IrpSp->Parameters.DeviceIoControl.InputBufferLength<
  96. (ULONG)FIELD_OFFSET (AFD_BIND_INFO, Address.Address)) ||
  97. IrpSp->Parameters.DeviceIoControl.OutputBufferLength<
  98. (ULONG)FIELD_OFFSET (TDI_ADDRESS_INFO, Address.Address[0].Address) ||
  99. (IrpSp->Parameters.DeviceIoControl.OutputBufferLength-
  100. (ULONG)FIELD_OFFSET (TDI_ADDRESS_INFO, Address) <
  101. IrpSp->Parameters.DeviceIoControl.InputBufferLength-
  102. (ULONG)FIELD_OFFSET (AFD_BIND_INFO, Address) ) ) {
  103. status = STATUS_INVALID_PARAMETER;
  104. goto complete;
  105. }
  106. //
  107. // Set up local pointers.
  108. //
  109. endpoint = IrpSp->FileObject->FsContext;
  110. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  111. localAddress = NULL;
  112. addressHandle = NULL;
  113. tdiAddressLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength
  114. - FIELD_OFFSET (AFD_BIND_INFO, Address);
  115. //
  116. // This is a state change operation, there should be no other
  117. // state changes going at the same time.
  118. //
  119. if (!AFD_START_STATE_CHANGE (endpoint, AfdEndpointStateBound)) {
  120. status = STATUS_INVALID_PARAMETER;
  121. goto complete;
  122. }
  123. //
  124. // Bomb off if this endpoind already has address associated with it
  125. //
  126. if ( endpoint->State != AfdEndpointStateOpen ) {
  127. status = STATUS_ADDRESS_ALREADY_ASSOCIATED;
  128. goto complete_wrong_state;
  129. }
  130. //
  131. // Remember SD (so we can destroy it later) since it shares the storage
  132. // with device object field
  133. //
  134. oldSd = endpoint->SecurityDescriptor;
  135. AFD_W4_INIT status = STATUS_SUCCESS;
  136. try {
  137. PAFD_BIND_INFO bindInfo;
  138. bindInfo = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  139. if (Irp->RequestorMode!=KernelMode) {
  140. ProbeForRead (IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
  141. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  142. PROBE_ALIGNMENT (AFD_BIND_INFO));
  143. }
  144. //
  145. // Allocate space for local address
  146. //
  147. localAddress = AFD_ALLOCATE_POOL_WITH_QUOTA (
  148. NonPagedPool,
  149. tdiAddressLength,
  150. AFD_LOCAL_ADDRESS_POOL_TAG
  151. );
  152. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets POOL_RAISE_IF_ALLOCATION_FAILURE flag
  153. ASSERT ( localAddress != NULL );
  154. afdShareAccess = bindInfo->ShareAccess;
  155. RtlMoveMemory(
  156. localAddress,
  157. &bindInfo->Address,
  158. tdiAddressLength
  159. );
  160. //
  161. // Validate internal consistency of the transport address structure.
  162. // Note that we HAVE to do this after copying since the malicious
  163. // application can change the content of the buffer on us any time
  164. // and our check will be bypassed.
  165. //
  166. if ((localAddress->TAAddressCount!=1) ||
  167. (LONG)tdiAddressLength<
  168. FIELD_OFFSET (TRANSPORT_ADDRESS,
  169. Address[0].Address[localAddress->Address[0].AddressLength])) {
  170. status = STATUS_INVALID_PARAMETER;
  171. goto complete_state_change;
  172. }
  173. if (IoAllocateMdl (Irp->UserBuffer,
  174. IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  175. FALSE, // SecondaryBuffer
  176. TRUE, // ChargeQuota
  177. Irp // Irp
  178. )==NULL) {
  179. status = STATUS_INSUFFICIENT_RESOURCES;
  180. goto complete_state_change;
  181. }
  182. MmProbeAndLockPages (Irp->MdlAddress,
  183. Irp->RequestorMode,
  184. IoWriteAccess);
  185. if (MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority)==NULL) {
  186. status = STATUS_INSUFFICIENT_RESOURCES;
  187. goto complete_state_change;
  188. }
  189. }
  190. except (AFD_EXCEPTION_FILTER(status)) {
  191. ASSERT (NT_ERROR (status));
  192. goto complete_state_change;
  193. }
  194. //
  195. // Make sure we have a valid provider info structure.
  196. // (we do not take any locks because this is read access only
  197. // and additional verification will be performed inside of the
  198. // routine under the lock).
  199. // If not, attempt to get it from provider
  200. // (this can happen if when the socket was created, transport
  201. // was not loaded yet)
  202. //
  203. if (!endpoint->TransportInfo->InfoValid) {
  204. status = AfdGetTransportInfo (
  205. &endpoint->TransportInfo->TransportDeviceName,
  206. &endpoint->TransportInfo);
  207. if (!NT_SUCCESS (status)) {
  208. goto complete_state_change;
  209. }
  210. //
  211. // Must be valid because we got success.
  212. //
  213. ASSERT (endpoint->TransportInfo->InfoValid);
  214. }
  215. //
  216. // Cache service flags for quick determination of provider characteristics
  217. // such as bufferring and messaging. Do it even if provider structure was
  218. // valid already because in may have become valid between the time the
  219. // flags were set and we checked it here. In any case update to the same
  220. // value won't hurt.
  221. //
  222. endpoint->TdiServiceFlags = endpoint->TransportInfo->ProviderInfo.ServiceFlags;
  223. //
  224. // Attempt to take ownership of the address.
  225. // We have to do this before we start looking for a conflict
  226. // so if someone does it in parallel with us, will see him or
  227. // he sees us.
  228. //
  229. ASSERT (endpoint->LocalAddress==NULL);
  230. endpoint->LocalAddress = localAddress;
  231. endpoint->LocalAddressLength = tdiAddressLength;
  232. if (IS_TDI_ADDRESS_SECURITY(endpoint) &&
  233. endpoint->SecurityDescriptor!=NULL) {
  234. sd = endpoint->SecurityDescriptor;
  235. shareAccess = 0;
  236. }
  237. else
  238. {
  239. //
  240. // There are three possibilities here.
  241. //
  242. switch (afdShareAccess) {
  243. case AFD_NORMALADDRUSE:
  244. if (IS_TDI_ADDRESS_SECURITY(endpoint)) {
  245. shareAccess = 0;
  246. sd = &AfdEmptySd;
  247. }
  248. else {
  249. //
  250. // This is the default. Application did not request to reuse
  251. // the address that is already owned by someone else, so we
  252. // have to check against all addresses that we know about.
  253. // There is still a possibility that another TDI client has
  254. // this address in exclusive use, so the transport can reject
  255. // our request even if we succeed. Note that we cannot relegate
  256. // this check to the transport because we request shared access
  257. // to the transport address: we cannot request exclusive access
  258. // because this is not what application asked for.
  259. //
  260. if (AfdIsAddressInUse (endpoint, FALSE)) {
  261. status = STATUS_SHARING_VIOLATION;
  262. goto complete_state_change;
  263. }
  264. shareAccess = FILE_SHARE_READ|FILE_SHARE_WRITE;
  265. }
  266. break;
  267. case AFD_REUSEADDRESS:
  268. //
  269. // We are asked to reuse the existing address
  270. //
  271. if (IS_TDI_ADDRESS_SECURITY(endpoint)) {
  272. sd = &AfdEmptySd;
  273. }
  274. shareAccess = FILE_SHARE_READ|FILE_SHARE_WRITE;
  275. break;
  276. case AFD_WILDCARDADDRESS:
  277. //
  278. // Application is binding to a wildcard port, so we leave the
  279. // decision with the transport.
  280. //
  281. if (IS_TDI_ADDRESS_SECURITY(endpoint)) {
  282. shareAccess = 0;
  283. sd = &AfdEmptySd;
  284. }
  285. else {
  286. shareAccess = FILE_SHARE_READ|FILE_SHARE_WRITE;
  287. }
  288. break;
  289. case AFD_EXCLUSIVEADDRUSE:
  290. //
  291. // Application has requested exclisuve access to the address.
  292. // We let the transport to decide by requesting exclusive access.
  293. //
  294. shareAccess = 0;
  295. break;
  296. default:
  297. ASSERT (!"Invalid share access");
  298. status = STATUS_INVALID_PARAMETER;
  299. goto complete_state_change;
  300. }
  301. }
  302. //
  303. // Set create options.
  304. //
  305. options = IO_NO_PARAMETER_CHECKING;
  306. if (IS_TDI_FORCE_ACCESS_CHECK(endpoint)) {
  307. options |= IO_FORCE_ACCESS_CHECK;
  308. }
  309. else {
  310. //
  311. // If this is an open of a raw address, fail if user is
  312. // not an admin and transport does not perform security
  313. // checking itself.
  314. //
  315. if ( endpoint->afdRaw && !AfdDisableRawSecurity) {
  316. if (!endpoint->AdminAccessGranted) {
  317. status = STATUS_ACCESS_DENIED;
  318. goto complete_state_change;
  319. }
  320. }
  321. }
  322. //
  323. // Allocate memory to hold the EA buffer we'll use to specify the
  324. // transport address to NtCreateFile.
  325. //
  326. eaLength = sizeof(FILE_FULL_EA_INFORMATION) - 1 +
  327. TDI_TRANSPORT_ADDRESS_LENGTH + 1 +
  328. tdiAddressLength;
  329. if (eaLength<=sizeof (eaBuffer)) {
  330. eaInfo = (PVOID)eaBuffer;
  331. }
  332. else {
  333. try {
  334. #if DBG
  335. eaInfo = AFD_ALLOCATE_POOL_WITH_QUOTA(
  336. NonPagedPool,
  337. eaLength,
  338. AFD_EA_POOL_TAG
  339. );
  340. #else
  341. eaInfo = AFD_ALLOCATE_POOL_WITH_QUOTA(
  342. PagedPool,
  343. eaLength,
  344. AFD_EA_POOL_TAG
  345. );
  346. #endif
  347. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets POOL_RAISE_IF_ALLOCATION_FAILURE flag
  348. ASSERT ( eaInfo != NULL );
  349. }
  350. except (EXCEPTION_EXECUTE_HANDLER) {
  351. status = GetExceptionCode ();
  352. goto complete_state_change;
  353. }
  354. }
  355. //
  356. // Initialize the EA.
  357. //
  358. eaInfo->NextEntryOffset = 0;
  359. eaInfo->Flags = 0;
  360. eaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
  361. eaInfo->EaValueLength = (USHORT)tdiAddressLength;
  362. RtlMoveMemory(
  363. eaInfo->EaName,
  364. TdiTransportAddress,
  365. TDI_TRANSPORT_ADDRESS_LENGTH + 1
  366. );
  367. RtlMoveMemory(
  368. &eaInfo->EaName[TDI_TRANSPORT_ADDRESS_LENGTH + 1],
  369. localAddress,
  370. tdiAddressLength
  371. );
  372. //
  373. // Prepare for opening the address object.
  374. // We ask to create a kernel handle which is
  375. // the handle in the context of the system process
  376. // so that application cannot close it on us while
  377. // we are creating and referencing it.
  378. //
  379. InitializeObjectAttributes(
  380. &objectAttributes,
  381. &endpoint->TransportInfo->TransportDeviceName,
  382. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, // attributes
  383. NULL, // RootDirectory
  384. sd // SecurityDescriptor
  385. );
  386. ASSERT (endpoint->AddressHandle==NULL);
  387. //
  388. // We specify MAXIMUM_ALLOWED access for the following reasons:
  389. // * transport objects are file objects, but regular file access
  390. // permissions don't really make sense - it is not really
  391. // meaningfull to say be able to receive and not send or vice
  392. // versa;
  393. // * we need to specify some access mask to get the IO manager and
  394. // possibly the transport to perform an access check to verify
  395. // that current caller has access, hence MAXIMUM_ALLOWED;
  396. // * the handle and the object is going to be used by AFD in kernel
  397. // mode - no access check will be performed anyway, so it doesn't
  398. // matter what we actually get;
  399. // * MAXIMUM_ALLOWED is not perfect in terms of performance since
  400. // security monitor is going to walk the whole DACL, it would be
  401. // better to specify a specific mask;
  402. // * currently IO manager allows the World only EXECUTE access to
  403. // transport device objects BEFORE any further restrictions imposed
  404. // by a particular transport so we can in theory specify
  405. // just GENERIC_EXECUTE, however, it is not clear if this is
  406. // going to remain valid forever;
  407. //
  408. status = IoCreateFile(
  409. &endpoint->AddressHandle,
  410. MAXIMUM_ALLOWED, // DesiredAccess (see above).
  411. &objectAttributes,
  412. &iosb, // returned status information.
  413. 0, // block size (unused).
  414. 0, // file attributes.
  415. shareAccess, // share access
  416. FILE_CREATE, // create disposition.
  417. 0, // create options.
  418. eaInfo, // EaBuffer
  419. eaLength, // EaLength
  420. CreateFileTypeNone, // CreateFileType
  421. NULL, // ExtraCreateParameters
  422. options
  423. );
  424. if (eaInfo!=(PVOID)eaBuffer) {
  425. AFD_FREE_POOL (eaInfo, AFD_EA_POOL_TAG);
  426. }
  427. if ( !NT_SUCCESS(status) ) {
  428. if ((status==STATUS_SHARING_VIOLATION) ||
  429. (status==STATUS_ADDRESS_ALREADY_EXISTS)) {
  430. if (afdShareAccess==AFD_REUSEADDRESS) {
  431. //
  432. // Map error code if application requested address
  433. // reuse, but the transport denied it (apparently due to
  434. // other client having this address for its exclusive use).
  435. //
  436. status = STATUS_ACCESS_DENIED;
  437. }
  438. }
  439. goto complete_state_change;
  440. }
  441. #if DBG
  442. {
  443. NTSTATUS status1;
  444. OBJECT_HANDLE_FLAG_INFORMATION handleInfo;
  445. handleInfo.Inherit = FALSE;
  446. handleInfo.ProtectFromClose = TRUE;
  447. status1 = ZwSetInformationObject (
  448. endpoint->AddressHandle,
  449. ObjectHandleFlagInformation,
  450. &handleInfo,
  451. sizeof (handleInfo)
  452. );
  453. ASSERT (NT_SUCCESS (status1));
  454. }
  455. #endif
  456. AfdRecordAddrOpened();
  457. //
  458. // Get a pointer to the file object of the address.
  459. //
  460. status = ObReferenceObjectByHandle(
  461. endpoint->AddressHandle,
  462. 0L, // DesiredAccess - we don't really need
  463. // one for kernel mode caller.
  464. NULL,
  465. KernelMode,
  466. (PVOID *)&endpoint->AddressFileObject,
  467. NULL
  468. );
  469. if ( !NT_SUCCESS(status) ) {
  470. goto complete_state_change;
  471. }
  472. AfdRecordAddrRef();
  473. //
  474. // Now open the handle for our caller.
  475. // If transport does not support new TDI_SERVICE_FORCE_ACCESS_CHECK_FLAG
  476. // we get the maximum possible access for the handle so that helper
  477. // DLL can do what it wants with it. Of course this compromises the
  478. // security, but we can't enforce it without the transport cooperation.
  479. //
  480. status = ObOpenObjectByPointer(
  481. endpoint->AddressFileObject,
  482. OBJ_CASE_INSENSITIVE,
  483. NULL,
  484. MAXIMUM_ALLOWED,
  485. *IoFileObjectType,
  486. (KPROCESSOR_MODE)((endpoint->TdiServiceFlags&TDI_SERVICE_FORCE_ACCESS_CHECK)
  487. ? Irp->RequestorMode
  488. : KernelMode),
  489. &addressHandle
  490. );
  491. if ( !NT_SUCCESS(status) ) {
  492. goto complete_state_change;
  493. }
  494. //
  495. // Remember the device object to which we need to give requests for
  496. // this address object. We can't just use the
  497. // fileObject->DeviceObject pointer because there may be a device
  498. // attached to the transport protocol.
  499. //
  500. endpoint->AddressDeviceObject =
  501. IoGetRelatedDeviceObject( endpoint->AddressFileObject );
  502. #ifdef _AFD_VARIABLE_STACK_
  503. if (endpoint->AddressDeviceObject->StackSize!=endpoint->TransportInfo->StackSize &&
  504. endpoint->AddressDeviceObject->StackSize > AfdTdiStackSize) {
  505. AfdFixTransportEntryPointsForBigStackSize (
  506. endpoint->TransportInfo,
  507. endpoint->AddressDeviceObject->StackSize);
  508. }
  509. #endif //_AFD_VARIABLE_STACK
  510. //
  511. // Set up indication handlers on the address object. Only set up
  512. // appropriate event handlers--don't set unnecessary event handlers.
  513. //
  514. status = AfdSetEventHandler(
  515. endpoint->AddressFileObject,
  516. TDI_EVENT_ERROR,
  517. (PVOID)AfdErrorEventHandler,
  518. endpoint
  519. );
  520. #if DBG
  521. if ( !NT_SUCCESS(status) ) {
  522. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  523. "AfdBind: Transport %*ls failed setting TDI_EVENT_ERROR: %lx\n",
  524. endpoint->TransportInfo->TransportDeviceName.Length/2,
  525. endpoint->TransportInfo->TransportDeviceName.Buffer,
  526. status ));
  527. }
  528. #endif
  529. if ( IS_DGRAM_ENDPOINT(endpoint) ) {
  530. endpoint->EventsActive = AFD_POLL_SEND;
  531. IF_DEBUG(EVENT_SELECT) {
  532. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  533. "AfdBind: Endp %08lX, Active %08lX\n",
  534. endpoint,
  535. endpoint->EventsActive
  536. ));
  537. }
  538. status = AfdSetEventHandler(
  539. endpoint->AddressFileObject,
  540. TDI_EVENT_RECEIVE_DATAGRAM,
  541. (PVOID)AfdReceiveDatagramEventHandler,
  542. endpoint
  543. );
  544. #if DBG
  545. if ( !NT_SUCCESS(status) ) {
  546. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_WARNING_LEVEL,
  547. "AfdBind: Transport %*ls failed setting TDI_EVENT_RECEIVE_DATAGRAM: %lx\n",
  548. endpoint->TransportInfo->TransportDeviceName.Length/2,
  549. endpoint->TransportInfo->TransportDeviceName.Buffer,
  550. status ));
  551. }
  552. #endif
  553. status = AfdSetEventHandler(
  554. endpoint->AddressFileObject,
  555. TDI_EVENT_ERROR_EX,
  556. (PVOID)AfdErrorExEventHandler,
  557. endpoint
  558. );
  559. if ( !NT_SUCCESS(status)) {
  560. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  561. "AfdBind: Transport %*ls failed setting TDI_EVENT_ERROR_EX: %lx\n",
  562. endpoint->TransportInfo->TransportDeviceName.Length/2,
  563. endpoint->TransportInfo->TransportDeviceName.Buffer,
  564. status ));
  565. }
  566. //
  567. // Since we don't use a spinlock for performance and AfdCleanup
  568. // relies upon endpoint->State != AfdEndpointStateOpen to
  569. // determine whether or not to remove TDI event handlers and
  570. // call AfdUnbind, we must guarantee that all of the above
  571. // instructions have completed and weren't reordered before we
  572. // set the state. If AfdCleanup winds up missing the state
  573. // transition, it's no big deal as the application would have
  574. // to be behaving rather badly for this race condition, and TDI
  575. // will eventually recycle the address (just not immediately).
  576. //
  577. // However, the current code calls a function just prior to
  578. // this assignment in all cases so a memory fence is unecessary.
  579. // We'll leave it commented out until future revisions of the
  580. // code add write instructions we depend on which could be
  581. // reordered. We could also use InterlockedExchange for this
  582. // on endpoint->State.
  583. //
  584. // KeMemoryBarrier();
  585. //
  586. //
  587. // Remember that the endpoint has been bound to a transport address.
  588. // (this is the fact even though the call below can fail for some reason)
  589. //
  590. endpoint->State = AfdEndpointStateBound;
  591. } else {
  592. status = AfdSetEventHandler(
  593. endpoint->AddressFileObject,
  594. TDI_EVENT_DISCONNECT,
  595. (PVOID)AfdDisconnectEventHandler,
  596. endpoint
  597. );
  598. #if DBG
  599. if ( !NT_SUCCESS(status) ) {
  600. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_WARNING_LEVEL,
  601. "AfdBind: Transport %*ls failed setting TDI_EVENT_DISCONNECT: %lx\n",
  602. endpoint->TransportInfo->TransportDeviceName.Length/2,
  603. endpoint->TransportInfo->TransportDeviceName.Buffer,
  604. status ));
  605. }
  606. #endif
  607. if ( IS_TDI_BUFFERRING(endpoint) ) {
  608. status = AfdSetEventHandler(
  609. endpoint->AddressFileObject,
  610. TDI_EVENT_RECEIVE,
  611. (PVOID)AfdReceiveEventHandler,
  612. endpoint
  613. );
  614. #if DBG
  615. if ( !NT_SUCCESS(status) ) {
  616. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_WARNING_LEVEL,
  617. "AfdBind: Transport %*ls failed setting TDI_EVENT_RECEIVE: %lx\n",
  618. endpoint->TransportInfo->TransportDeviceName.Length/2,
  619. endpoint->TransportInfo->TransportDeviceName.Buffer,
  620. status ));
  621. }
  622. #endif
  623. //
  624. // PROBLEM: Why don't we check for this
  625. // if (IS_TDI_EXPEDITED (endpoint)) {
  626. status = AfdSetEventHandler(
  627. endpoint->AddressFileObject,
  628. TDI_EVENT_RECEIVE_EXPEDITED,
  629. (PVOID)AfdReceiveExpeditedEventHandler,
  630. endpoint
  631. );
  632. #if DBG
  633. if ( !NT_SUCCESS(status) ) {
  634. DbgPrint( "AfdBind: Transport %*ls failed setting TDI_EVENT_RECEIVE_EXPEDITED: %lx\n",
  635. endpoint->TransportInfo->TransportDeviceName.Length/2,
  636. endpoint->TransportInfo->TransportDeviceName.Buffer,
  637. status );
  638. }
  639. #endif
  640. // }
  641. status = AfdSetEventHandler(
  642. endpoint->AddressFileObject,
  643. TDI_EVENT_SEND_POSSIBLE,
  644. (PVOID)AfdSendPossibleEventHandler,
  645. endpoint
  646. );
  647. #if DBG
  648. if ( !NT_SUCCESS(status) ) {
  649. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_WARNING_LEVEL,
  650. "AfdBind: Transport %*ls failed setting TDI_EVENT_SEND_POSSIBLE: %lx\n",
  651. endpoint->TransportInfo->TransportDeviceName.Length/2,
  652. endpoint->TransportInfo->TransportDeviceName.Buffer,
  653. status ));
  654. }
  655. #endif
  656. } else {
  657. status = AfdSetEventHandler(
  658. endpoint->AddressFileObject,
  659. TDI_EVENT_RECEIVE,
  660. (PVOID)AfdBReceiveEventHandler,
  661. endpoint
  662. );
  663. #if DBG
  664. if ( !NT_SUCCESS(status) ) {
  665. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_WARNING_LEVEL,
  666. "AfdBind: Transport %*ls failed setting TDI_EVENT_RECEIVE: %lx\n",
  667. endpoint->TransportInfo->TransportDeviceName.Length/2,
  668. endpoint->TransportInfo->TransportDeviceName.Buffer,
  669. status ));
  670. }
  671. #endif
  672. if (IS_TDI_EXPEDITED (endpoint)) {
  673. status = AfdSetEventHandler(
  674. endpoint->AddressFileObject,
  675. TDI_EVENT_RECEIVE_EXPEDITED,
  676. (PVOID)AfdBReceiveExpeditedEventHandler,
  677. endpoint
  678. );
  679. #if DBG
  680. if ( !NT_SUCCESS(status) ) {
  681. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  682. "AfdBind: Transport %*ls failed setting TDI_EVENT_RECEIVE_EXPEDITED: %lx\n",
  683. endpoint->TransportInfo->TransportDeviceName.Length/2,
  684. endpoint->TransportInfo->TransportDeviceName.Buffer,
  685. status ));
  686. }
  687. #endif
  688. }
  689. if (!AfdDisableChainedReceive) {
  690. status = AfdSetEventHandler(
  691. endpoint->AddressFileObject,
  692. TDI_EVENT_CHAINED_RECEIVE,
  693. (PVOID)AfdBChainedReceiveEventHandler,
  694. endpoint
  695. );
  696. if ( !NT_SUCCESS(status) ) {
  697. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  698. "AfdBind: Transport %*ls failed setting TDI_EVENT_CHAINED_RECEIVE: %lx\n",
  699. endpoint->TransportInfo->TransportDeviceName.Length/2,
  700. endpoint->TransportInfo->TransportDeviceName.Buffer,
  701. status ));
  702. }
  703. }
  704. }
  705. if (IS_CROOT_ENDPOINT(endpoint)) {
  706. PAFD_CONNECTION connection;
  707. //
  708. // Create root connection
  709. // This one will be used to send data to all
  710. // leaf nodes (what if there are none -> the transport
  711. // should handle this.
  712. //
  713. status = AfdCreateConnection(
  714. endpoint->TransportInfo,
  715. endpoint->AddressHandle,
  716. IS_TDI_BUFFERRING(endpoint),
  717. endpoint->InLine,
  718. endpoint->OwningProcess,
  719. &connection
  720. );
  721. if (!NT_SUCCESS(status)) {
  722. goto complete_state_change;
  723. }
  724. //
  725. // Set up a referenced pointer from the connection to the endpoint.
  726. // Note that we set up the connection's pointer to the endpoint
  727. // BEFORE the endpoint's pointer to the connection so that AfdPoll
  728. // doesn't try to back reference the endpoint from the connection.
  729. //
  730. REFERENCE_ENDPOINT( endpoint );
  731. connection->Endpoint = endpoint;
  732. //
  733. // Remember that this is now a connecting type of endpoint, and set
  734. // up a pointer to the connection in the endpoint. This is
  735. // implicitly a referenced pointer.
  736. //
  737. endpoint->Common.VirtualCircuit.Connection = connection;
  738. endpoint->Type = AfdBlockTypeVcConnecting;
  739. //
  740. // The root connection is marked as connected immediately upon
  741. // creation. See the comment above
  742. //
  743. AfdAddConnectedReference (connection);
  744. //
  745. // Since we don't use a spinlock for performance and AfdCleanup
  746. // relies upon endpoint->State != AfdEndpointStateOpen to
  747. // determine whether or not to remove TDI event handlers and
  748. // call AfdUnbind, we must guarantee that all of the above
  749. // instructions have completed and weren't reordered before we
  750. // set the state. If AfdCleanup winds up missing the state
  751. // transition, it's no big deal as the application would have
  752. // to be behaving rather badly for this race condition, and TDI
  753. // will eventually recycle the address (just not immediately).
  754. //
  755. // However, the current code calls a function just prior to
  756. // this assignment in all cases so a memory fence is unecessary.
  757. // We'll leave it commented out until future revisions of the
  758. // code add write instructions we depend on which could be
  759. // reordered. We could also use InterlockedExchange for this
  760. // on endpoint->State.
  761. //
  762. // KeMemoryBarrier();
  763. //
  764. endpoint->State = AfdEndpointStateConnected;
  765. connection->State = AfdConnectionStateConnected;
  766. ASSERT( IS_TDI_BUFFERRING(endpoint) == connection->TdiBufferring );
  767. } else {
  768. //
  769. // Since we don't use a spinlock for performance and AfdCleanup
  770. // relies upon endpoint->State != AfdEndpointStateOpen to
  771. // determine whether or not to remove TDI event handlers and
  772. // call AfdUnbind, we must guarantee that all of the above
  773. // instructions have completed and weren't reordered before we
  774. // set the state. If AfdCleanup winds up missing the state
  775. // transition, it's no big deal as the application would have
  776. // to be behaving rather badly for this race condition, and TDI
  777. // will eventually recycle the address (just not immediately).
  778. //
  779. // However, the current code calls a function just prior to
  780. // this assignment in all cases so a memory fence is unecessary.
  781. // We'll leave it commented out until future revisions of the
  782. // code add write instructions we depend on which could be
  783. // reordered. We could also use InterlockedExchange for this
  784. // on endpoint->State.
  785. //
  786. // KeMemoryBarrier();
  787. //
  788. //
  789. // Remember that the endpoint has been bound to a transport address.
  790. // (this is the fact even though the call below can fail for some reason)
  791. //
  792. endpoint->State = AfdEndpointStateBound;
  793. }
  794. }
  795. AFD_END_STATE_CHANGE (endpoint);
  796. //
  797. // endpoint->State is no longer Open. Dispose of the SD
  798. //
  799. if (oldSd != NULL) {
  800. ObDereferenceSecurityDescriptor( oldSd, 1 );
  801. }
  802. TdiBuildQueryInformation(
  803. Irp,
  804. endpoint->AddressDeviceObject,
  805. endpoint->AddressFileObject,
  806. AfdRestartBindGetAddress,
  807. endpoint,
  808. TDI_QUERY_ADDRESS_INFO,
  809. Irp->MdlAddress
  810. );
  811. //
  812. // Save address handle to use in completion routine
  813. //
  814. IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = addressHandle;
  815. IF_DEBUG(BIND) {
  816. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  817. "AfdBind: endpoint at %p (address at %p, address file at %p).\n",
  818. endpoint,
  819. endpoint->LocalAddress,
  820. endpoint->AddressFileObject ));
  821. }
  822. status = AfdIoCallDriver( endpoint, endpoint->AddressDeviceObject, Irp );
  823. return status;
  824. complete_state_change:
  825. if (endpoint->AddressFileObject!=NULL) {
  826. ObDereferenceObject (endpoint->AddressFileObject);
  827. endpoint->AddressFileObject = NULL;
  828. ASSERT (endpoint->AddressHandle!=NULL);
  829. }
  830. //
  831. // Restore SD (might have been over-written by AddressDeviceObject)
  832. // We're still holding endpoint state change lock.
  833. //
  834. ASSERT (endpoint->State == AfdEndpointStateOpen);
  835. endpoint->SecurityDescriptor = oldSd;
  836. if (endpoint->AddressHandle!=NULL) {
  837. #if DBG
  838. {
  839. NTSTATUS status1;
  840. OBJECT_HANDLE_FLAG_INFORMATION handleInfo;
  841. handleInfo.Inherit = FALSE;
  842. handleInfo.ProtectFromClose = FALSE;
  843. status1 = ZwSetInformationObject (
  844. endpoint->AddressHandle,
  845. ObjectHandleFlagInformation,
  846. &handleInfo,
  847. sizeof (handleInfo)
  848. );
  849. ASSERT (NT_SUCCESS (status1));
  850. }
  851. #endif
  852. ZwClose(endpoint->AddressHandle);
  853. endpoint->AddressHandle = NULL;
  854. ASSERT (localAddress!=NULL);
  855. }
  856. if (localAddress!=NULL) {
  857. //
  858. // Need to have exclusive access to make sure no one
  859. // uses it (to compare) as we are going to free it.
  860. // We'll use a local variable to free memory
  861. //
  862. //
  863. // Make sure the thread in which we execute cannot get
  864. // suspeneded in APC while we own the global resource.
  865. //
  866. KeEnterCriticalRegion ();
  867. ExAcquireResourceExclusiveLite( AfdResource, TRUE);
  868. endpoint->LocalAddress = NULL;
  869. endpoint->LocalAddressLength = 0;
  870. ExReleaseResourceLite( AfdResource );
  871. KeLeaveCriticalRegion ();
  872. AFD_FREE_POOL (
  873. localAddress,
  874. AFD_LOCAL_ADDRESS_POOL_TAG
  875. );
  876. }
  877. complete_wrong_state:
  878. AFD_END_STATE_CHANGE (endpoint);
  879. //
  880. // Free MDL here as IO system can't do it if it is
  881. // not locked.
  882. //
  883. if (Irp->MdlAddress!=NULL) {
  884. if (Irp->MdlAddress->MdlFlags & MDL_PAGES_LOCKED) {
  885. MmUnlockPages (Irp->MdlAddress);
  886. }
  887. IoFreeMdl (Irp->MdlAddress);
  888. Irp->MdlAddress = NULL;
  889. }
  890. complete:
  891. Irp->IoStatus.Status = status;
  892. IoCompleteRequest( Irp, AfdPriorityBoost );
  893. return status;
  894. } // AfdBind
  895. NTSTATUS
  896. AfdRestartBindGetAddress (
  897. IN PDEVICE_OBJECT DeviceObject,
  898. IN PIRP Irp,
  899. IN PVOID Context
  900. )
  901. {
  902. NTSTATUS status;
  903. PAFD_ENDPOINT endpoint = Context;
  904. UNREFERENCED_PARAMETER (DeviceObject);
  905. ASSERT (IS_AFD_ENDPOINT_TYPE (endpoint));
  906. //
  907. // If the request succeeded, save the address in the endpoint so
  908. // we can use it to handle address sharing.
  909. //
  910. if ( NT_SUCCESS(Irp->IoStatus.Status) ) {
  911. ULONG addressLength;
  912. //
  913. // First determine the length of the address by walking the MDL
  914. // chain.
  915. //
  916. //
  917. // We cannot have a chain here.
  918. //
  919. ASSERT( Irp->MdlAddress != NULL);
  920. ASSERT( Irp->MdlAddress->Next == NULL );
  921. //
  922. // If the new address is longer than the original address, allocate
  923. // a new local address buffer. The +4 accounts for the ActivityCount
  924. // field that is returned by a query address but is not part
  925. // of a TRANSPORT_ADDRESS.
  926. //
  927. // This cannot happen, in any case msafd does not retry if buffer is
  928. // insuffucient, so application perceives this as failure to bind
  929. // or get address.
  930. //
  931. addressLength = MmGetMdlByteCount (Irp->MdlAddress) - FIELD_OFFSET (TDI_ADDRESS_INFO, Address);
  932. if (addressLength>endpoint->LocalAddressLength) {
  933. addressLength = (ULONG)Irp->IoStatus.Information - FIELD_OFFSET (TDI_ADDRESS_INFO, Address);
  934. }
  935. if ( addressLength <= endpoint->LocalAddressLength) {
  936. status = TdiCopyMdlToBuffer(
  937. Irp->MdlAddress,
  938. FIELD_OFFSET (TDI_ADDRESS_INFO, Address),
  939. endpoint->LocalAddress,
  940. 0,
  941. addressLength,
  942. &endpoint->LocalAddressLength
  943. );
  944. ASSERT( NT_SUCCESS(status) );
  945. }
  946. else {
  947. DbgPrint ("AfdRestartBindGetAddress: Endpoint %p transport returned"
  948. " address is longer than the original one.\n",
  949. endpoint);
  950. ASSERT (FALSE);
  951. }
  952. }
  953. else {
  954. //
  955. //
  956. //
  957. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_WARNING_LEVEL,
  958. "AfdRestartBindGetAddress: Transport %*ls failed get address query, status %lx.\n",
  959. endpoint->TransportInfo->TransportDeviceName.Length/2,
  960. endpoint->TransportInfo->TransportDeviceName.Buffer,
  961. Irp->IoStatus.Status));
  962. }
  963. //
  964. // If pending has been returned for this irp then mark the current
  965. // stack as pending.
  966. //
  967. if ( Irp->PendingReturned ) {
  968. IoMarkIrpPending( Irp );
  969. }
  970. //
  971. // Retreive and return address handle in the information field
  972. //
  973. Irp->IoStatus.Information =
  974. (ULONG_PTR)IoGetCurrentIrpStackLocation (Irp)->Parameters.DeviceIoControl.Type3InputBuffer;
  975. AfdCompleteOutstandingIrp( endpoint, Irp );
  976. return STATUS_SUCCESS;
  977. } // AfdRestartBindGetAddress
  978. NTSTATUS
  979. FASTCALL
  980. AfdGetAddress (
  981. IN PIRP Irp,
  982. IN PIO_STACK_LOCATION IrpSp
  983. )
  984. /*++
  985. Routine Description:
  986. Handles the IOCTL_AFD_BIND IOCTL.
  987. Arguments:
  988. Irp - Pointer to I/O request packet.
  989. IrpSp - pointer to the IO stack location to use for this request.
  990. Return Value:
  991. NTSTATUS -- Indicates whether the request was successfully queued.
  992. --*/
  993. {
  994. NTSTATUS status;
  995. PAFD_ENDPOINT endpoint;
  996. PAFD_CONNECTION connection;
  997. PFILE_OBJECT fileObject;
  998. PDEVICE_OBJECT deviceObject;
  999. PAGED_CODE( );
  1000. Irp->IoStatus.Information = 0;
  1001. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength<
  1002. (ULONG) FIELD_OFFSET(TDI_ADDRESS_INFO, Address.Address[0].Address)) {
  1003. status = STATUS_INVALID_PARAMETER;
  1004. goto complete;
  1005. }
  1006. AFD_W4_INIT status = STATUS_SUCCESS;
  1007. try {
  1008. if (IoAllocateMdl (Irp->UserBuffer,
  1009. IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  1010. FALSE, // SecondaryBuffer
  1011. TRUE, // ChargeQuota
  1012. Irp // Irp
  1013. )==NULL) {
  1014. status = STATUS_INSUFFICIENT_RESOURCES;
  1015. goto complete;
  1016. }
  1017. MmProbeAndLockPages (Irp->MdlAddress,
  1018. Irp->RequestorMode,
  1019. IoWriteAccess);
  1020. if (MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority)==NULL) {
  1021. status = STATUS_INSUFFICIENT_RESOURCES;
  1022. goto complete;
  1023. }
  1024. }
  1025. except (AFD_EXCEPTION_FILTER (status)) {
  1026. ASSERT (NT_ERROR (status));
  1027. goto complete;
  1028. }
  1029. //
  1030. // Make sure that the endpoint is in the correct state.
  1031. //
  1032. endpoint = IrpSp->FileObject->FsContext;
  1033. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  1034. if ( endpoint->State!=AfdEndpointStateBound &&
  1035. endpoint->State != AfdEndpointStateConnected ) {
  1036. status = STATUS_INVALID_PARAMETER;
  1037. goto complete;
  1038. }
  1039. //
  1040. // If the endpoint is connected, use the connection's file object.
  1041. // Otherwise, use the address file object. Don't use the connection
  1042. // file object if this is a Netbios endpoint because NETBT cannot
  1043. // support this TDI feature.
  1044. //
  1045. if ( endpoint->LocalAddress->Address[0].AddressType !=
  1046. TDI_ADDRESS_TYPE_NETBIOS &&
  1047. endpoint->Type == AfdBlockTypeVcConnecting &&
  1048. endpoint->State == AfdEndpointStateConnected &&
  1049. ((connection=AfdGetConnectionReferenceFromEndpoint (endpoint)) != NULL)
  1050. ) {
  1051. ASSERT( connection->Type == AfdBlockTypeConnection );
  1052. fileObject = connection->FileObject;
  1053. deviceObject = connection->DeviceObject;
  1054. //
  1055. // Reference file object so it cannot go away even if
  1056. // connection is disassociated in TransmitFile (REUSE)
  1057. // and closed.
  1058. //
  1059. ObReferenceObject (fileObject);
  1060. DEREFERENCE_CONNECTION (connection);
  1061. }
  1062. //
  1063. // Reference address file object under the lock so it cannot go away
  1064. // in TransmitFile (REUSE).
  1065. //
  1066. else if ((fileObject=AfdGetAddressFileReference (endpoint))!=NULL) {
  1067. fileObject = endpoint->AddressFileObject;
  1068. deviceObject = IoGetRelatedDeviceObject (fileObject);
  1069. }
  1070. else {
  1071. status = STATUS_INVALID_PARAMETER;
  1072. goto complete;
  1073. }
  1074. //
  1075. // Set up the query info to the TDI provider.
  1076. //
  1077. TdiBuildQueryInformation(
  1078. Irp,
  1079. deviceObject,
  1080. fileObject,
  1081. AfdRestartGetAddress,
  1082. fileObject,
  1083. TDI_QUERY_ADDRESS_INFO,
  1084. Irp->MdlAddress
  1085. );
  1086. //
  1087. // Call the TDI provider to get the address.
  1088. //
  1089. return AfdIoCallDriver( endpoint, deviceObject, Irp );
  1090. complete:
  1091. if (Irp->MdlAddress!=NULL) {
  1092. if (Irp->MdlAddress->MdlFlags & MDL_PAGES_LOCKED) {
  1093. MmUnlockPages (Irp->MdlAddress);
  1094. }
  1095. IoFreeMdl (Irp->MdlAddress);
  1096. Irp->MdlAddress = NULL;
  1097. }
  1098. Irp->IoStatus.Status = status;
  1099. IoCompleteRequest( Irp, AfdPriorityBoost );
  1100. return status;
  1101. } // AfdGetAddress
  1102. PFILE_OBJECT
  1103. AfdGetAddressFileReference (
  1104. PAFD_ENDPOINT Endpoint
  1105. )
  1106. {
  1107. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1108. PFILE_OBJECT fileObject;
  1109. AfdAcquireSpinLock (&Endpoint->SpinLock, &lockHandle);
  1110. fileObject = Endpoint->AddressFileObject;
  1111. if (fileObject!=NULL) {
  1112. ObReferenceObject (fileObject);
  1113. }
  1114. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  1115. return fileObject;
  1116. }
  1117. NTSTATUS
  1118. AfdRestartGetAddress (
  1119. IN PDEVICE_OBJECT DeviceObject,
  1120. IN PIRP Irp,
  1121. IN PVOID Context
  1122. )
  1123. {
  1124. NTSTATUS status;
  1125. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
  1126. PAFD_ENDPOINT endpoint = irpSp->FileObject->FsContext;
  1127. PFILE_OBJECT fileObject = Context;
  1128. UNREFERENCED_PARAMETER (DeviceObject);
  1129. ASSERT (IS_AFD_ENDPOINT_TYPE( endpoint ));
  1130. //
  1131. // If the request succeeded, save the address in the endpoint so
  1132. // we can use it to handle address sharing.
  1133. // Avoid updating accepting endpoint since they share address
  1134. // with listening endpoint.
  1135. //
  1136. if ( NT_SUCCESS(Irp->IoStatus.Status) &&
  1137. (endpoint->Type!=AfdBlockTypeVcConnecting ||
  1138. endpoint->Common.VcConnecting.ListenEndpoint==NULL)) {
  1139. ULONG addressLength;
  1140. //
  1141. // First determine the length of the address by walking the MDL
  1142. // chain.
  1143. //
  1144. //
  1145. // We cannot have a chain here.
  1146. //
  1147. ASSERT( Irp->MdlAddress != NULL);
  1148. ASSERT( Irp->MdlAddress->Next == NULL );
  1149. //
  1150. // If the new address is longer than the original address, allocate
  1151. // a new local address buffer. The +4 accounts for the ActivityCount
  1152. // field that is returned by a query address but is not part
  1153. // of a TRANSPORT_ADDRESS.
  1154. //
  1155. // This cannot happen, in any case msafd does not retry if buffer is
  1156. // insuffucient, so application perceives this as failure to bind
  1157. // or get address.
  1158. //
  1159. addressLength = MmGetMdlByteCount (Irp->MdlAddress) - FIELD_OFFSET (TDI_ADDRESS_INFO, Address);
  1160. if (addressLength>endpoint->LocalAddressLength) {
  1161. addressLength = (ULONG)Irp->IoStatus.Information - FIELD_OFFSET (TDI_ADDRESS_INFO, Address);
  1162. }
  1163. if ( addressLength <= endpoint->LocalAddressLength) {
  1164. status = TdiCopyMdlToBuffer(
  1165. Irp->MdlAddress,
  1166. FIELD_OFFSET (TDI_ADDRESS_INFO, Address),
  1167. endpoint->LocalAddress,
  1168. 0,
  1169. addressLength,
  1170. &endpoint->LocalAddressLength
  1171. );
  1172. ASSERT( NT_SUCCESS(status) );
  1173. }
  1174. else {
  1175. DbgPrint ("AfdRestartGetAddress: Endpoint %p transport returned"
  1176. " address is longer than the original one.\n",
  1177. endpoint);
  1178. ASSERT (FALSE);
  1179. }
  1180. }
  1181. //
  1182. // If pending has been returned for this irp then mark the current
  1183. // stack as pending.
  1184. //
  1185. if ( Irp->PendingReturned ) {
  1186. IoMarkIrpPending( Irp );
  1187. }
  1188. AfdCompleteOutstandingIrp( endpoint, Irp );
  1189. ObDereferenceObject (fileObject);
  1190. return STATUS_SUCCESS;
  1191. } // AfdRestartGetAddress
  1192. const CHAR ZeroNodeAddress[6]={0};
  1193. const CHAR ZeroIP6Address[16]={0};
  1194. BOOLEAN
  1195. AfdAreTransportAddressesEqual (
  1196. IN PTRANSPORT_ADDRESS EndpointAddress,
  1197. IN ULONG EndpointAddressLength,
  1198. IN PTRANSPORT_ADDRESS RequestAddress,
  1199. IN ULONG RequestAddressLength,
  1200. IN BOOLEAN HonorWildcardIpPortInEndpointAddress
  1201. )
  1202. {
  1203. //
  1204. // Make sure we can safely access the address type and length fields
  1205. //
  1206. if ((EndpointAddressLength<(ULONG)FIELD_OFFSET (TRANSPORT_ADDRESS,Address[0].Address))
  1207. || (RequestAddressLength<(ULONG)FIELD_OFFSET (TRANSPORT_ADDRESS,Address[0].Address)) ) {
  1208. return FALSE;
  1209. }
  1210. if ( EndpointAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IP &&
  1211. RequestAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IP ) {
  1212. TDI_ADDRESS_IP UNALIGNED *ipEndpointAddress;
  1213. TDI_ADDRESS_IP UNALIGNED *ipRequestAddress;
  1214. //
  1215. // They are both IP addresses. If the ports are the same, and
  1216. // the IP addresses are or _could_be_ the same, then the addresses
  1217. // are equal. The "cound be" part is true if either IP address
  1218. // is 0, the "wildcard" IP address.
  1219. //
  1220. ipEndpointAddress = (TDI_ADDRESS_IP UNALIGNED *)&EndpointAddress->Address[0].Address[0];
  1221. ipRequestAddress = (TDI_ADDRESS_IP UNALIGNED *)&RequestAddress->Address[0].Address[0];
  1222. if ( (EndpointAddressLength>=(ULONG)FIELD_OFFSET (TA_IP_ADDRESS, Address[0].Address[0].sin_zero)) &&
  1223. (RequestAddressLength>=(ULONG)FIELD_OFFSET (TA_IP_ADDRESS, Address[0].Address[0].sin_zero)) &&
  1224. ( ipEndpointAddress->sin_port == ipRequestAddress->sin_port ||
  1225. ( HonorWildcardIpPortInEndpointAddress &&
  1226. ipEndpointAddress->sin_port == 0 ) ) &&
  1227. ( ipEndpointAddress->in_addr == ipRequestAddress->in_addr ||
  1228. ipEndpointAddress->in_addr == 0 || ipRequestAddress->in_addr == 0 ) ) {
  1229. return TRUE;
  1230. }
  1231. //
  1232. // The addresses are not equal.
  1233. //
  1234. return FALSE;
  1235. }
  1236. if ( EndpointAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IP6 &&
  1237. RequestAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IP6 ) {
  1238. TDI_ADDRESS_IP6 UNALIGNED *ipEndpointAddress;
  1239. TDI_ADDRESS_IP6 UNALIGNED *ipRequestAddress;
  1240. C_ASSERT (sizeof (ZeroIP6Address)==sizeof (ipEndpointAddress->sin6_addr));
  1241. //
  1242. // They are both IPv6 addresses. If the ports are the same, and
  1243. // the IPv6 addresses are or _could_be_ the same, then the addresses
  1244. // are equal. The "could be" part is true if either IPv6 address
  1245. // is the unspecified IPv6 address.
  1246. //
  1247. ipEndpointAddress = (TDI_ADDRESS_IP6 UNALIGNED *)&EndpointAddress->Address[0].Address;
  1248. ipRequestAddress = (TDI_ADDRESS_IP6 UNALIGNED *)&RequestAddress->Address[0].Address;
  1249. if ( (EndpointAddressLength>=sizeof (TA_IP6_ADDRESS)) &&
  1250. (RequestAddressLength>=sizeof (TA_IP6_ADDRESS)) &&
  1251. (ipEndpointAddress->sin6_port == ipRequestAddress->sin6_port ||
  1252. ( HonorWildcardIpPortInEndpointAddress &&
  1253. ipEndpointAddress->sin6_port == 0 ) ) &&
  1254. ( RtlEqualMemory(&ipEndpointAddress->sin6_addr,
  1255. &ipRequestAddress->sin6_addr,
  1256. sizeof (ipEndpointAddress->sin6_addr)) ||
  1257. RtlEqualMemory(&ipEndpointAddress->sin6_addr,
  1258. ZeroIP6Address,
  1259. sizeof (ipEndpointAddress->sin6_addr)) ||
  1260. RtlEqualMemory(&ipRequestAddress->sin6_addr,
  1261. ZeroIP6Address,
  1262. sizeof (ipEndpointAddress->sin6_addr)) ) ) {
  1263. return TRUE;
  1264. }
  1265. //
  1266. // The addresses are not equal.
  1267. //
  1268. return FALSE;
  1269. }
  1270. if ( EndpointAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IPX &&
  1271. RequestAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IPX ) {
  1272. TDI_ADDRESS_IPX UNALIGNED *ipxEndpointAddress;
  1273. TDI_ADDRESS_IPX UNALIGNED *ipxRequestAddress;
  1274. C_ASSERT (sizeof (ZeroNodeAddress)==sizeof (ipxEndpointAddress->NodeAddress));
  1275. ipxEndpointAddress = (TDI_ADDRESS_IPX UNALIGNED *)&EndpointAddress->Address[0].Address[0];
  1276. ipxRequestAddress = (TDI_ADDRESS_IPX UNALIGNED *)&RequestAddress->Address[0].Address[0];
  1277. //
  1278. // They are both IPX addresses. Check the network addresses
  1279. // first--if they don't match and both != 0, the addresses
  1280. // are different.
  1281. //
  1282. if ( (EndpointAddressLength<sizeof (TA_IPX_ADDRESS)) ||
  1283. (RequestAddressLength<sizeof (TA_IPX_ADDRESS)) ||
  1284. ( ipxEndpointAddress->NetworkAddress != ipxRequestAddress->NetworkAddress &&
  1285. ipxEndpointAddress->NetworkAddress != 0 &&
  1286. ipxRequestAddress->NetworkAddress != 0 )) {
  1287. return FALSE;
  1288. }
  1289. //
  1290. // Now check the node addresses. Again, if they don't match
  1291. // and neither is 0, the addresses don't match.
  1292. //
  1293. ASSERT( ZeroNodeAddress[0] == 0 );
  1294. ASSERT( ZeroNodeAddress[1] == 0 );
  1295. ASSERT( ZeroNodeAddress[2] == 0 );
  1296. ASSERT( ZeroNodeAddress[3] == 0 );
  1297. ASSERT( ZeroNodeAddress[4] == 0 );
  1298. ASSERT( ZeroNodeAddress[5] == 0 );
  1299. if ( !RtlEqualMemory(
  1300. ipxEndpointAddress->NodeAddress,
  1301. ipxRequestAddress->NodeAddress,
  1302. 6 ) &&
  1303. !RtlEqualMemory(
  1304. ipxEndpointAddress->NodeAddress,
  1305. ZeroNodeAddress,
  1306. 6 ) &&
  1307. !RtlEqualMemory(
  1308. ipxRequestAddress->NodeAddress,
  1309. ZeroNodeAddress,
  1310. 6 ) ) {
  1311. return FALSE;
  1312. }
  1313. //
  1314. // Finally, make sure the socket numbers match.
  1315. //
  1316. if ( ipxEndpointAddress->Socket != ipxRequestAddress->Socket ) {
  1317. return FALSE;
  1318. }
  1319. return TRUE;
  1320. }
  1321. //
  1322. // If either address is not of a known address type, then do a
  1323. // simple memory compare. (Don't go out of bounds on either
  1324. // structure).
  1325. //
  1326. if (RequestAddressLength>EndpointAddressLength)
  1327. RequestAddressLength = EndpointAddressLength;
  1328. return (BOOLEAN)(EndpointAddressLength == RtlCompareMemory(
  1329. EndpointAddress,
  1330. RequestAddress,
  1331. RequestAddressLength ) );
  1332. } // AfdAreTransportAddressesEqual
  1333. BOOLEAN
  1334. AfdIsAddressInUse (
  1335. PAFD_ENDPOINT Endpoint,
  1336. BOOLEAN OtherProcessesOnly
  1337. )
  1338. {
  1339. PLIST_ENTRY listEntry;
  1340. BOOLEAN res = FALSE;
  1341. PAGED_CODE ();
  1342. //
  1343. // We use shared access to the resource because we only need to make
  1344. // sure that endpoint list is not modified while we are accessing it
  1345. // and existing local addresses are not removed (both of these
  1346. // operations are performed under exclusive access).
  1347. //
  1348. //
  1349. // Make sure the thread in which we execute cannot get
  1350. // suspeneded in APC while we own the global resource.
  1351. //
  1352. KeEnterCriticalRegion ();
  1353. ExAcquireResourceSharedLite( AfdResource, TRUE );
  1354. //
  1355. // Walk the global list of endpoints,
  1356. // and compare this address againat the address on each endpoint.
  1357. //
  1358. for ( listEntry = AfdEndpointListHead.Flink;
  1359. listEntry != &AfdEndpointListHead;
  1360. listEntry = listEntry->Flink ) {
  1361. PAFD_ENDPOINT compareEndpoint;
  1362. compareEndpoint = CONTAINING_RECORD(
  1363. listEntry,
  1364. AFD_ENDPOINT,
  1365. GlobalEndpointListEntry
  1366. );
  1367. ASSERT( IS_AFD_ENDPOINT_TYPE( compareEndpoint ) );
  1368. //
  1369. // Check whether the endpoint has a local address, whether
  1370. // the endpoint has been disconnected, whether the
  1371. // endpoint is in the process of closing, and whether
  1372. // it represents accepted connection. If any of these
  1373. // is true, don't compare addresses with this endpoint.
  1374. //
  1375. if (compareEndpoint!=Endpoint &&
  1376. compareEndpoint->LocalAddress != NULL &&
  1377. ( (compareEndpoint->DisconnectMode &
  1378. (AFD_PARTIAL_DISCONNECT_SEND |
  1379. AFD_ABORTIVE_DISCONNECT) ) == 0 ) &&
  1380. (compareEndpoint->State != AfdEndpointStateClosing) &&
  1381. ((compareEndpoint->State != AfdEndpointStateConnected)
  1382. || (compareEndpoint->Type!=AfdBlockTypeVcConnecting)
  1383. || (compareEndpoint->Common.VcConnecting.ListenEndpoint==NULL)) &&
  1384. (!OtherProcessesOnly ||
  1385. compareEndpoint->OwningProcess!=Endpoint->OwningProcess)
  1386. ) {
  1387. //
  1388. // Compare the bits in the endpoint's address and the
  1389. // address we're attempting to bind to. Note that we
  1390. // also compare the transport device names on the
  1391. // endpoints, as it is legal to bind to the same address
  1392. // on different transports (e.g. bind to same port in
  1393. // TCP and UDP). We can just compare the transport
  1394. // device name pointers because unique names are stored
  1395. // globally.
  1396. //
  1397. if ( Endpoint->TransportInfo ==
  1398. compareEndpoint->TransportInfo &&
  1399. compareEndpoint->LocalAddressLength == Endpoint->LocalAddressLength &&
  1400. AfdAreTransportAddressesEqual(
  1401. compareEndpoint->LocalAddress,
  1402. compareEndpoint->LocalAddressLength,
  1403. Endpoint->LocalAddress,
  1404. Endpoint->LocalAddressLength,
  1405. FALSE
  1406. ) ) {
  1407. //
  1408. // The addresses are equal.
  1409. //
  1410. res = TRUE;
  1411. break;
  1412. }
  1413. }
  1414. }
  1415. ExReleaseResourceLite( AfdResource );
  1416. KeLeaveCriticalRegion ();
  1417. return res;
  1418. }
  1419. #if NOT_YET
  1420. NTSTATUS
  1421. AfdStealClosedEnpointAddress (
  1422. PAFD_ENDPOINT Endpoint,
  1423. NTSTATUS Status
  1424. )
  1425. /*++
  1426. Routine Description:
  1427. Allows reuse of address consumed by listening socket being closed
  1428. This a workaround the problem posed by TDI semantics. The TDI client
  1429. must maintain an address object for connections accepted on such object
  1430. to stay open. The prevents creation of another address object with
  1431. the same address although from the transport point of view there
  1432. is no conflict.
  1433. Arguments:
  1434. Endpoint - endpoint that failed address object creation due to a conflict
  1435. Status - original failure status
  1436. Return Value:
  1437. STATUS_SUCCESS - the candidate for reuse was found
  1438. Original status passed - no listening endpoint with matching address was found
  1439. Other - failure to create handle for some other reason.
  1440. --*/
  1441. {
  1442. PLIST_ENTRY listEntry;
  1443. PAGED_CODE ();
  1444. //
  1445. // We use shared access to the resource because we only need to make
  1446. // sure that endpoint list is not modified while we are accessing it
  1447. // and existing local addresses are not removed (both of these
  1448. // operations are performed under exclusive access).
  1449. //
  1450. //
  1451. // Make sure the thread in which we execute cannot get
  1452. // suspeneded in APC while we own the global resource.
  1453. //
  1454. KeEnterCriticalRegion ();
  1455. ExAcquireResourceSharedLite( AfdResource, TRUE );
  1456. //
  1457. // Walk the global list of endpoints,
  1458. // and compare this address againat the address on each endpoint.
  1459. //
  1460. for ( listEntry = AfdEndpointListHead.Flink;
  1461. listEntry != &AfdEndpointListHead;
  1462. listEntry = listEntry->Flink ) {
  1463. PAFD_ENDPOINT compareEndpoint;
  1464. compareEndpoint = CONTAINING_RECORD(
  1465. listEntry,
  1466. AFD_ENDPOINT,
  1467. GlobalEndpointListEntry
  1468. );
  1469. ASSERT( IS_AFD_ENDPOINT_TYPE( compareEndpoint ) );
  1470. if (compareEndpoint!=Endpoint &&
  1471. compareEndpoint->EndpointCleanedUp &&
  1472. compareEndpoint->TransportInfo==
  1473. Endpoint->TransportInfo &&
  1474. compareEndpoint->Listening &&
  1475. compareEndpoint->AddressHandle!=NULL &&
  1476. compareEndpoint->LocalAddressLength == Endpoint->LocalAddressLength &&
  1477. AfdAreTransportAddressesEqual(
  1478. compareEndpoint->LocalAddress,
  1479. compareEndpoint->LocalAddressLength,
  1480. Endpoint->LocalAddress,
  1481. Endpoint->LocalAddressLength,
  1482. FALSE
  1483. )) {
  1484. //
  1485. // There is a theoretical security issue here.
  1486. // We open a handle from kernel mode and thus
  1487. // bypass the security checks which were done by the
  1488. // original client when calling IoCreateFile.
  1489. //
  1490. Status = ObOpenObjectByPointer(
  1491. compareEndpoint->AddressFileObject,
  1492. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  1493. NULL,
  1494. MAXIMUM_ALLOWED,
  1495. *IoFileObjectType,
  1496. KernelMode,
  1497. &Endpoint->AddressHandle
  1498. );
  1499. break;
  1500. }
  1501. }
  1502. ExReleaseResourceLite( AfdResource );
  1503. KeLeaveCriticalRegion ();
  1504. return Status;
  1505. }
  1506. #endif // NOT_YET