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.

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