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.

1838 lines
52 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. query.c
  5. Abstract:
  6. This module contains code which performs the following TDI services:
  7. o TdiQueryInformation
  8. o TdiSetInformation
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. //
  16. // Remove the warning -- this is defined in windef also.
  17. //
  18. #ifdef FAR
  19. #undef FAR
  20. #endif
  21. #include <windef.h>
  22. #include <nb30.h>
  23. //
  24. // Useful macro to obtain the total length of a buffer chain.
  25. // Make this use NDIS macros ?
  26. //
  27. #define NbiGetBufferChainLength(Buffer, Length) { \
  28. PNDIS_BUFFER _Buffer = (Buffer); \
  29. *(Length) = 0; \
  30. while (_Buffer) { \
  31. *(Length) += MmGetMdlByteCount(_Buffer); \
  32. _Buffer = _Buffer->Next; \
  33. } \
  34. }
  35. NTSTATUS
  36. NbiTdiQueryInformation(
  37. IN PDEVICE Device,
  38. IN PREQUEST Request
  39. )
  40. /*++
  41. Routine Description:
  42. This routine performs the TdiQueryInformation request for the transport
  43. provider.
  44. Arguments:
  45. Request - the request for the operation.
  46. Return Value:
  47. The status of operation.
  48. --*/
  49. {
  50. NTSTATUS Status;
  51. PTDI_REQUEST_KERNEL_QUERY_INFORMATION Query;
  52. PADDRESS_FILE AddressFile;
  53. PADDRESS Address;
  54. PCONNECTION Connection;
  55. union {
  56. struct {
  57. ULONG ActivityCount;
  58. TA_NETBIOS_ADDRESS NbiAddress;
  59. } AddressInfo;
  60. TA_NETBIOS_ADDRESS BroadcastAddress;
  61. TDI_ADDRESS_IPX IpxAddress;
  62. TDI_DATAGRAM_INFO DatagramInfo;
  63. struct {
  64. FIND_NAME_HEADER Header;
  65. FIND_NAME_BUFFER Buffer;
  66. } FindNameInfo;
  67. } TempBuffer;
  68. IPX_SOURCE_ROUTING_INFO SourceRoutingInfo;
  69. PADAPTER_STATUS AdapterStatus;
  70. BOOLEAN RemoteAdapterStatus;
  71. TDI_ADDRESS_NETBIOS * RemoteAddress;
  72. ULONG TargetBufferLength;
  73. ULONG ActualBytesCopied;
  74. ULONG AdapterStatusLength;
  75. ULONG ValidStatusLength;
  76. ULONG ElementSize, TransportAddressSize;
  77. PTRANSPORT_ADDRESS TransportAddress;
  78. TA_ADDRESS * CurAddress;
  79. PNETBIOS_CACHE CacheName;
  80. FIND_NAME_HEADER UNALIGNED * FindNameHeader = NULL;
  81. UINT FindNameBufferLength;
  82. NTSTATUS QueryStatus;
  83. CTELockHandle LockHandle;
  84. PLIST_ENTRY p;
  85. BOOLEAN UsedConnection;
  86. UINT i;
  87. //
  88. // what type of status do we want?
  89. //
  90. Query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)REQUEST_PARAMETERS(Request);
  91. switch (Query->QueryType) {
  92. case TDI_QUERY_ADDRESS_INFO:
  93. //
  94. // The caller wants the exact address value.
  95. //
  96. if (REQUEST_OPEN_TYPE(Request) == (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
  97. AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);
  98. #if defined(_PNP_POWER)
  99. Status = NbiVerifyAddressFile (AddressFile, CONFLICT_IS_NOT_OK);
  100. #else
  101. Status = NbiVerifyAddressFile (AddressFile);
  102. #endif _PNP_POWER
  103. if (!NT_SUCCESS(Status)) {
  104. break;
  105. }
  106. UsedConnection = FALSE;
  107. } else if (REQUEST_OPEN_TYPE(Request) == (PVOID)TDI_CONNECTION_FILE) {
  108. Connection = (PCONNECTION)REQUEST_OPEN_CONTEXT(Request);
  109. Status = NbiVerifyConnection (Connection);
  110. if (!NT_SUCCESS(Status)) {
  111. break;
  112. }
  113. if (!(AddressFile = Connection->AddressFile))
  114. {
  115. Status = STATUS_INVALID_ADDRESS;
  116. break;
  117. }
  118. UsedConnection = TRUE;
  119. } else {
  120. Status = STATUS_INVALID_ADDRESS;
  121. break;
  122. }
  123. Address = AddressFile->Address;
  124. NB_DEBUG2 (QUERY, ("Query address info on %lx\n", AddressFile));
  125. TempBuffer.AddressInfo.ActivityCount = 0;
  126. NB_GET_LOCK (&Address->Lock, &LockHandle);
  127. for (p = Address->AddressFileDatabase.Flink;
  128. p != &Address->AddressFileDatabase;
  129. p = p->Flink) {
  130. if (CONTAINING_RECORD (p, ADDRESS_FILE, Linkage)->State == ADDRESSFILE_STATE_OPEN) {
  131. ++TempBuffer.AddressInfo.ActivityCount;
  132. }
  133. }
  134. NB_FREE_LOCK (&Address->Lock, LockHandle);
  135. TdiBuildNetbiosAddress(
  136. AddressFile->Address->NetbiosAddress.NetbiosName,
  137. (BOOLEAN)(AddressFile->Address->NetbiosAddress.NetbiosNameType == TDI_ADDRESS_NETBIOS_TYPE_GROUP),
  138. &TempBuffer.AddressInfo.NbiAddress);
  139. Status = TdiCopyBufferToMdl(
  140. &TempBuffer.AddressInfo,
  141. 0,
  142. sizeof(ULONG) + sizeof(TA_NETBIOS_ADDRESS),
  143. REQUEST_NDIS_BUFFER(Request),
  144. 0,
  145. &ActualBytesCopied);
  146. REQUEST_INFORMATION(Request) = ActualBytesCopied;
  147. if (UsedConnection) {
  148. NbiDereferenceConnection (Connection, CREF_VERIFY);
  149. } else {
  150. NbiDereferenceAddressFile (AddressFile, AFREF_VERIFY);
  151. }
  152. break;
  153. case TDI_QUERY_CONNECTION_INFO:
  154. //
  155. // Connection info is queried on a connection,
  156. // verify this.
  157. //
  158. Connection = (PCONNECTION)REQUEST_OPEN_CONTEXT(Request);
  159. Status = NbiVerifyConnection (Connection);
  160. if (!NT_SUCCESS (Status)) {
  161. return Status;
  162. }
  163. if (Connection->State != CONNECTION_STATE_ACTIVE) {
  164. Status = STATUS_INVALID_CONNECTION;
  165. } else {
  166. //
  167. // Assume 50 ms of delay for every hop after the
  168. // first. The delay is returned as a negative number.
  169. //
  170. if (Connection->HopCount > 1) {
  171. Connection->ConnectionInfo.Delay.HighPart = (ULONG)-1;
  172. Connection->ConnectionInfo.Delay.LowPart =
  173. -((Connection->HopCount-1) * 50 * MILLISECONDS);
  174. } else {
  175. Connection->ConnectionInfo.Delay.HighPart = 0;
  176. Connection->ConnectionInfo.Delay.LowPart = 0;
  177. }
  178. //
  179. // We have tick count; to convert to bytes/second we do:
  180. //
  181. // packet 576 bytes 18.21 ticks
  182. // ---------------- * --------- * -----------
  183. // tick_count ticks packet seconds
  184. //
  185. // to get 10489/tick_count = bytes/second. We
  186. // double this because routers tend to
  187. // overestimate it.
  188. //
  189. // Since tick_count has such a low granularity,
  190. // a tick count of 1 gives us a throughput of
  191. // only 84 kbps, which is much too low. In
  192. // that case we return twice the link speed
  193. // which is in 100 bps units; that corresponds
  194. // to about 1/6 of our bandwidth in bytes/sec.
  195. //
  196. if (Connection->TickCount <= Connection->HopCount) {
  197. Connection->ConnectionInfo.Throughput.QuadPart =
  198. UInt32x32To64 (Connection->LineInfo.LinkSpeed, 2);
  199. } else {
  200. Connection->ConnectionInfo.Throughput.HighPart = 0;
  201. Connection->ConnectionInfo.Throughput.LowPart =
  202. 20978 / (Connection->TickCount - Connection->HopCount);
  203. }
  204. Connection->ConnectionInfo.Unreliable = FALSE;
  205. Status = TdiCopyBufferToMdl (
  206. &Connection->ConnectionInfo,
  207. 0,
  208. sizeof(TDI_CONNECTION_INFO),
  209. REQUEST_NDIS_BUFFER(Request),
  210. 0,
  211. &ActualBytesCopied);
  212. REQUEST_INFORMATION(Request) = ActualBytesCopied;
  213. }
  214. NbiDereferenceConnection (Connection, CREF_VERIFY);
  215. break;
  216. case TDI_QUERY_PROVIDER_INFO:
  217. NB_DEBUG2 (QUERY, ("Query provider info\n"));
  218. Status = TdiCopyBufferToMdl (
  219. &Device->Information,
  220. 0,
  221. sizeof (TDI_PROVIDER_INFO),
  222. REQUEST_NDIS_BUFFER(Request),
  223. 0,
  224. &ActualBytesCopied);
  225. REQUEST_INFORMATION(Request) = ActualBytesCopied;
  226. break;
  227. case TDI_QUERY_BROADCAST_ADDRESS:
  228. //
  229. // for this provider, the broadcast address is a zero byte name,
  230. // contained in a Transport address structure.
  231. //
  232. NB_DEBUG2 (QUERY, ("Query broadcast address\n"));
  233. TempBuffer.BroadcastAddress.TAAddressCount = 1;
  234. TempBuffer.BroadcastAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  235. TempBuffer.BroadcastAddress.Address[0].AddressLength = 0;
  236. Status = TdiCopyBufferToMdl (
  237. (PVOID)&TempBuffer.BroadcastAddress,
  238. 0L,
  239. sizeof (TempBuffer.BroadcastAddress.TAAddressCount) +
  240. sizeof (TempBuffer.BroadcastAddress.Address[0].AddressType) +
  241. sizeof (TempBuffer.BroadcastAddress.Address[0].AddressLength),
  242. REQUEST_NDIS_BUFFER(Request),
  243. 0,
  244. &ActualBytesCopied);
  245. REQUEST_INFORMATION(Request) = ActualBytesCopied;
  246. break;
  247. case TDI_QUERY_ADAPTER_STATUS:
  248. //
  249. // Determine if this is a local or remote query.
  250. //
  251. RemoteAdapterStatus = FALSE;
  252. if (Query->RequestConnectionInformation != NULL) {
  253. RemoteAddress = NbiParseTdiAddress(Query->RequestConnectionInformation->RemoteAddress, Query->RequestConnectionInformation->RemoteAddressLength, FALSE);
  254. if (RemoteAddress == NULL) {
  255. return STATUS_BAD_NETWORK_PATH;
  256. }
  257. #if defined(_PNP_POWER)
  258. if ( !NbiFindAdapterAddress(
  259. RemoteAddress->NetbiosName,
  260. LOCK_NOT_ACQUIRED ) ) {
  261. RemoteAdapterStatus = TRUE;
  262. }
  263. #else
  264. if (!RtlEqualMemory(
  265. RemoteAddress->NetbiosName,
  266. Device->ReservedNetbiosName,
  267. 16)) {
  268. RemoteAdapterStatus = TRUE;
  269. }
  270. #endif _PNP_POWER
  271. }
  272. if (RemoteAdapterStatus) {
  273. //
  274. // See if we have this name cached.
  275. //
  276. NB_GET_LOCK (&Device->Lock, &LockHandle);
  277. Status = CacheFindName(
  278. Device,
  279. FindNameOther,
  280. RemoteAddress->NetbiosName,
  281. &CacheName);
  282. if (Status == STATUS_PENDING) {
  283. //
  284. // A request for routes to this name has been
  285. // sent out on the net, we queue up this status
  286. // request and processing will be resumed when
  287. // we get a response.
  288. //
  289. // The status field in the request will hold
  290. // the cache entry for the remote. The information
  291. // field will hold the remote netbios name while
  292. // it is in the WaitingAdapterStatus queue, and
  293. // will hold a timeout value while we it is in
  294. // the ActiveAdapterStatus queue.
  295. //
  296. NB_DEBUG2 (QUERY, ("Queueing up adapter status %lx\n", Request));
  297. NbiReferenceDevice (Device, DREF_STATUS_QUERY);
  298. REQUEST_INFORMATION (Request) = (ULONG_PTR) RemoteAddress;
  299. InsertTailList(
  300. &Device->WaitingAdapterStatus,
  301. REQUEST_LINKAGE (Request));
  302. NB_FREE_LOCK (&Device->Lock, LockHandle);
  303. } else if (Status == STATUS_SUCCESS) {
  304. NB_DEBUG2 (QUERY, ("Found adapter status cached %lx\n", Request));
  305. //
  306. // We reference the cache name entry so it won't
  307. // go away while we are using it.
  308. //
  309. REQUEST_STATUSPTR(Request) = (PVOID)CacheName;
  310. ++CacheName->ReferenceCount;
  311. NbiReferenceDevice (Device, DREF_STATUS_QUERY);
  312. REQUEST_INFORMATION (Request) = 0;
  313. InsertTailList(
  314. &Device->ActiveAdapterStatus,
  315. REQUEST_LINKAGE (Request));
  316. NB_FREE_LOCK (&Device->Lock, LockHandle);
  317. NbiSendStatusQuery (Request);
  318. Status = STATUS_PENDING;
  319. } else {
  320. if (Status != STATUS_INSUFFICIENT_RESOURCES) {
  321. Status = STATUS_IO_TIMEOUT;
  322. }
  323. REQUEST_INFORMATION (Request) = 0;
  324. NB_FREE_LOCK (&Device->Lock, LockHandle);
  325. }
  326. } else {
  327. //
  328. // Local adapter status.
  329. //
  330. NbiGetBufferChainLength (REQUEST_NDIS_BUFFER(Request), &TargetBufferLength);
  331. Status = NbiStoreAdapterStatus(
  332. TargetBufferLength,
  333. 1, // NIC ID, was 0, changed to 1 for Bug #18026
  334. // because for NicId = 0, Ipx returns virtual
  335. // address. Netbios uses that to register the
  336. // name (00...01) and fails.
  337. &AdapterStatus,
  338. &AdapterStatusLength,
  339. &ValidStatusLength);
  340. if (Status != STATUS_INSUFFICIENT_RESOURCES) {
  341. //
  342. // This should succeed since we know the length
  343. // will fit.
  344. //
  345. (VOID)TdiCopyBufferToMdl(
  346. AdapterStatus,
  347. 0,
  348. ValidStatusLength,
  349. REQUEST_NDIS_BUFFER(Request),
  350. 0,
  351. &ActualBytesCopied);
  352. REQUEST_INFORMATION(Request) = ActualBytesCopied;
  353. NbiFreeMemory (AdapterStatus, AdapterStatusLength, MEMORY_STATUS, "Adapter Status");
  354. }
  355. }
  356. break;
  357. case TDI_QUERY_FIND_NAME:
  358. //
  359. // Check that there is a valid Netbios remote address.
  360. //
  361. if ((Query->RequestConnectionInformation == NULL) ||
  362. ((RemoteAddress = NbiParseTdiAddress(Query->RequestConnectionInformation->RemoteAddress, Query->RequestConnectionInformation->RemoteAddressLength, FALSE)) == NULL)) {
  363. return STATUS_BAD_NETWORK_PATH;
  364. }
  365. //
  366. // We assume the entire request buffer is in the first
  367. // piece of the MDL chain.
  368. // Make sure there is room for at least the header.
  369. //
  370. NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request), (PVOID *)&FindNameHeader, &FindNameBufferLength,
  371. HighPagePriority);
  372. if ((!FindNameHeader) ||
  373. (FindNameBufferLength < sizeof(FIND_NAME_HEADER))) {
  374. return STATUS_INSUFFICIENT_RESOURCES;
  375. }
  376. //
  377. // See if we have this name cached. We specify that this is
  378. // a netbios name query, so this will only succeed if this is a
  379. // unique name -- for a group name it will queue up a find
  380. // name query and when we get the response we will fill in
  381. // the request's buffer based on it.
  382. //
  383. NB_GET_LOCK (&Device->Lock, &LockHandle);
  384. Status = CacheFindName(
  385. Device,
  386. FindNameNetbiosFindName,
  387. RemoteAddress->NetbiosName,
  388. &CacheName);
  389. if (Status == STATUS_PENDING) {
  390. //
  391. // A request for routes to this name has been
  392. // sent out on the net, we queue up this find
  393. // name request and processing will be resumed when
  394. // we get a response.
  395. //
  396. // The information field will hold the remote
  397. // netbios name while it is in the WaitingNetbiosFindName
  398. // queue. The status will hold the current status --
  399. // initially failure, then success, then overflow
  400. // if the buffer is too small.
  401. //
  402. NB_DEBUG2 (QUERY, ("Queueing up find name %lx\n", Request));
  403. NbiReferenceDevice (Device, DREF_NB_FIND_NAME);
  404. FindNameHeader->node_count = 0;
  405. FindNameHeader->reserved = 0;
  406. FindNameHeader->unique_group = 0;
  407. REQUEST_INFORMATION (Request) = (ULONG_PTR)RemoteAddress;
  408. //
  409. // Assume it fails, we update the status to
  410. // SUCCESS or BUFFER_OVERFLOW if needed.
  411. //
  412. REQUEST_STATUS (Request) = STATUS_IO_TIMEOUT;
  413. InsertTailList(
  414. &Device->WaitingNetbiosFindName,
  415. REQUEST_LINKAGE (Request));
  416. NB_FREE_LOCK (&Device->Lock, LockHandle);
  417. } else if (Status == STATUS_SUCCESS) {
  418. NB_DEBUG2 (QUERY, ("Found find name cached %lx\n", Request));
  419. //
  420. // We don't need to reference the cache entry since
  421. // we only use it here with the lock still held.
  422. //
  423. //
  424. // Query the local address, which we will return as
  425. // the destination address of this query. Since we
  426. // use TempBuffer.IpxAddress for this query, we have
  427. // to immediately copy it to its correct place in
  428. // TempBuffer.FindNameInfo.Buffer.
  429. //
  430. #if defined(_PNP_POWER)
  431. if( (*Device->Bind.QueryHandler)( // Check return code
  432. IPX_QUERY_IPX_ADDRESS,
  433. &CacheName->Networks[0].LocalTarget.NicHandle,
  434. &TempBuffer.IpxAddress,
  435. sizeof(TDI_ADDRESS_IPX),
  436. NULL) != STATUS_SUCCESS ) {
  437. NB_DEBUG( QUERY, ("Ipx Query %d failed for Nic %x\n",IPX_QUERY_IPX_ADDRESS,
  438. CacheName->Networks[0].LocalTarget.NicHandle.NicId ));
  439. goto QueryFindNameFailed;
  440. }
  441. #else
  442. (VOID)(*Device->Bind.QueryHandler)( // Check return code
  443. IPX_QUERY_IPX_ADDRESS,
  444. CacheName->Networks[0].LocalTarget.NicId,
  445. &TempBuffer.IpxAddress,
  446. sizeof(TDI_ADDRESS_IPX),
  447. NULL);
  448. #endif _PNP_POWER
  449. RtlMoveMemory (TempBuffer.FindNameInfo.Buffer.destination_addr, TempBuffer.IpxAddress.NodeAddress, 6);
  450. TempBuffer.FindNameInfo.Buffer.access_control = 0x10; // standard token-ring values
  451. TempBuffer.FindNameInfo.Buffer.frame_control = 0x40;
  452. RtlCopyMemory (TempBuffer.FindNameInfo.Buffer.source_addr, CacheName->FirstResponse.NodeAddress, 6);
  453. //
  454. // Query source routing information about this remote, if any.
  455. //
  456. SourceRoutingInfo.Identifier = IDENTIFIER_NB;
  457. RtlCopyMemory (SourceRoutingInfo.RemoteAddress, CacheName->FirstResponse.NodeAddress, 6);
  458. QueryStatus = (*Device->Bind.QueryHandler)(
  459. IPX_QUERY_SOURCE_ROUTING,
  460. #if defined(_PNP_POWER)
  461. &CacheName->Networks[0].LocalTarget.NicHandle,
  462. #else
  463. CacheName->Networks[0].LocalTarget.NicId,
  464. #endif _PNP_POWER
  465. &SourceRoutingInfo,
  466. sizeof(IPX_SOURCE_ROUTING_INFO),
  467. NULL);
  468. RtlZeroMemory(TempBuffer.FindNameInfo.Buffer.routing_info, 18);
  469. if (QueryStatus != STATUS_SUCCESS) {
  470. SourceRoutingInfo.SourceRoutingLength = 0;
  471. } else if (SourceRoutingInfo.SourceRoutingLength > 0) {
  472. RtlMoveMemory(
  473. TempBuffer.FindNameInfo.Buffer.routing_info,
  474. SourceRoutingInfo.SourceRouting,
  475. SourceRoutingInfo.SourceRoutingLength);
  476. }
  477. TempBuffer.FindNameInfo.Buffer.length = (UCHAR)(14 + SourceRoutingInfo.SourceRoutingLength);
  478. TempBuffer.FindNameInfo.Header.node_count = 1;
  479. TempBuffer.FindNameInfo.Header.reserved = 0;
  480. TempBuffer.FindNameInfo.Header.unique_group = 0; // unique
  481. NB_FREE_LOCK (&Device->Lock, LockHandle);
  482. //
  483. // 33 is sizeof(FIND_NAME_BUFFER) without the padding.
  484. //
  485. Status = TdiCopyBufferToMdl (
  486. (PVOID)&TempBuffer.FindNameInfo,
  487. 0,
  488. sizeof(FIND_NAME_HEADER) + 33,
  489. REQUEST_NDIS_BUFFER(Request),
  490. 0,
  491. &ActualBytesCopied);
  492. REQUEST_INFORMATION(Request) = ActualBytesCopied;
  493. } else {
  494. #if defined(_PNP_POWER)
  495. QueryFindNameFailed:
  496. #endif _PNP_POWER
  497. if (Status != STATUS_INSUFFICIENT_RESOURCES) {
  498. Status = STATUS_IO_TIMEOUT;
  499. }
  500. REQUEST_INFORMATION (Request) = 0;
  501. NB_FREE_LOCK (&Device->Lock, LockHandle);
  502. }
  503. break;
  504. case TDI_QUERY_PROVIDER_STATISTICS:
  505. //
  506. // Keep track of more of these.
  507. //
  508. NB_DEBUG2 (QUERY, ("Query provider statistics\n"));
  509. Status = TdiCopyBufferToMdl (
  510. &Device->Statistics,
  511. 0,
  512. FIELD_OFFSET (TDI_PROVIDER_STATISTICS, ResourceStats[0]),
  513. REQUEST_NDIS_BUFFER(Request),
  514. 0,
  515. &ActualBytesCopied);
  516. REQUEST_INFORMATION(Request) = ActualBytesCopied;
  517. break;
  518. case TDI_QUERY_DATAGRAM_INFO:
  519. NB_DEBUG2 (QUERY, ("Query datagram info\n"));
  520. TempBuffer.DatagramInfo.MaximumDatagramBytes = 0;
  521. TempBuffer.DatagramInfo.MaximumDatagramCount = 0;
  522. Status = TdiCopyBufferToMdl (
  523. &TempBuffer.DatagramInfo,
  524. 0,
  525. sizeof(TempBuffer.DatagramInfo),
  526. REQUEST_NDIS_BUFFER(Request),
  527. 0,
  528. &ActualBytesCopied);
  529. REQUEST_INFORMATION(Request) = ActualBytesCopied;
  530. break;
  531. case TDI_QUERY_DATA_LINK_ADDRESS:
  532. case TDI_QUERY_NETWORK_ADDRESS:{
  533. #if defined(_PNP_POWER)
  534. Status = (*Device->Bind.QueryHandler)( // Check return code
  535. (Query->QueryType == TDI_QUERY_DATA_LINK_ADDRESS
  536. ? IPX_QUERY_DATA_LINK_ADDRESS
  537. : IPX_QUERY_NETWORK_ADDRESS ),
  538. NULL,
  539. Request,
  540. 0,
  541. NULL);
  542. #else
  543. ULONG TransportAddressAllocSize;
  544. if (Query->QueryType == TDI_QUERY_DATA_LINK_ADDRESS) {
  545. ElementSize = (2 * sizeof(USHORT)) + 6;
  546. } else {
  547. ElementSize = (2 * sizeof(USHORT)) + sizeof(TDI_ADDRESS_IPX);
  548. }
  549. // TransportAddress = CTEAllocMem(sizeof(int) + (ElementSize * Device->MaximumNicId));
  550. TransportAddressAllocSize = sizeof(int) + ( ElementSize * Device->MaximumNicId);
  551. TransportAddress = NbiAllocateMemory( TransportAddressAllocSize, MEMORY_QUERY, "Temp Query Allocation");
  552. if (TransportAddress == NULL) {
  553. Status = STATUS_INSUFFICIENT_RESOURCES;
  554. } else {
  555. TransportAddress->TAAddressCount = 0;
  556. TransportAddressSize = sizeof(int);
  557. CurAddress = (TA_ADDRESS UNALIGNED *)TransportAddress->Address;
  558. for (i = 1; i <= Device->MaximumNicId; i++) {
  559. Status = (*Device->Bind.QueryHandler)( // Check return code
  560. IPX_QUERY_IPX_ADDRESS,
  561. (USHORT)i,
  562. &TempBuffer.IpxAddress,
  563. sizeof(TDI_ADDRESS_IPX),
  564. NULL);
  565. if (Status != STATUS_SUCCESS) {
  566. continue;
  567. }
  568. if (Query->QueryType == TDI_QUERY_DATA_LINK_ADDRESS) {
  569. CurAddress->AddressLength = 6;
  570. CurAddress->AddressType = TDI_ADDRESS_TYPE_UNSPEC;
  571. RtlCopyMemory (CurAddress->Address, TempBuffer.IpxAddress.NodeAddress, 6);
  572. } else {
  573. CurAddress->AddressLength = sizeof(TDI_ADDRESS_IPX);
  574. CurAddress->AddressType = TDI_ADDRESS_TYPE_IPX;
  575. RtlCopyMemory (CurAddress->Address, &TempBuffer.IpxAddress, sizeof(TDI_ADDRESS_IPX));
  576. }
  577. ++TransportAddress->TAAddressCount;
  578. TransportAddressSize += ElementSize;
  579. CurAddress = (TA_ADDRESS UNALIGNED *)(((PUCHAR)CurAddress) + ElementSize);
  580. }
  581. Status = TdiCopyBufferToMdl (
  582. TransportAddress,
  583. 0,
  584. TransportAddressSize,
  585. REQUEST_NDIS_BUFFER(Request),
  586. 0,
  587. &ActualBytesCopied);
  588. REQUEST_INFORMATION(Request) = ActualBytesCopied;
  589. // CTEFreeMem (TransportAddress);
  590. NbiFreeMemory( TransportAddress, TransportAddressAllocSize, MEMORY_QUERY, "Temp Query Allocation");
  591. }
  592. #endif _PNP_POWER
  593. break;
  594. }
  595. default:
  596. NB_DEBUG (QUERY, ("Invalid query type %d\n", Query->QueryType));
  597. Status = STATUS_INVALID_DEVICE_REQUEST;
  598. break;
  599. }
  600. return Status;
  601. } /* NbiTdiQueryInformation */
  602. NTSTATUS
  603. NbiStoreAdapterStatus(
  604. IN ULONG MaximumLength,
  605. IN USHORT NicId,
  606. OUT PVOID * StatusBuffer,
  607. OUT ULONG * StatusBufferLength,
  608. OUT ULONG * ValidBufferLength
  609. )
  610. /*++
  611. Routine Description:
  612. This routine allocates an ADAPTER_STATUS buffer and
  613. fills it in. The buffer will be allocated at most
  614. MaximumLength size. The caller is responsible for
  615. freeing the buffer.
  616. Arguments:
  617. MaximumLength - The maximum length to allocate.
  618. NicId - The NIC ID the query was received on, or 0 for
  619. a local query.
  620. StatusBuffer - Returns the allocated buffer.
  621. StatusBufferLength - Returns the length of the buffer.
  622. ValidBufferLength - Returns the length of the buffer which
  623. contains valid adapter status data.
  624. Return Value:
  625. STATUS_SUCCESS - The buffer was written successfully.
  626. STATUS_BUFFER_OVERFLOW - The buffer was written but not all
  627. data could fit in MaximumLength bytes.
  628. STATUS_INSUFFICIENT_RESOURCES - The buffer could not be allocated.
  629. --*/
  630. {
  631. PADAPTER_STATUS AdapterStatus;
  632. PNAME_BUFFER NameBuffer;
  633. ADAPTER_STATUS TempAdapterStatus;
  634. #if !defined(_PNP_POWER)
  635. TDI_ADDRESS_IPX IpxAddress;
  636. #endif !_PNP_POWER
  637. PDEVICE Device = NbiDevice;
  638. PADDRESS Address;
  639. UCHAR NameCount;
  640. ULONG LengthNeeded;
  641. ULONG BytesWritten;
  642. NTSTATUS Status;
  643. PLIST_ENTRY p;
  644. CTELockHandle LockHandle;
  645. //
  646. // First fill in the basic adapter status structure, to make
  647. // it easier to copy over if the target buffer is really short.
  648. //
  649. RtlZeroMemory ((PVOID)&TempAdapterStatus, sizeof(ADAPTER_STATUS));
  650. #if defined(_PNP_POWER)
  651. RtlCopyMemory (TempAdapterStatus.adapter_address, Device->Bind.Node, 6);
  652. #else
  653. (VOID)(*Device->Bind.QueryHandler)( // Check return code
  654. IPX_QUERY_IPX_ADDRESS,
  655. NicId,
  656. &IpxAddress,
  657. sizeof(TDI_ADDRESS_IPX),
  658. NULL);
  659. RtlCopyMemory (TempAdapterStatus.adapter_address, IpxAddress.NodeAddress, 6);
  660. #endif _PNP_POWER
  661. //
  662. // Some of the fields mean different things for Novell Netbios,
  663. // as described in the comments.
  664. //
  665. TempAdapterStatus.rev_major = 0; // Jumpers
  666. TempAdapterStatus.reserved0 = 0; // SelfTest
  667. TempAdapterStatus.adapter_type = 0; // MajorVersion
  668. TempAdapterStatus.rev_minor = 0; // MinorVersion
  669. TempAdapterStatus.duration = 0; // ReportingPeriod
  670. TempAdapterStatus.frmr_recv = 0; // ReceiveCRCErrors
  671. TempAdapterStatus.frmr_xmit = 0; // ReceiveAlignErrors
  672. TempAdapterStatus.iframe_recv_err = 0; // XmitCollisions
  673. TempAdapterStatus.xmit_aborts = 0; // XmitAbort
  674. TempAdapterStatus.xmit_success = Device->Statistics.DataFramesSent; // SuccessfulXmits
  675. TempAdapterStatus.recv_success = Device->Statistics.DataFramesReceived; // SuccessfulReceive
  676. TempAdapterStatus.iframe_xmit_err = (WORD)Device->Statistics.DataFramesResent; // XmitRetries
  677. TempAdapterStatus.recv_buff_unavail = (WORD)Device->Statistics.DataFramesRejected; // ExhaustedResource
  678. // t1_timeouts, ti_timeouts, and reserved1 are unused.
  679. TempAdapterStatus.free_ncbs = 0xffff; // FreeBlocks
  680. TempAdapterStatus.max_cfg_ncbs = 0xffff; // ConfiguredNCB
  681. TempAdapterStatus.max_ncbs = 0xffff; // MaxNCB
  682. // xmit_bug_unavail and max_dgram_size are unused.
  683. TempAdapterStatus.pending_sess = (WORD)Device->Statistics.OpenConnections; // CurrentSessions
  684. TempAdapterStatus.max_cfg_sess = 0xffff; // MaxSessionConfigured
  685. TempAdapterStatus.max_sess = 0xffff; // MaxSessionPossible
  686. TempAdapterStatus.max_sess_pkt_size = (USHORT)
  687. (Device->Bind.LineInfo.MaximumSendSize - sizeof(NB_CONNECTION)); // MaxSessionPacketSize
  688. TempAdapterStatus.name_count = 0;
  689. //
  690. // Do a quick estimate of how many names we need room for.
  691. // This includes stopping addresses and the broadcast
  692. // address, for the moment.
  693. //
  694. NB_GET_LOCK (&Device->Lock, &LockHandle);
  695. LengthNeeded = sizeof(ADAPTER_STATUS) + (Device->AddressCount * sizeof(NAME_BUFFER));
  696. if (LengthNeeded > MaximumLength) {
  697. LengthNeeded = MaximumLength;
  698. }
  699. AdapterStatus = NbiAllocateMemory(LengthNeeded, MEMORY_STATUS, "Adapter Status");
  700. if (AdapterStatus == NULL) {
  701. NB_FREE_LOCK (&Device->Lock, LockHandle);
  702. return STATUS_INSUFFICIENT_RESOURCES;
  703. }
  704. *StatusBuffer = AdapterStatus;
  705. *StatusBufferLength = LengthNeeded;
  706. if (LengthNeeded < sizeof(ADAPTER_STATUS)) {
  707. RtlCopyMemory (AdapterStatus, &TempAdapterStatus, LengthNeeded);
  708. *ValidBufferLength = LengthNeeded;
  709. NB_FREE_LOCK (&Device->Lock, LockHandle);
  710. return STATUS_BUFFER_OVERFLOW;
  711. }
  712. RtlCopyMemory (AdapterStatus, &TempAdapterStatus, sizeof(ADAPTER_STATUS));
  713. BytesWritten = sizeof(ADAPTER_STATUS);
  714. NameBuffer = (PNAME_BUFFER)(AdapterStatus+1);
  715. NameCount = 0;
  716. //
  717. // Scan through the device's address database, filling in
  718. // the NAME_BUFFERs.
  719. //
  720. Status = STATUS_SUCCESS;
  721. for (p = Device->AddressDatabase.Flink;
  722. p != &Device->AddressDatabase;
  723. p = p->Flink) {
  724. Address = CONTAINING_RECORD (p, ADDRESS, Linkage);
  725. //
  726. // Ignore addresses that are shutting down.
  727. //
  728. #if defined(_PNP_POWER)
  729. if ((Address->State != ADDRESS_STATE_OPEN) ||
  730. (Address->Flags & ADDRESS_FLAGS_CONFLICT)) {
  731. continue;
  732. }
  733. #else
  734. if ((Address->State != ADDRESS_STATE_OPEN) != 0) {
  735. continue;
  736. }
  737. #endif _PNP_POWER
  738. //
  739. // Ignore the broadcast address.
  740. //
  741. if (Address->NetbiosAddress.Broadcast) {
  742. continue;
  743. }
  744. //
  745. // Ignore our reserved address.
  746. //
  747. #if defined(_PNP_POWER)
  748. if ( NbiFindAdapterAddress(
  749. Address->NetbiosAddress.NetbiosName,
  750. LOCK_ACQUIRED
  751. )) {
  752. continue;
  753. }
  754. #else
  755. if (RtlEqualMemory(
  756. Address->NetbiosAddress.NetbiosName,
  757. Device->ReservedNetbiosName,
  758. 16)) {
  759. continue;
  760. }
  761. #endif _PNP_POWER
  762. //
  763. // Make sure we still have room.
  764. //
  765. if (BytesWritten + sizeof(NAME_BUFFER) > LengthNeeded) {
  766. Status = STATUS_BUFFER_OVERFLOW;
  767. break;
  768. }
  769. RtlCopyMemory(
  770. NameBuffer->name,
  771. Address->NetbiosAddress.NetbiosName,
  772. 16);
  773. ++NameCount;
  774. NameBuffer->name_num = NameCount;
  775. NameBuffer->name_flags = REGISTERED;
  776. if (Address->NameTypeFlag == NB_NAME_GROUP) {
  777. NameBuffer->name_flags |= GROUP_NAME;
  778. }
  779. BytesWritten += sizeof(NAME_BUFFER);
  780. ++NameBuffer;
  781. }
  782. AdapterStatus->name_count = (WORD)NameCount;
  783. *ValidBufferLength = BytesWritten;
  784. NB_FREE_LOCK (&Device->Lock, LockHandle);
  785. return Status;
  786. } /* NbiStoreAdapterStatus */
  787. VOID
  788. NbiUpdateNetbiosFindName(
  789. IN PREQUEST Request,
  790. #if defined(_PNP_POWER)
  791. IN PNIC_HANDLE NicHandle,
  792. #else
  793. IN USHORT NicId,
  794. #endif _PNP_POWER
  795. IN TDI_ADDRESS_IPX UNALIGNED * RemoteIpxAddress,
  796. IN BOOLEAN Unique
  797. )
  798. /*++
  799. Routine Description:
  800. This routine updates the find name request with the
  801. new information received. It updates the status in
  802. the request if needed.
  803. Arguments:
  804. Request - The netbios find name request.
  805. NicId - The NIC ID the response was received on.
  806. RemoteIpxAddress - The IPX address of the remote.
  807. Unique - TRUE if the name is unique.
  808. Return Value:
  809. None.
  810. --*/
  811. {
  812. FIND_NAME_HEADER UNALIGNED * FindNameHeader = NULL;
  813. FIND_NAME_BUFFER UNALIGNED * FindNameBuffer;
  814. UINT FindNameBufferLength;
  815. TDI_ADDRESS_IPX LocalIpxAddress;
  816. IPX_SOURCE_ROUTING_INFO SourceRoutingInfo;
  817. NTSTATUS QueryStatus;
  818. UINT i;
  819. NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request), (PVOID *)&FindNameHeader, &FindNameBufferLength,
  820. HighPagePriority);
  821. if (!FindNameHeader)
  822. {
  823. return;
  824. }
  825. //
  826. // Scan through the names saved so far and see if this one
  827. // is there.
  828. //
  829. FindNameBuffer = (FIND_NAME_BUFFER UNALIGNED *)(FindNameHeader+1);
  830. for (i = 0; i < FindNameHeader->node_count; i++) {
  831. if (RtlEqualMemory(
  832. FindNameBuffer->source_addr,
  833. RemoteIpxAddress->NodeAddress,
  834. 6)) {
  835. //
  836. // This remote already responded, ignore it.
  837. //
  838. return;
  839. }
  840. FindNameBuffer = (FIND_NAME_BUFFER UNALIGNED *) (((PUCHAR)FindNameBuffer) + 33);
  841. }
  842. //
  843. // Make sure there is room for this new node. 33 is
  844. // sizeof(FIND_NAME_BUFFER) without padding.
  845. //
  846. if (FindNameBufferLength < sizeof(FIND_NAME_HEADER) + ((FindNameHeader->node_count+1) * 33)) {
  847. REQUEST_STATUS(Request) = STATUS_BUFFER_OVERFLOW;
  848. return;
  849. }
  850. //
  851. // Query the local address, which we will return as
  852. // the destination address of this query.
  853. //
  854. #if defined(_PNP_POWER)
  855. if( (*NbiDevice->Bind.QueryHandler)( // Check return code
  856. IPX_QUERY_IPX_ADDRESS,
  857. NicHandle,
  858. &LocalIpxAddress,
  859. sizeof(TDI_ADDRESS_IPX),
  860. NULL) != STATUS_SUCCESS ) {
  861. //
  862. // Ignore this response if the query fails. maybe the NicHandle
  863. // is bad or it just got removed.
  864. //
  865. NB_DEBUG( QUERY, ("Ipx Query %d failed for Nic %x\n",IPX_QUERY_IPX_ADDRESS,
  866. NicHandle->NicId ));
  867. return;
  868. }
  869. #else
  870. (VOID)(*NbiDevice->Bind.QueryHandler)( // Check return code
  871. IPX_QUERY_IPX_ADDRESS,
  872. NicId,
  873. &LocalIpxAddress,
  874. sizeof(TDI_ADDRESS_IPX),
  875. NULL);
  876. #endif _PNP_POWER
  877. FindNameBuffer->access_control = 0x10; // standard token-ring values
  878. FindNameBuffer->frame_control = 0x40;
  879. RtlMoveMemory (FindNameBuffer->destination_addr, LocalIpxAddress.NodeAddress, 6);
  880. RtlCopyMemory (FindNameBuffer->source_addr, RemoteIpxAddress->NodeAddress, 6);
  881. //
  882. // Query source routing information about this remote, if any.
  883. //
  884. SourceRoutingInfo.Identifier = IDENTIFIER_NB;
  885. RtlCopyMemory (SourceRoutingInfo.RemoteAddress, RemoteIpxAddress->NodeAddress, 6);
  886. QueryStatus = (*NbiDevice->Bind.QueryHandler)(
  887. IPX_QUERY_SOURCE_ROUTING,
  888. #if defined(_PNP_POWER)
  889. NicHandle,
  890. #else
  891. NicId,
  892. #endif _PNP_POWER
  893. &SourceRoutingInfo,
  894. sizeof(IPX_SOURCE_ROUTING_INFO),
  895. NULL);
  896. RtlZeroMemory(FindNameBuffer->routing_info, 18);
  897. if (QueryStatus != STATUS_SUCCESS) {
  898. SourceRoutingInfo.SourceRoutingLength = 0;
  899. } else if (SourceRoutingInfo.SourceRoutingLength > 0) {
  900. RtlMoveMemory(
  901. FindNameBuffer->routing_info,
  902. SourceRoutingInfo.SourceRouting,
  903. SourceRoutingInfo.SourceRoutingLength);
  904. }
  905. FindNameBuffer->length = (UCHAR)(14 + SourceRoutingInfo.SourceRoutingLength);
  906. ++FindNameHeader->node_count;
  907. if (!Unique) {
  908. FindNameHeader->unique_group = 1; // group
  909. }
  910. REQUEST_STATUS(Request) = STATUS_SUCCESS;
  911. } /* NbiUpdateNetbiosFindName */
  912. VOID
  913. NbiSetNetbiosFindNameInformation(
  914. IN PREQUEST Request
  915. )
  916. /*++
  917. Routine Description:
  918. This routine sets the REQUEST_INFORMATION field to the right
  919. value based on the number of responses recorded in the netbios
  920. find name request's buffer.
  921. Arguments:
  922. Request - The netbios find name request.
  923. Return Value:
  924. None.
  925. --*/
  926. {
  927. FIND_NAME_HEADER UNALIGNED * FindNameHeader = NULL;
  928. UINT FindNameBufferLength;
  929. NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request), (PVOID *)&FindNameHeader, &FindNameBufferLength,
  930. HighPagePriority);
  931. if (FindNameHeader)
  932. {
  933. //
  934. // 33 is sizeof(FIND_NAME_BUFFER) without the padding.
  935. //
  936. REQUEST_INFORMATION(Request) = sizeof(FIND_NAME_HEADER) + (FindNameHeader->node_count * 33);
  937. }
  938. } /* NbiSetNetbiosFindNameInformation */
  939. NTSTATUS
  940. NbiTdiSetInformation(
  941. IN PDEVICE Device,
  942. IN PREQUEST Request
  943. )
  944. /*++
  945. Routine Description:
  946. This routine performs the TdiSetInformation request for the transport
  947. provider.
  948. Arguments:
  949. Device - the device.
  950. Request - the request for the operation.
  951. Return Value:
  952. NTSTATUS - status of operation.
  953. --*/
  954. {
  955. UNREFERENCED_PARAMETER (Device);
  956. UNREFERENCED_PARAMETER (Request);
  957. return STATUS_NOT_IMPLEMENTED;
  958. } /* NbiTdiSetInformation */
  959. VOID
  960. NbiProcessStatusQuery(
  961. IN PIPX_LOCAL_TARGET RemoteAddress,
  962. IN ULONG MacOptions,
  963. IN PUCHAR PacketBuffer,
  964. IN UINT PacketSize
  965. )
  966. /*++
  967. Routine Description:
  968. This routine handles NB_CMD_STATUS_QUERY frames.
  969. Arguments:
  970. RemoteAddress - The local target this packet was received from.
  971. MacOptions - The MAC options for the underlying NDIS binding.
  972. LookaheadBuffer - The packet data, starting at the IPX
  973. header.
  974. PacketSize - The total length of the packet, starting at the
  975. IPX header.
  976. Return Value:
  977. None.
  978. --*/
  979. {
  980. PSINGLE_LIST_ENTRY s;
  981. PNB_SEND_RESERVED Reserved;
  982. PNDIS_PACKET Packet;
  983. NB_CONNECTIONLESS UNALIGNED * Header;
  984. NDIS_STATUS NdisStatus;
  985. IPX_LINE_INFO LineInfo;
  986. ULONG ResponseSize;
  987. NTSTATUS Status;
  988. PNDIS_BUFFER AdapterStatusBuffer;
  989. PADAPTER_STATUS AdapterStatus;
  990. ULONG AdapterStatusLength;
  991. ULONG ValidStatusLength;
  992. PDEVICE Device = NbiDevice;
  993. NB_CONNECTIONLESS UNALIGNED * Connectionless =
  994. (NB_CONNECTIONLESS UNALIGNED *)PacketBuffer;
  995. //
  996. // The old stack does not include the 14 bytes of padding in
  997. // the 802.3 or IPX length of the packet.
  998. //
  999. if (PacketSize < (sizeof(IPX_HEADER) + 2)) {
  1000. return;
  1001. }
  1002. //
  1003. // Get the maximum size we can send.
  1004. //
  1005. #if defined(_PNP_POWER)
  1006. if( (*Device->Bind.QueryHandler)( // Check return code
  1007. IPX_QUERY_LINE_INFO,
  1008. &RemoteAddress->NicHandle,
  1009. &LineInfo,
  1010. sizeof(IPX_LINE_INFO),
  1011. NULL) != STATUS_SUCCESS ) {
  1012. //
  1013. // Bad NicHandle or it just got removed.
  1014. //
  1015. NB_DEBUG( QUERY, ("Ipx Query %d failed for Nic %x\n",IPX_QUERY_LINE_INFO,
  1016. RemoteAddress->NicHandle.NicId ));
  1017. return;
  1018. }
  1019. //
  1020. // Allocate a packet from the pool.
  1021. //
  1022. s = NbiPopSendPacket(Device, FALSE);
  1023. if (s == NULL) {
  1024. return;
  1025. }
  1026. #else
  1027. //
  1028. // Allocate a packet from the pool.
  1029. //
  1030. s = NbiPopSendPacket(Device, FALSE);
  1031. if (s == NULL) {
  1032. return;
  1033. }
  1034. //
  1035. // Get the maximum size we can send.
  1036. //
  1037. (VOID)(*Device->Bind.QueryHandler)( // Check return code
  1038. IPX_QUERY_LINE_INFO,
  1039. RemoteAddress->NicId,
  1040. &LineInfo,
  1041. sizeof(IPX_LINE_INFO),
  1042. NULL);
  1043. #endif _PNP_POWER
  1044. ResponseSize = LineInfo.MaximumSendSize - sizeof(IPX_HEADER) - sizeof(NB_STATUS_RESPONSE);
  1045. //
  1046. // Get the local adapter status (this allocates a buffer).
  1047. //
  1048. Status = NbiStoreAdapterStatus(
  1049. ResponseSize,
  1050. #if defined(_PNP_POWER)
  1051. RemoteAddress->NicHandle.NicId,
  1052. #else
  1053. RemoteAddress->NicId,
  1054. #endif _PNP_POWER
  1055. &AdapterStatus,
  1056. &AdapterStatusLength,
  1057. &ValidStatusLength);
  1058. if (Status == STATUS_INSUFFICIENT_RESOURCES) {
  1059. ExInterlockedPushEntrySList(
  1060. &Device->SendPacketList,
  1061. s,
  1062. &NbiGlobalPoolInterlock);
  1063. return;
  1064. }
  1065. //
  1066. // Allocate an NDIS buffer to map the extra buffer.
  1067. //
  1068. NdisAllocateBuffer(
  1069. &NdisStatus,
  1070. &AdapterStatusBuffer,
  1071. Device->NdisBufferPoolHandle,
  1072. AdapterStatus,
  1073. ValidStatusLength);
  1074. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  1075. NbiFreeMemory (AdapterStatus, AdapterStatusLength, MEMORY_STATUS, "Adapter Status");
  1076. ExInterlockedPushEntrySList(
  1077. &Device->SendPacketList,
  1078. s,
  1079. &NbiGlobalPoolInterlock);
  1080. return;
  1081. }
  1082. NB_DEBUG2 (QUERY, ("Reply to AdapterStatus from %lx %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n",
  1083. *(UNALIGNED ULONG *)Connectionless->IpxHeader.SourceNetwork,
  1084. Connectionless->IpxHeader.SourceNode[0],
  1085. Connectionless->IpxHeader.SourceNode[1],
  1086. Connectionless->IpxHeader.SourceNode[2],
  1087. Connectionless->IpxHeader.SourceNode[3],
  1088. Connectionless->IpxHeader.SourceNode[4],
  1089. Connectionless->IpxHeader.SourceNode[5]));
  1090. Reserved = CONTAINING_RECORD (s, NB_SEND_RESERVED, PoolLinkage);
  1091. Packet = CONTAINING_RECORD (Reserved, NDIS_PACKET, ProtocolReserved[0]);
  1092. CTEAssert (Reserved->SendInProgress == FALSE);
  1093. Reserved->SendInProgress = TRUE;
  1094. Reserved->Type = SEND_TYPE_STATUS_RESPONSE;
  1095. Reserved->u.SR_AS.ActualBufferLength = AdapterStatusLength;
  1096. //
  1097. // Fill in the IPX header -- the default header has the broadcast
  1098. // address on net 0 as the destination IPX address.
  1099. //
  1100. Header = (NB_CONNECTIONLESS UNALIGNED *)
  1101. (&Reserved->Header[Device->Bind.IncludedHeaderOffset]);
  1102. RtlCopyMemory((PVOID)&Header->IpxHeader, &Device->ConnectionlessHeader, sizeof(IPX_HEADER));
  1103. RtlCopyMemory(&Header->IpxHeader.DestinationNetwork, Connectionless->IpxHeader.SourceNetwork, 12);
  1104. Header->IpxHeader.PacketLength[0] = (UCHAR)((sizeof(IPX_HEADER)+sizeof(NB_STATUS_RESPONSE)+ValidStatusLength) / 256);
  1105. Header->IpxHeader.PacketLength[1] = (UCHAR)((sizeof(IPX_HEADER)+sizeof(NB_STATUS_RESPONSE)+ValidStatusLength) % 256);
  1106. Header->IpxHeader.PacketType = 0x04;
  1107. //
  1108. // Now fill in the Netbios header.
  1109. //
  1110. Header->StatusResponse.ConnectionControlFlag = 0x00;
  1111. Header->StatusResponse.DataStreamType = NB_CMD_STATUS_RESPONSE;
  1112. NbiReferenceDevice (Device, DREF_STATUS_RESPONSE);
  1113. NdisChainBufferAtBack (Packet, AdapterStatusBuffer);
  1114. //
  1115. // Now send the frame, IPX will adjust the length of the
  1116. // first buffer correctly.
  1117. //
  1118. NdisAdjustBufferLength(NB_GET_NBHDR_BUFF(Packet), sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE));
  1119. if ((NdisStatus =
  1120. (*Device->Bind.SendHandler)(
  1121. RemoteAddress,
  1122. Packet,
  1123. sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE) + ValidStatusLength,
  1124. sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE))) != STATUS_PENDING) {
  1125. NbiSendComplete(
  1126. Packet,
  1127. NdisStatus);
  1128. }
  1129. } /* NbiProcessStatusQuery */
  1130. VOID
  1131. NbiSendStatusQuery(
  1132. IN PREQUEST Request
  1133. )
  1134. /*++
  1135. Routine Description:
  1136. This routine sends NB_CMD_STATUS_QUERY frames.
  1137. Arguments:
  1138. Request - Holds the request describing the remote adapter
  1139. status query. REQUEST_STATUS(Request) points
  1140. to the netbios cache entry for the remote name.
  1141. Return Value:
  1142. None.
  1143. --*/
  1144. {
  1145. PSINGLE_LIST_ENTRY s;
  1146. PNB_SEND_RESERVED Reserved;
  1147. PNDIS_PACKET Packet;
  1148. NB_CONNECTIONLESS UNALIGNED * Header;
  1149. NDIS_STATUS NdisStatus;
  1150. PNETBIOS_CACHE CacheName;
  1151. PIPX_LOCAL_TARGET LocalTarget;
  1152. PDEVICE Device = NbiDevice;
  1153. //
  1154. // Allocate a packet from the pool.
  1155. //
  1156. s = NbiPopSendPacket(Device, FALSE);
  1157. if (s == NULL) {
  1158. return;
  1159. }
  1160. Reserved = CONTAINING_RECORD (s, NB_SEND_RESERVED, PoolLinkage);
  1161. Packet = CONTAINING_RECORD (Reserved, NDIS_PACKET, ProtocolReserved[0]);
  1162. CTEAssert (Reserved->SendInProgress == FALSE);
  1163. Reserved->SendInProgress = TRUE;
  1164. Reserved->Type = SEND_TYPE_STATUS_QUERY;
  1165. CacheName = (PNETBIOS_CACHE)REQUEST_STATUSPTR(Request);
  1166. //
  1167. // Fill in the IPX header -- the default header has the broadcast
  1168. // address on net 0 as the destination IPX address.
  1169. //
  1170. Header = (NB_CONNECTIONLESS UNALIGNED *)
  1171. (&Reserved->Header[Device->Bind.IncludedHeaderOffset]);
  1172. RtlCopyMemory((PVOID)&Header->IpxHeader, &Device->ConnectionlessHeader, sizeof(IPX_HEADER));
  1173. RtlCopyMemory (Header->IpxHeader.DestinationNetwork, &CacheName->FirstResponse, 12);
  1174. LocalTarget = &CacheName->Networks[0].LocalTarget;
  1175. Header->IpxHeader.PacketLength[0] = (sizeof(IPX_HEADER)+sizeof(NB_STATUS_QUERY)) / 256;
  1176. Header->IpxHeader.PacketLength[1] = (sizeof(IPX_HEADER)+sizeof(NB_STATUS_QUERY)) % 256;
  1177. Header->IpxHeader.PacketType = 0x04;
  1178. //
  1179. // Now fill in the Netbios header.
  1180. //
  1181. Header->StatusResponse.ConnectionControlFlag = 0x00;
  1182. Header->StatusResponse.DataStreamType = NB_CMD_STATUS_QUERY;
  1183. NbiReferenceDevice (Device, DREF_STATUS_FRAME);
  1184. //
  1185. // Now send the frame, IPX will adjust the length of the
  1186. // first buffer correctly.
  1187. //
  1188. NdisAdjustBufferLength(NB_GET_NBHDR_BUFF(Packet), sizeof(IPX_HEADER) + sizeof(NB_STATUS_QUERY));
  1189. if ((NdisStatus =
  1190. (*Device->Bind.SendHandler)(
  1191. LocalTarget,
  1192. Packet,
  1193. sizeof(IPX_HEADER) + sizeof(NB_STATUS_QUERY),
  1194. sizeof(IPX_HEADER) + sizeof(NB_STATUS_QUERY))) != STATUS_PENDING) {
  1195. NbiSendComplete(
  1196. Packet,
  1197. NdisStatus);
  1198. }
  1199. } /* NbiProcessStatusQuery */
  1200. VOID
  1201. NbiProcessStatusResponse(
  1202. IN NDIS_HANDLE MacBindingHandle,
  1203. IN NDIS_HANDLE MacReceiveContext,
  1204. IN PIPX_LOCAL_TARGET RemoteAddress,
  1205. IN ULONG MacOptions,
  1206. IN PUCHAR LookaheadBuffer,
  1207. IN UINT LookaheadBufferSize,
  1208. IN UINT LookaheadBufferOffset,
  1209. IN UINT PacketSize
  1210. )
  1211. /*++
  1212. Routine Description:
  1213. This routine handles NB_CMD_STATUS_RESPONSE frames.
  1214. Arguments:
  1215. MacBindingHandle - A handle to use when calling NdisTransferData.
  1216. MacReceiveContext - A context to use when calling NdisTransferData.
  1217. RemoteAddress - The local target this packet was received from.
  1218. MacOptions - The MAC options for the underlying NDIS binding.
  1219. LookaheadBuffer - The lookahead buffer, starting at the IPX
  1220. header.
  1221. LookaheadBufferSize - The length of the lookahead data.
  1222. LookaheadBufferOffset - The offset to add when calling
  1223. NdisTransferData.
  1224. PacketSize - The total length of the packet, starting at the
  1225. IPX header.
  1226. Return Value:
  1227. None.
  1228. --*/
  1229. {
  1230. PDEVICE Device = NbiDevice;
  1231. CTELockHandle LockHandle;
  1232. PREQUEST AdapterStatusRequest;
  1233. PNETBIOS_CACHE CacheName;
  1234. PLIST_ENTRY p;
  1235. PSINGLE_LIST_ENTRY s;
  1236. PNDIS_BUFFER TargetBuffer;
  1237. ULONG TargetBufferLength, BytesToTransfer;
  1238. ULONG BytesTransferred;
  1239. NDIS_STATUS NdisStatus;
  1240. PNB_RECEIVE_RESERVED ReceiveReserved;
  1241. PNDIS_PACKET Packet;
  1242. BOOLEAN Found;
  1243. PNAME_BUFFER NameBuffer;
  1244. UINT i,NameCount = 0;
  1245. NB_CONNECTIONLESS UNALIGNED * Connectionless =
  1246. (NB_CONNECTIONLESS UNALIGNED *)LookaheadBuffer;
  1247. if (PacketSize < (sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE))) {
  1248. return;
  1249. }
  1250. //
  1251. // Find out how many names are there.
  1252. //
  1253. NameBuffer = (PNAME_BUFFER)(LookaheadBuffer + sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE) + sizeof(ADAPTER_STATUS));
  1254. if ( LookaheadBufferSize > sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE) + sizeof(ADAPTER_STATUS) ) {
  1255. NameCount = (LookaheadBufferSize - (sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE) + sizeof(ADAPTER_STATUS)) ) /
  1256. sizeof(NAME_BUFFER);
  1257. }
  1258. //
  1259. // Find a request queued to this remote. If there are
  1260. // multiple requests outstanding for the same name we
  1261. // should get multiple responses, so we only need to
  1262. // find one.
  1263. //
  1264. NB_GET_LOCK (&Device->Lock, &LockHandle);
  1265. Found = FALSE;
  1266. p = Device->ActiveAdapterStatus.Flink;
  1267. while (p != &Device->ActiveAdapterStatus) {
  1268. AdapterStatusRequest = LIST_ENTRY_TO_REQUEST(p);
  1269. p = p->Flink;
  1270. CacheName = (PNETBIOS_CACHE)REQUEST_STATUSPTR(AdapterStatusRequest);
  1271. if ( CacheName->Unique ) {
  1272. if (RtlEqualMemory(
  1273. &CacheName->FirstResponse,
  1274. Connectionless->IpxHeader.SourceNetwork,
  1275. 12)) {
  1276. Found = TRUE;
  1277. break;
  1278. }
  1279. } else if ( RtlEqualMemory( CacheName->NetbiosName,NetbiosBroadcastName,16)){
  1280. //
  1281. // It's a broadcast name. Any response is fine.
  1282. //
  1283. Found = TRUE;
  1284. break;
  1285. } else {
  1286. //
  1287. // It's group name. Make sure that this remote
  1288. // has this group name registered with him.
  1289. //
  1290. for (i =0;i<NameCount;i++) {
  1291. if ( (RtlEqualMemory(
  1292. CacheName->NetbiosName,
  1293. NameBuffer[i].name,
  1294. 16)) &&
  1295. (NameBuffer[i].name_flags & GROUP_NAME) ) {
  1296. Found = TRUE;
  1297. break;
  1298. }
  1299. }
  1300. }
  1301. }
  1302. if (!Found) {
  1303. NB_FREE_LOCK (&Device->Lock, LockHandle);
  1304. return;
  1305. }
  1306. NB_DEBUG2 (QUERY, ("Got response to AdapterStatus %lx\n", AdapterStatusRequest));
  1307. RemoveEntryList (REQUEST_LINKAGE(AdapterStatusRequest));
  1308. if (--CacheName->ReferenceCount == 0) {
  1309. NB_DEBUG2 (CACHE, ("Free delete name cache entry %lx\n", CacheName));
  1310. NbiFreeMemory(
  1311. CacheName,
  1312. sizeof(NETBIOS_CACHE) + ((CacheName->NetworksAllocated-1) * sizeof(NETBIOS_NETWORK)),
  1313. MEMORY_CACHE,
  1314. "Name deleted");
  1315. }
  1316. NB_FREE_LOCK (&Device->Lock, LockHandle);
  1317. s = NbiPopReceivePacket (Device);
  1318. if (s == NULL) {
  1319. REQUEST_INFORMATION (AdapterStatusRequest) = 0;
  1320. REQUEST_STATUS (AdapterStatusRequest) = STATUS_INSUFFICIENT_RESOURCES;
  1321. NbiCompleteRequest (AdapterStatusRequest);
  1322. NbiFreeRequest (Device, AdapterStatusRequest);
  1323. NbiDereferenceDevice (Device, DREF_STATUS_QUERY);
  1324. return;
  1325. }
  1326. ReceiveReserved = CONTAINING_RECORD (s, NB_RECEIVE_RESERVED, PoolLinkage);
  1327. Packet = CONTAINING_RECORD (ReceiveReserved, NDIS_PACKET, ProtocolReserved[0]);
  1328. //
  1329. // Initialize the receive packet.
  1330. //
  1331. ReceiveReserved->Type = RECEIVE_TYPE_ADAPTER_STATUS;
  1332. ReceiveReserved->u.RR_AS.Request = AdapterStatusRequest;
  1333. REQUEST_STATUS(AdapterStatusRequest) = STATUS_SUCCESS;
  1334. CTEAssert (!ReceiveReserved->TransferInProgress);
  1335. ReceiveReserved->TransferInProgress = TRUE;
  1336. //
  1337. // Now that we have a packet and a buffer, set up the transfer.
  1338. // We will complete the request when the transfer completes.
  1339. //
  1340. TargetBuffer = REQUEST_NDIS_BUFFER (AdapterStatusRequest);
  1341. NdisChainBufferAtFront (Packet, TargetBuffer);
  1342. NbiGetBufferChainLength (TargetBuffer, &TargetBufferLength);
  1343. BytesToTransfer = PacketSize - (sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE));
  1344. if (TargetBufferLength < BytesToTransfer) {
  1345. BytesToTransfer = TargetBufferLength;
  1346. REQUEST_STATUS(AdapterStatusRequest) = STATUS_BUFFER_OVERFLOW;
  1347. }
  1348. (*Device->Bind.TransferDataHandler) (
  1349. &NdisStatus,
  1350. MacBindingHandle,
  1351. MacReceiveContext,
  1352. LookaheadBufferOffset + (sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE)),
  1353. BytesToTransfer,
  1354. Packet,
  1355. &BytesTransferred);
  1356. if (NdisStatus != NDIS_STATUS_PENDING) {
  1357. #if DBG
  1358. if (NdisStatus == STATUS_SUCCESS) {
  1359. CTEAssert (BytesTransferred == BytesToTransfer);
  1360. }
  1361. #endif
  1362. NbiTransferDataComplete(
  1363. Packet,
  1364. NdisStatus,
  1365. BytesTransferred);
  1366. }
  1367. } /* NbiProcessStatusResponse */