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

2974 lines
100 KiB

  1. /*++
  2. Copyright (c) 1989, 1990, 1991 Microsoft Corporation
  3. Module Name:
  4. uframes.c
  5. Abstract:
  6. This module contains a routine called NbfProcessUi, that gets control
  7. from routines in DLC.C when a DLC UI frame is received. Here we
  8. decode the encapsulated connectionless NetBIOS frame and dispatch
  9. to the correct NetBIOS frame handler.
  10. The following frame types are cracked by routines in this module:
  11. o NBF_CMD_ADD_GROUP_NAME_QUERY
  12. o NBF_CMD_ADD_NAME_QUERY
  13. o NBF_CMD_NAME_IN_CONFLICT
  14. o NBF_CMD_STATUS_QUERY
  15. o NBF_CMD_TERMINATE_TRACE
  16. o NBF_CMD_DATAGRAM
  17. o NBF_CMD_DATAGRAM_BROADCAST
  18. o NBF_CMD_NAME_QUERY
  19. o NBF_CMD_ADD_NAME_RESPONSE
  20. o NBF_CMD_NAME_RECOGNIZED
  21. o NBF_CMD_STATUS_RESPONSE
  22. o NBF_CMD_TERMINATE_TRACE2
  23. Author:
  24. David Beaver (dbeaver) 1-July-1991
  25. Environment:
  26. Kernel mode, DISPATCH_LEVEL.
  27. Revision History:
  28. --*/
  29. #include "precomp.h"
  30. #pragma hdrstop
  31. VOID
  32. NbfListenTimeout(
  33. IN PKDPC Dpc,
  34. IN PVOID DeferredContext,
  35. IN PVOID SystemArgument1,
  36. IN PVOID SystemArgument2
  37. )
  38. /*++
  39. Routine Description:
  40. This routine is executed as a DPC at DISPATCH_LEVEL when the timeout
  41. period for the session setup after listening a connection occurs. This
  42. will occur if the remote has discovered our name and we do not get a
  43. connection started within some reasonable period of time. In this
  44. routine we simply tear down the connection (and, most likely, the link
  45. associated with it).
  46. Arguments:
  47. Dpc - Pointer to a system DPC object.
  48. DeferredContext - Pointer to the TP_CONNECTION block representing the
  49. request that has timed out.
  50. SystemArgument1 - Not used.
  51. SystemArgument2 - Not used.
  52. Return Value:
  53. none.
  54. --*/
  55. {
  56. PTP_CONNECTION Connection;
  57. Dpc, SystemArgument1, SystemArgument2; // prevent compiler warnings
  58. ENTER_NBF;
  59. Connection = (PTP_CONNECTION)DeferredContext;
  60. //
  61. // If this connection is being run down, then we can't do anything.
  62. //
  63. ACQUIRE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  64. if ((Connection->Flags2 & CONNECTION_FLAGS2_STOPPING) ||
  65. ((Connection->Flags & CONNECTION_FLAGS_WAIT_SI) == 0)) {
  66. //
  67. // The connection is stopping, or the SESSION_INITIALIZE
  68. // has already been processed.
  69. //
  70. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  71. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  72. NbfPrint1 ("ListenTimeout: connection %lx stopping.\n",
  73. Connection);
  74. }
  75. NbfDereferenceConnection ("Listen timeout, ignored", Connection, CREF_TIMER);
  76. LEAVE_NBF;
  77. return;
  78. }
  79. //
  80. // We connected to the link before sending the NAME_RECOGNIZED,
  81. // so we disconnect from it now.
  82. //
  83. #if DBG
  84. if (NbfDisconnectDebug) {
  85. STRING remoteName, localName;
  86. remoteName.Length = NETBIOS_NAME_LENGTH - 1;
  87. remoteName.Buffer = Connection->RemoteName;
  88. localName.Length = NETBIOS_NAME_LENGTH - 1;
  89. localName.Buffer = Connection->AddressFile->Address->NetworkName->NetbiosName;
  90. NbfPrint2( "NbfListenTimeout disconnecting connection to %S from %S\n",
  91. &remoteName, &localName );
  92. }
  93. #endif
  94. //
  95. // BUBGUG: This is really ugly and I doubt it is correct.
  96. //
  97. if ((Connection->Flags2 & CONNECTION_FLAGS2_ACCEPTED) != 0) {
  98. //
  99. // This connection is up, we stop it.
  100. //
  101. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  102. NbfPrint1 ("ListenTimeout: connection %lx, accepted.\n",
  103. Connection);
  104. }
  105. //
  106. // Set this so that the client will get a disconnect
  107. // indication.
  108. //
  109. Connection->Flags2 |= CONNECTION_FLAGS2_REQ_COMPLETED;
  110. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  111. NbfStopConnection (Connection, STATUS_IO_TIMEOUT);
  112. } else if (Connection->Link != (PTP_LINK)NULL) {
  113. //
  114. // This connection is from a listen...we want to
  115. // silently reset the listen.
  116. //
  117. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  118. NbfPrint1 ("ListenTimeout: connection %lx, listen restarted.\n",
  119. Connection);
  120. }
  121. Connection->Flags &= ~CONNECTION_FLAGS_WAIT_SI;
  122. Connection->Flags2 &= ~CONNECTION_FLAGS2_REMOTE_VALID;
  123. Connection->Flags2 |= CONNECTION_FLAGS2_WAIT_NQ;
  124. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  125. NbfDereferenceConnection ("Timeout", Connection, CREF_LINK);
  126. (VOID)NbfDisconnectFromLink (Connection, FALSE);
  127. } else {
  128. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  129. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  130. NbfPrint1 ("ListenTimeout: connection %lx, link down.\n",
  131. Connection);
  132. }
  133. }
  134. NbfDereferenceConnection("Listen Timeout", Connection, CREF_TIMER);
  135. LEAVE_NBF;
  136. return;
  137. } /* ListenTimeout */
  138. NTSTATUS
  139. ProcessAddGroupNameQuery(
  140. IN PDEVICE_CONTEXT DeviceContext,
  141. IN PTP_ADDRESS Address,
  142. IN PNBF_HDR_CONNECTIONLESS Header,
  143. IN PHARDWARE_ADDRESS SourceAddress,
  144. IN PUCHAR SourceRouting,
  145. IN UINT SourceRoutingLength
  146. )
  147. /*++
  148. Routine Description:
  149. This routine processes an incoming ADD_GROUP_NAME_QUERY frame. Because
  150. our caller has already verified that the destination name in the frame
  151. matches the transport address passed to us, we must simply transmit an
  152. ADD_NAME_RESPONSE frame and exit with STATUS_ABANDONED.
  153. When we return STATUS_MORE_PROCESSING_REQUIRED, the caller of
  154. this routine will continue to call us for each address for the device
  155. context. When we return STATUS_SUCCESS, the caller will switch to the
  156. next address.
  157. When we return any other status code, including STATUS_ABANDONED, the
  158. caller will stop distributing the frame.
  159. Arguments:
  160. DeviceContext - Pointer to our device context.
  161. Address - Pointer to the transport address object.
  162. Header - Pointer to the connectionless NetBIOS header of the frame.
  163. SourceAddress - Pointer to the source hardware address in the received
  164. frame.
  165. SourceRouting - Pointer to the source routing information in
  166. the frame.
  167. SourceRoutingLength - Length of the source routing information.
  168. Return Value:
  169. NTSTATUS - status of operation.
  170. --*/
  171. {
  172. PTP_UI_FRAME RawFrame; // ptr to allocated connectionless frame.
  173. UINT HeaderLength;
  174. UCHAR TempSR[MAX_SOURCE_ROUTING];
  175. PUCHAR ResponseSR;
  176. UNREFERENCED_PARAMETER (SourceAddress);
  177. UNREFERENCED_PARAMETER (Address);
  178. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  179. NbfPrint2 ("ProcessAddGroupNameQuery %lx: [%.16s].\n", Address, Header->DestinationName);
  180. }
  181. //
  182. // Allocate a UI frame from the pool.
  183. //
  184. if (NbfCreateConnectionlessFrame (DeviceContext, &RawFrame) != STATUS_SUCCESS) {
  185. return STATUS_ABANDONED; // no resources to do this.
  186. }
  187. //
  188. // Build the MAC header. ADD_NAME_RESPONSE frames go out as
  189. // non-broadcast source routing.
  190. //
  191. if (SourceRouting != NULL) {
  192. RtlCopyMemory(
  193. TempSR,
  194. SourceRouting,
  195. SourceRoutingLength);
  196. MacCreateNonBroadcastReplySR(
  197. &DeviceContext->MacInfo,
  198. TempSR,
  199. SourceRoutingLength,
  200. &ResponseSR);
  201. } else {
  202. ResponseSR = NULL;
  203. }
  204. MacConstructHeader (
  205. &DeviceContext->MacInfo,
  206. RawFrame->Header,
  207. SourceAddress->Address,
  208. DeviceContext->LocalAddress.Address,
  209. sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS),
  210. ResponseSR,
  211. SourceRoutingLength,
  212. &HeaderLength);
  213. //
  214. // Build the DLC UI frame header.
  215. //
  216. NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
  217. HeaderLength += sizeof(DLC_FRAME);
  218. //
  219. // Build the Netbios header.
  220. //
  221. ConstructAddNameResponse (
  222. (PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
  223. NETBIOS_NAME_TYPE_GROUP, // type of name is GROUP.
  224. RESPONSE_CORR(Header), // correlator from rec'd frame.
  225. (PUCHAR)Header->SourceName); // NetBIOS name being responded to.
  226. HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
  227. //
  228. // Munge the packet length and send it.
  229. //
  230. NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
  231. NbfSendUIFrame (
  232. DeviceContext,
  233. RawFrame,
  234. FALSE); // no loopback.
  235. return STATUS_ABANDONED; // don't forward frame to other addr's.
  236. } /* ProcessAddGroupNameQuery */
  237. NTSTATUS
  238. ProcessAddNameQuery(
  239. IN PDEVICE_CONTEXT DeviceContext,
  240. IN PTP_ADDRESS Address,
  241. IN PNBF_HDR_CONNECTIONLESS Header,
  242. IN PHARDWARE_ADDRESS SourceAddress,
  243. IN PUCHAR SourceRouting,
  244. IN UINT SourceRoutingLength
  245. )
  246. /*++
  247. Routine Description:
  248. This routine processes an incoming ADD_NAME_QUERY frame. Because
  249. our caller has already verified that the destination name in the frame
  250. matches the transport address passed to us, we must simply transmit an
  251. ADD_NAME_RESPONSE frame and exit with STATUS_ABANDONED.
  252. When we return STATUS_MORE_PROCESSING_REQUIRED, the caller of
  253. this routine will continue to call us for each address for the device
  254. context. When we return STATUS_SUCCESS, the caller will switch to the
  255. next address. When we return any other status code, including
  256. STATUS_ABANDONED, the caller will stop distributing the frame.
  257. Arguments:
  258. DeviceContext - Pointer to our device context.
  259. Address - Pointer to the transport address object.
  260. Header - Pointer to the connectionless NetBIOS header of the frame.
  261. SourceAddress - Pointer to the source hardware address in the received
  262. frame.
  263. SourceRouting - Pointer to the source routing information in
  264. the frame.
  265. SourceRoutingLength - Length of the source routing information.
  266. Return Value:
  267. NTSTATUS - status of operation.
  268. --*/
  269. {
  270. PTP_UI_FRAME RawFrame; // ptr to allocated connectionless frame.
  271. UINT HeaderLength;
  272. UCHAR TempSR[MAX_SOURCE_ROUTING];
  273. PUCHAR ResponseSR;
  274. Address, SourceAddress; // prevent compiler warnings
  275. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  276. NbfPrint2 ("ProcessAddNameQuery %lx: [%.16s].\n", Address, Header->DestinationName);
  277. }
  278. //
  279. // Allocate a UI frame from the pool.
  280. //
  281. if (NbfCreateConnectionlessFrame (DeviceContext, &RawFrame) != STATUS_SUCCESS) {
  282. return STATUS_ABANDONED; // no resources to do this.
  283. }
  284. //
  285. // Build the MAC header. ADD_NAME_RESPONSE frames go out as
  286. // non-broadcast source routing.
  287. //
  288. if (SourceRouting != NULL) {
  289. RtlCopyMemory(
  290. TempSR,
  291. SourceRouting,
  292. SourceRoutingLength);
  293. MacCreateNonBroadcastReplySR(
  294. &DeviceContext->MacInfo,
  295. TempSR,
  296. SourceRoutingLength,
  297. &ResponseSR);
  298. } else {
  299. ResponseSR = NULL;
  300. }
  301. MacConstructHeader (
  302. &DeviceContext->MacInfo,
  303. RawFrame->Header,
  304. SourceAddress->Address,
  305. DeviceContext->LocalAddress.Address,
  306. sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS),
  307. ResponseSR,
  308. SourceRoutingLength,
  309. &HeaderLength);
  310. //
  311. // Build the DLC UI frame header.
  312. //
  313. NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
  314. HeaderLength += sizeof(DLC_FRAME);
  315. //
  316. // Build the Netbios header.
  317. //
  318. ConstructAddNameResponse (
  319. (PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
  320. NETBIOS_NAME_TYPE_UNIQUE, // type of name is UNIQUE.
  321. RESPONSE_CORR(Header), // correlator from received frame.
  322. (PUCHAR)Header->SourceName); // NetBIOS name being responded to
  323. HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
  324. //
  325. // Munge the packet length and send it.
  326. //
  327. NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
  328. NbfSendUIFrame (
  329. DeviceContext,
  330. RawFrame,
  331. FALSE); // no loopback.
  332. return STATUS_ABANDONED; // don't forward frame to other addr's.
  333. } /* ProcessAddNameQuery */
  334. NTSTATUS
  335. ProcessNameInConflict(
  336. IN PDEVICE_CONTEXT DeviceContext,
  337. IN PTP_ADDRESS Address,
  338. IN PNBF_HDR_CONNECTIONLESS Header,
  339. IN PHARDWARE_ADDRESS SourceAddress,
  340. IN PUCHAR SourceRouting,
  341. IN UINT SourceRoutingLength
  342. )
  343. /*++
  344. Routine Description:
  345. This routine processes an incoming NAME_IN_CONFLICT frame.
  346. Although we can't disrupt any traffic on this address, it is considered
  347. invalid and cannot be used for any new address files or new connections.
  348. Therefore, we just mark the address as invalid.
  349. When we return STATUS_MORE_PROCESSING_REQUIRED, the caller of
  350. this routine will continue to call us for each address for the device
  351. context. When we return STATUS_SUCCESS, the caller will switch to the
  352. next address. When we return any other status code, including
  353. STATUS_ABANDONED, the caller will stop distributing the frame.
  354. Arguments:
  355. DeviceContext - Pointer to our device context.
  356. Address - Pointer to the transport address object.
  357. Header - Pointer to the connectionless NetBIOS header of the frame.
  358. SourceAddress - Pointer to the source hardware address in the received
  359. frame.
  360. SourceRouting - Pointer to the source routing information in
  361. the frame.
  362. SourceRoutingLength - Length of the source routing information.
  363. Return Value:
  364. NTSTATUS - status of operation.
  365. --*/
  366. {
  367. DeviceContext, Header, SourceAddress; // prevent compiler warnings
  368. //
  369. // Ignore this if we are registering/deregistering (the name will
  370. // go away anyway) or if we have already marked this name as
  371. // in conflict and logged an error.
  372. //
  373. if (Address->Flags & (ADDRESS_FLAGS_REGISTERING | ADDRESS_FLAGS_DEREGISTERING | ADDRESS_FLAGS_CONFLICT)) {
  374. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  375. NbfPrint2 ("ProcessNameInConflict %lx: address marked [%.16s].\n", Address, Header->SourceName);
  376. }
  377. return STATUS_ABANDONED;
  378. }
  379. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  380. NbfPrint2 ("ProcessNameInConflict %lx: [%.16s].\n", Address, Header->SourceName);
  381. }
  382. #if 0
  383. ACQUIRE_DPC_SPIN_LOCK (&Address->SpinLock);
  384. Address->Flags |= ADDRESS_FLAGS_CONFLICT;
  385. RELEASE_DPC_SPIN_LOCK (&Address->SpinLock);
  386. DbgPrint ("NBF: Name-in-conflict on <%.16s> from ", Header->DestinationName);
  387. DbgPrint ("%2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n",
  388. SourceAddress->Address[0],
  389. SourceAddress->Address[1],
  390. SourceAddress->Address[2],
  391. SourceAddress->Address[3],
  392. SourceAddress->Address[4],
  393. SourceAddress->Address[5]);
  394. #endif
  395. NbfWriteGeneralErrorLog(
  396. Address->Provider,
  397. EVENT_TRANSPORT_BAD_PROTOCOL,
  398. 2,
  399. STATUS_DUPLICATE_NAME,
  400. L"NAME_IN_CONFLICT",
  401. 16/sizeof(ULONG),
  402. (PULONG)(Header->DestinationName));
  403. return STATUS_ABANDONED;
  404. } /* ProcessNameInConflict */
  405. NTSTATUS
  406. NbfIndicateDatagram(
  407. IN PDEVICE_CONTEXT DeviceContext,
  408. IN PTP_ADDRESS Address,
  409. IN PUCHAR Dsdu,
  410. IN ULONG Length
  411. )
  412. /*++
  413. Routine Description:
  414. This routine processes an incoming DATAGRAM or DATAGRAM_BROADCAST frame.
  415. BROADCAST and normal datagrams have the same receive logic, except
  416. for broadcast datagrams Address will be the broadcast address.
  417. When we return STATUS_MORE_PROCESSING_REQUIRED, the caller of
  418. this routine will continue to call us for each address for the device
  419. context. When we return STATUS_SUCCESS, the caller will switch to the
  420. next address. When we return any other status code, including
  421. STATUS_ABANDONED, the caller will stop distributing the frame.
  422. Arguments:
  423. DeviceContext - Pointer to our device context.
  424. Address - Pointer to the transport address object.
  425. Dsdu - Pointer to a Mdl buffer that contains the received datagram.
  426. The first byte of information in the buffer is the first byte in
  427. the NetBIOS connectionless header, and it is already negotiated that
  428. the data link layer will provide at least the entire NetBIOS header
  429. as contiguous data.
  430. Length - The length of the MDL pointed to by Dsdu.
  431. Return Value:
  432. NTSTATUS - status of operation.
  433. --*/
  434. {
  435. NTSTATUS status;
  436. PLIST_ENTRY p, q;
  437. PIRP irp;
  438. PIO_STACK_LOCATION irpSp;
  439. ULONG IndicateBytesCopied, MdlBytesCopied, BytesToCopy;
  440. TA_NETBIOS_ADDRESS SourceName;
  441. TA_NETBIOS_ADDRESS DestinationName;
  442. PTDI_CONNECTION_INFORMATION remoteInformation;
  443. ULONG returnLength;
  444. PTP_ADDRESS_FILE addressFile, prevaddressFile;
  445. PTDI_CONNECTION_INFORMATION DatagramInformation;
  446. TDI_ADDRESS_NETBIOS * DatagramAddress;
  447. PNBF_HDR_CONNECTIONLESS Header = (PNBF_HDR_CONNECTIONLESS)Dsdu;
  448. IF_NBFDBG (NBF_DEBUG_DATAGRAMS) {
  449. NbfPrint0 ("NbfIndicateDatagram: Entered.\n");
  450. }
  451. //
  452. // If this datagram wasn't big enough for a transport header, then don't
  453. // let the caller look at any data.
  454. //
  455. if (Length < sizeof(NBF_HDR_CONNECTIONLESS)) {
  456. IF_NBFDBG (NBF_DEBUG_DATAGRAMS) {
  457. NbfPrint0 ("NbfIndicateDatagram: Short datagram abandoned.\n");
  458. }
  459. return STATUS_ABANDONED;
  460. }
  461. //
  462. // Update our statistics.
  463. //
  464. ++DeviceContext->Statistics.DatagramsReceived;
  465. ADD_TO_LARGE_INTEGER(
  466. &DeviceContext->Statistics.DatagramBytesReceived,
  467. Length - sizeof(NBF_HDR_CONNECTIONLESS));
  468. //
  469. // Call the client's ReceiveDatagram indication handler. He may
  470. // want to accept the datagram that way.
  471. //
  472. TdiBuildNetbiosAddress ((PUCHAR)Header->SourceName, FALSE, &SourceName);
  473. TdiBuildNetbiosAddress ((PUCHAR)Header->DestinationName, FALSE, &DestinationName);
  474. ACQUIRE_DPC_SPIN_LOCK (&Address->SpinLock);
  475. //
  476. // Find the first open address file in the list.
  477. //
  478. p = Address->AddressFileDatabase.Flink;
  479. while (p != &Address->AddressFileDatabase) {
  480. addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
  481. if (addressFile->State != ADDRESSFILE_STATE_OPEN) {
  482. p = p->Flink;
  483. continue;
  484. }
  485. NbfReferenceAddressFile(addressFile);
  486. break;
  487. }
  488. while (p != &Address->AddressFileDatabase) {
  489. //
  490. // do we have a datagram receive request outstanding? If so, we will
  491. // satisfy it first. We run through the receive datagram queue
  492. // until we find a datagram with no remote address or with
  493. // this sender's address as its remote address.
  494. //
  495. for (q = addressFile->ReceiveDatagramQueue.Flink;
  496. q != &addressFile->ReceiveDatagramQueue;
  497. q = q->Flink) {
  498. irp = CONTAINING_RECORD (q, IRP, Tail.Overlay.ListEntry);
  499. DatagramInformation = ((PTDI_REQUEST_KERNEL_RECEIVEDG)
  500. &((IoGetCurrentIrpStackLocation(irp))->
  501. Parameters))->ReceiveDatagramInformation;
  502. if (DatagramInformation &&
  503. (DatagramInformation->RemoteAddress) &&
  504. (DatagramAddress = NbfParseTdiAddress(DatagramInformation->RemoteAddress, FALSE)) &&
  505. (!RtlEqualMemory(
  506. Header->SourceName,
  507. DatagramAddress->NetbiosName,
  508. NETBIOS_NAME_LENGTH))) {
  509. continue;
  510. }
  511. break;
  512. }
  513. if (q != &addressFile->ReceiveDatagramQueue) {
  514. KIRQL cancelIrql;
  515. RemoveEntryList (q);
  516. RELEASE_DPC_SPIN_LOCK (&Address->SpinLock);
  517. IF_NBFDBG (NBF_DEBUG_DATAGRAMS) {
  518. NbfPrint0 ("NbfIndicateDatagram: Receive datagram request found, copying.\n");
  519. }
  520. //
  521. // Copy the actual user data.
  522. //
  523. MdlBytesCopied = 0;
  524. BytesToCopy = Length - sizeof(NBF_HDR_CONNECTIONLESS);
  525. if ((BytesToCopy > 0) && irp->MdlAddress) {
  526. status = TdiCopyBufferToMdl (
  527. Dsdu,
  528. sizeof(NBF_HDR_CONNECTIONLESS), // offset
  529. BytesToCopy, // length
  530. irp->MdlAddress,
  531. 0,
  532. &MdlBytesCopied);
  533. } else {
  534. status = STATUS_SUCCESS;
  535. }
  536. //
  537. // Copy the addressing information.
  538. //
  539. irpSp = IoGetCurrentIrpStackLocation (irp);
  540. remoteInformation =
  541. ((PTDI_REQUEST_KERNEL_RECEIVEDG)(&irpSp->Parameters))->
  542. ReturnDatagramInformation;
  543. if (remoteInformation != NULL) {
  544. try {
  545. if (remoteInformation->RemoteAddressLength != 0) {
  546. if (remoteInformation->RemoteAddressLength >=
  547. sizeof (TA_NETBIOS_ADDRESS)) {
  548. RtlCopyMemory (
  549. (PTA_NETBIOS_ADDRESS)remoteInformation->RemoteAddress,
  550. &SourceName,
  551. sizeof (TA_NETBIOS_ADDRESS));
  552. returnLength = sizeof(TA_NETBIOS_ADDRESS);
  553. remoteInformation->RemoteAddressLength = returnLength;
  554. } else {
  555. RtlCopyMemory (
  556. (PTA_NETBIOS_ADDRESS)remoteInformation->RemoteAddress,
  557. &SourceName,
  558. remoteInformation->RemoteAddressLength);
  559. returnLength = remoteInformation->RemoteAddressLength;
  560. remoteInformation->RemoteAddressLength = returnLength;
  561. }
  562. } else {
  563. returnLength = 0;
  564. }
  565. status = STATUS_SUCCESS;
  566. } except (EXCEPTION_EXECUTE_HANDLER) {
  567. returnLength = 0;
  568. status = GetExceptionCode ();
  569. }
  570. }
  571. IoAcquireCancelSpinLock(&cancelIrql);
  572. IoSetCancelRoutine(irp, NULL);
  573. IoReleaseCancelSpinLock(cancelIrql);
  574. irp->IoStatus.Information = MdlBytesCopied;
  575. irp->IoStatus.Status = STATUS_SUCCESS;
  576. IoCompleteRequest (irp, IO_NETWORK_INCREMENT);
  577. NbfDereferenceAddress ("Receive DG done", Address, AREF_REQUEST);
  578. } else {
  579. RELEASE_DPC_SPIN_LOCK (&Address->SpinLock);
  580. //
  581. // no receive datagram requests; is there a kernel client?
  582. //
  583. if (addressFile->RegisteredReceiveDatagramHandler) {
  584. IndicateBytesCopied = 0;
  585. status = (*addressFile->ReceiveDatagramHandler)(
  586. addressFile->ReceiveDatagramHandlerContext,
  587. sizeof (TA_NETBIOS_ADDRESS),
  588. &SourceName,
  589. 0,
  590. NULL,
  591. TDI_RECEIVE_COPY_LOOKAHEAD,
  592. Length - sizeof(NBF_HDR_CONNECTIONLESS), // indicated
  593. Length - sizeof(NBF_HDR_CONNECTIONLESS), // available
  594. &IndicateBytesCopied,
  595. Dsdu + sizeof(NBF_HDR_CONNECTIONLESS),
  596. &irp);
  597. if (status == STATUS_SUCCESS) {
  598. //
  599. // The client accepted the datagram and so we're done.
  600. //
  601. } else if (status == STATUS_DATA_NOT_ACCEPTED) {
  602. //
  603. // The client did not accept the datagram and we need to satisfy
  604. // a TdiReceiveDatagram, if possible.
  605. //
  606. IF_NBFDBG (NBF_DEBUG_DATAGRAMS) {
  607. NbfPrint0 ("NbfIndicateDatagram: Picking off a rcv datagram request from this address.\n");
  608. }
  609. status = STATUS_MORE_PROCESSING_REQUIRED;
  610. } else if (status == STATUS_MORE_PROCESSING_REQUIRED) {
  611. //
  612. // The client returned an IRP that we should queue up to the
  613. // address to satisfy the request.
  614. //
  615. irp->IoStatus.Status = STATUS_PENDING; // init status information.
  616. irp->IoStatus.Information = 0;
  617. irpSp = IoGetCurrentIrpStackLocation (irp); // get current stack loctn.
  618. if ((irpSp->MajorFunction != IRP_MJ_INTERNAL_DEVICE_CONTROL) ||
  619. (irpSp->MinorFunction != TDI_RECEIVE_DATAGRAM)) {
  620. irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  621. return status;
  622. }
  623. //
  624. // Now copy the actual user data.
  625. //
  626. MdlBytesCopied = 0;
  627. BytesToCopy = Length - sizeof(NBF_HDR_CONNECTIONLESS) - IndicateBytesCopied;
  628. if ((BytesToCopy > 0) && irp->MdlAddress) {
  629. status = TdiCopyBufferToMdl (
  630. Dsdu,
  631. sizeof(NBF_HDR_CONNECTIONLESS) + IndicateBytesCopied,
  632. BytesToCopy,
  633. irp->MdlAddress,
  634. 0,
  635. &MdlBytesCopied);
  636. } else {
  637. status = STATUS_SUCCESS;
  638. }
  639. irp->IoStatus.Information = MdlBytesCopied;
  640. irp->IoStatus.Status = status;
  641. LEAVE_NBF;
  642. IoCompleteRequest (irp, IO_NETWORK_INCREMENT);
  643. ENTER_NBF;
  644. }
  645. }
  646. }
  647. //
  648. // Save this to dereference it later.
  649. //
  650. prevaddressFile = addressFile;
  651. //
  652. // Reference the next address file on the list, so it
  653. // stays around.
  654. //
  655. ACQUIRE_DPC_SPIN_LOCK (&Address->SpinLock);
  656. p = p->Flink;
  657. while (p != &Address->AddressFileDatabase) {
  658. addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
  659. if (addressFile->State != ADDRESSFILE_STATE_OPEN) {
  660. p = p->Flink;
  661. continue;
  662. }
  663. NbfReferenceAddressFile(addressFile);
  664. break;
  665. }
  666. RELEASE_DPC_SPIN_LOCK (&Address->SpinLock);
  667. //
  668. // Now dereference the previous address file with
  669. // the lock released.
  670. //
  671. NbfDereferenceAddressFile (prevaddressFile);
  672. ACQUIRE_DPC_SPIN_LOCK (&Address->SpinLock);
  673. } // end of while loop
  674. RELEASE_DPC_SPIN_LOCK (&Address->SpinLock);
  675. return status; // to dispatcher.
  676. } /* NbfIndicateDatagram */
  677. NTSTATUS
  678. ProcessNameQuery(
  679. IN PDEVICE_CONTEXT DeviceContext,
  680. IN PTP_ADDRESS Address,
  681. IN PNBF_HDR_CONNECTIONLESS Header,
  682. IN PHARDWARE_ADDRESS SourceAddress,
  683. IN PUCHAR SourceRouting,
  684. IN UINT SourceRoutingLength
  685. )
  686. /*++
  687. Routine Description:
  688. This routine processes an incoming NAME_QUERY frame. There are two
  689. types of NAME_QUERY frames, with basically the same layout. If the
  690. session number in the frame is 0, then the frame is really a request
  691. for information about the name, and not a request to establish a
  692. session. If the session number is non-zero, then the frame is a
  693. connection request that we use to satisfy a listen.
  694. With the new version of TDI, we now indicate the user that a request
  695. for connection has been received, iff there is no outstanding listen.
  696. If this does occur, the user can return a connection that is to be used
  697. to accept the connection on.
  698. When we return STATUS_MORE_PROCESSING_REQUIRED, the caller of
  699. this routine will continue to call us for each address for the device
  700. context. When we return STATUS_SUCCESS, the caller will switch to the
  701. next address. When we return any other status code, including
  702. STATUS_ABANDONED, the caller will stop distributing the frame.
  703. Arguments:
  704. DeviceContext - Pointer to our device context.
  705. Address - Pointer to the transport address object.
  706. Header - Pointer to the connectionless NetBIOS header of the frame.
  707. SourceAddress - Pointer to the source hardware address in the received
  708. frame.
  709. SourceRouting - Pointer to the source routing information in
  710. the frame.
  711. SourceRoutingLength - Length of the source routing information.
  712. Return Value:
  713. NTSTATUS - status of operation.
  714. --*/
  715. {
  716. NTSTATUS status;
  717. PTP_UI_FRAME RawFrame;
  718. PTP_CONNECTION Connection;
  719. PTP_LINK Link;
  720. UCHAR NameType;
  721. BOOLEAN ConnectIndicationBlocked = FALSE;
  722. PLIST_ENTRY p;
  723. UINT HeaderLength;
  724. PUCHAR GeneralSR;
  725. UINT GeneralSRLength;
  726. BOOLEAN UsedListeningConnection = FALSE;
  727. PTP_ADDRESS_FILE addressFile, prevaddressFile;
  728. PIRP acceptIrp;
  729. CONNECTION_CONTEXT connectionContext;
  730. TA_NETBIOS_ADDRESS RemoteAddress;
  731. //
  732. // If we are just registering or deregistering this address, then don't
  733. // allow state changes. Just throw the packet away, and let the frame
  734. // distributor try the next address.
  735. //
  736. // Also drop it if the address is in conflict.
  737. //
  738. if (Address->Flags & (ADDRESS_FLAGS_REGISTERING | ADDRESS_FLAGS_DEREGISTERING | ADDRESS_FLAGS_CONFLICT)) {
  739. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  740. NbfPrint2 ("ProcessNameQuery %lx: address not stable [%.16s].\n", Address, Header->SourceName);
  741. }
  742. return STATUS_SUCCESS;
  743. }
  744. //
  745. // Process this differently depending on whether it is a find name
  746. // request or an incoming connection.
  747. //
  748. if (Header->Data2Low == 0) {
  749. //
  750. // This is a find-name request. Respond with a NAME_RECOGNIZED frame.
  751. //
  752. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  753. NbfPrint2 ("ProcessNameQuery %lx: find name [%.16s].\n", Address, Header->SourceName);
  754. }
  755. NbfSendNameRecognized(
  756. Address,
  757. 0, // LSN 0 == FIND_NAME response
  758. Header,
  759. SourceAddress,
  760. SourceRouting,
  761. SourceRoutingLength);
  762. return STATUS_ABANDONED; // don't allow multiple responses.
  763. } else { // (if Data2Low is non-zero)
  764. //
  765. // This is an incoming connection request. If we have a listening
  766. // connection on this address, then continue with the connection setup.
  767. // If there is no outstanding listen, then indicate any kernel mode
  768. // clients that want to know about this frame. If a listen was posted,
  769. // then a connection has already been set up for it. The LSN field of
  770. // the connection is set to 0, so we look for the first 0 LSN in the
  771. // database.
  772. //
  773. //
  774. // First, check if we already have an active connection with
  775. // this remote on this address. If so, we resend the NAME_RECOGNIZED
  776. // if we have not yet received the SESSION_INITIALIZE; otherwise
  777. // we ignore the frame.
  778. //
  779. //
  780. // If successful this adds a reference of type CREF_LISTENING.
  781. //
  782. if (Connection = NbfLookupRemoteName(Address, (PUCHAR)Header->SourceName, Header->Data2Low)) {
  783. //
  784. // We have an active connection on this guy, see if he
  785. // still appears to be waiting to a NAME_RECOGNIZED.
  786. //
  787. if (((Connection->Flags & CONNECTION_FLAGS_WAIT_SI) != 0) &&
  788. (Connection->Link != (PTP_LINK)NULL) &&
  789. (Connection->Link->State == LINK_STATE_ADM)) {
  790. //
  791. // Yes, he must have dropped a previous NAME_RECOGNIZED
  792. // so we send another one.
  793. //
  794. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  795. NbfPrint2("Dup NAME_QUERY found: %lx [%.16s]\n", Connection, Header->SourceName);
  796. }
  797. NbfSendNameRecognized(
  798. Address,
  799. Connection->Lsn,
  800. Header,
  801. SourceAddress,
  802. SourceRouting,
  803. SourceRoutingLength);
  804. } else {
  805. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  806. NbfPrint2("Dup NAME_QUERY ignored: %lx [%.16s]\n", Connection, Header->SourceName);
  807. }
  808. }
  809. NbfDereferenceConnection ("Lookup done", Connection, CREF_LISTENING);
  810. return STATUS_ABANDONED;
  811. }
  812. // If successful, this adds a reference which is removed before
  813. // this function returns.
  814. Connection = NbfLookupListeningConnection (Address, (PUCHAR)Header->SourceName);
  815. if (Connection == NULL) {
  816. //
  817. // not having a listening connection is not reason to bail out here.
  818. // we need to indicate to the user that a connect attempt occurred,
  819. // and see if there is a desire to use this connection. We
  820. // indicate in order to all address files that are
  821. // using this address.
  822. //
  823. // If we already have an indication pending on this address,
  824. // we ignore this frame (the NAME_QUERY may have come from
  825. // a different address, but we can't know that). Also, if
  826. // there is already an active connection on this remote
  827. // name, then we ignore the frame.
  828. //
  829. ACQUIRE_DPC_SPIN_LOCK (&Address->SpinLock);
  830. p = Address->AddressFileDatabase.Flink;
  831. while (p != &Address->AddressFileDatabase) {
  832. addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
  833. if (addressFile->State != ADDRESSFILE_STATE_OPEN) {
  834. p = p->Flink;
  835. continue;
  836. }
  837. NbfReferenceAddressFile(addressFile);
  838. break;
  839. }
  840. while (p != &Address->AddressFileDatabase) {
  841. RELEASE_DPC_SPIN_LOCK (&Address->SpinLock);
  842. if ((addressFile->RegisteredConnectionHandler == TRUE) &&
  843. (!addressFile->ConnectIndicationInProgress)) {
  844. TdiBuildNetbiosAddress (
  845. (PUCHAR)Header->SourceName,
  846. FALSE,
  847. &RemoteAddress);
  848. addressFile->ConnectIndicationInProgress = TRUE;
  849. //
  850. // we have a connection handler, now indicate that a connection
  851. // attempt occurred.
  852. //
  853. status = (addressFile->ConnectionHandler)(
  854. addressFile->ConnectionHandlerContext,
  855. sizeof (TA_NETBIOS_ADDRESS),
  856. &RemoteAddress,
  857. 0,
  858. NULL,
  859. 0,
  860. NULL,
  861. &connectionContext,
  862. &acceptIrp);
  863. if (status == STATUS_MORE_PROCESSING_REQUIRED) {
  864. //
  865. // the user has connected a currently open connection, but
  866. // we have to figure out which one it is.
  867. //
  868. //
  869. // If successful this adds a reference of type LISTENING
  870. // (the same what NbfLookupListeningConnection adds).
  871. //
  872. Connection = NbfLookupConnectionByContext (
  873. Address,
  874. connectionContext);
  875. if (Connection == NULL) {
  876. //
  877. // We have to tell the client that
  878. // his connection is bogus (or has this
  879. // already happened??).
  880. //
  881. NbfPrint0("STATUS_MORE_PROCESSING, connection not found\n");
  882. addressFile->ConnectIndicationInProgress = FALSE;
  883. acceptIrp->IoStatus.Status = STATUS_INVALID_CONNECTION;
  884. IoCompleteRequest (acceptIrp, IO_NETWORK_INCREMENT);
  885. goto whileend; // try next address file
  886. } else {
  887. if (Connection->AddressFile->Address != Address) {
  888. addressFile->ConnectIndicationInProgress = FALSE;
  889. NbfPrint0("STATUS_MORE_PROCESSING, address wrong\n");
  890. NbfStopConnection (Connection, STATUS_INVALID_ADDRESS);
  891. NbfDereferenceConnection("Bad Address", Connection, CREF_LISTENING);
  892. Connection = NULL;
  893. acceptIrp->IoStatus.Status = STATUS_INVALID_ADDRESS;
  894. IoCompleteRequest (acceptIrp, IO_NETWORK_INCREMENT);
  895. goto whileend; // try next address file
  896. }
  897. //
  898. // OK, we have a valid connection. If the response to
  899. // this connection was disconnect, we need to reject
  900. // the connection request and return. If it was accept
  901. // or not specified (to be done later), we simply
  902. // fall through and continue processing on the U Frame.
  903. //
  904. ACQUIRE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  905. if ((Connection->Flags2 & CONNECTION_FLAGS2_DISCONNECT) != 0) {
  906. // Connection->Flags2 &= ~CONNECTION_FLAGS2_DISCONNECT;
  907. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  908. NbfPrint0("STATUS_MORE_PROCESSING, disconnect\n");
  909. addressFile->ConnectIndicationInProgress = FALSE;
  910. NbfDereferenceConnection("Disconnecting", Connection, CREF_LISTENING);
  911. Connection = NULL;
  912. acceptIrp->IoStatus.Status = STATUS_INVALID_CONNECTION;
  913. IoCompleteRequest (acceptIrp, IO_NETWORK_INCREMENT);
  914. goto whileend; // try next address file
  915. }
  916. }
  917. //
  918. // Make a note that we have to set
  919. // addressFile->ConnectIndicationInProgress to
  920. // FALSE once the address is safely stored
  921. // in the connection.
  922. //
  923. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  924. NbfPrint4 ("ProcessNameQuery %lx: indicate DONE, context %lx conn %lx [%.16s].\n", Address, connectionContext, Connection, Header->SourceName);
  925. }
  926. IF_NBFDBG (NBF_DEBUG_SETUP) {
  927. NbfPrint6 ("Link is %x-%x-%x-%x-%x-%x\n",
  928. SourceAddress->Address[0],
  929. SourceAddress->Address[1],
  930. SourceAddress->Address[2],
  931. SourceAddress->Address[3],
  932. SourceAddress->Address[4],
  933. SourceAddress->Address[5]);
  934. }
  935. //
  936. // Set up our flags...we turn on REQ_COMPLETED
  937. // so that disconnect will be indicated if the
  938. // connection goes down before a session init
  939. // is received.
  940. //
  941. Connection->Flags2 &= ~CONNECTION_FLAGS2_STOPPING;
  942. Connection->Status = STATUS_PENDING;
  943. Connection->Flags2 |= (CONNECTION_FLAGS2_ACCEPTED |
  944. CONNECTION_FLAGS2_REQ_COMPLETED);
  945. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  946. ConnectIndicationBlocked = TRUE;
  947. NbfDereferenceAddressFile (addressFile);
  948. acceptIrp->IoStatus.Status = STATUS_SUCCESS;
  949. IoCompleteRequest (acceptIrp, IO_NETWORK_INCREMENT);
  950. ACQUIRE_DPC_SPIN_LOCK (&Address->SpinLock);
  951. break; // exit the while
  952. #if 0
  953. } else if (status == STATUS_EVENT_PENDING) {
  954. //
  955. // user has returned a connectionContext, use that for further
  956. // processing of the connection. First validate it so
  957. // we can know we won't just start a connection and never
  958. // finish.
  959. //
  960. //
  961. // If successful this adds a reference of type LISTENING
  962. // (the same what NbfLookupListeningConnection adds).
  963. //
  964. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  965. NbfPrint3 ("ProcessNameQuery %lx: indicate PENDING, context %lx [%.16s].\n", Address, connectionContext, Header->SourceName);
  966. }
  967. Connection = NbfLookupConnectionByContext (
  968. Address,
  969. connectionContext);
  970. if (Connection == NULL) {
  971. //
  972. // We have to tell the client that
  973. // his connection is bogus (or has this
  974. // already happened??).
  975. //
  976. NbfPrint0("STATUS_MORE_PROCESSING, but connection not found\n");
  977. addressFile->ConnectIndicationInProgress = FALSE;
  978. goto whileend; // try next address file.
  979. } else {
  980. if (Connection->AddressFile->Address != Address) {
  981. addressFile->ConnectIndicationInProgress = FALSE;
  982. NbfStopConnection (Connection, STATUS_INVALID_ADDRESS);
  983. NbfDereferenceConnection("Bad Address", Connection, CREF_LISTENING);
  984. Connection = NULL;
  985. goto whileend; // try next address file.
  986. }
  987. }
  988. //
  989. // Make a note that we have to set
  990. // addressFile->ConnectionIndicatInProgress to
  991. // FALSE once the address is safely stored
  992. // in the connection.
  993. //
  994. ConnectIndicationBlocked = TRUE;
  995. NbfDereferenceAddressFile (addressFile);
  996. ACQUIRE_DPC_SPIN_LOCK (&Address->SpinLock);
  997. break; // exit the while
  998. #endif
  999. } else if (status == STATUS_INSUFFICIENT_RESOURCES) {
  1000. //
  1001. // we know the address, but can't create a connection to
  1002. // use on it. This gets passed to the network as a response
  1003. // saying I'm here, but can't help.
  1004. //
  1005. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1006. NbfPrint2 ("ProcessNameQuery %lx: indicate RESOURCES [%.16s].\n", Address, Header->SourceName);
  1007. }
  1008. addressFile->ConnectIndicationInProgress = FALSE;
  1009. //
  1010. // We should send a NR with LSN 0xff, indicating
  1011. // no resources, but LM 2.0 does not interpret
  1012. // that correctly. So, we send LSN 0 (no listens)
  1013. // instead.
  1014. //
  1015. NbfSendNameRecognized(
  1016. Address,
  1017. 0,
  1018. Header,
  1019. SourceAddress,
  1020. SourceRouting,
  1021. SourceRoutingLength);
  1022. NbfDereferenceAddressFile (addressFile);
  1023. return STATUS_ABANDONED;
  1024. } else {
  1025. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1026. NbfPrint2 ("ProcessNameQuery %lx: indicate invalid [%.16s].\n", Address, Header->SourceName);
  1027. }
  1028. addressFile->ConnectIndicationInProgress = FALSE;
  1029. goto whileend; // try next address file
  1030. } // end status ifs
  1031. } else {
  1032. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1033. NbfPrint2 ("ProcessNameQuery %lx: no handler [%.16s].\n", Address, Header->SourceName);
  1034. }
  1035. goto whileend; // try next address file
  1036. } // end no indication handler
  1037. whileend:
  1038. //
  1039. // Jumping here is like a continue, except that the
  1040. // addressFile pointer is advanced correctly.
  1041. //
  1042. //
  1043. // Save this to dereference it later.
  1044. //
  1045. prevaddressFile = addressFile;
  1046. //
  1047. // Reference the next address file on the list, so it
  1048. // stays around.
  1049. //
  1050. ACQUIRE_DPC_SPIN_LOCK (&Address->SpinLock);
  1051. p = p->Flink;
  1052. while (p != &Address->AddressFileDatabase) {
  1053. addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
  1054. if (addressFile->State != ADDRESSFILE_STATE_OPEN) {
  1055. p = p->Flink;
  1056. continue;
  1057. }
  1058. NbfReferenceAddressFile(addressFile);
  1059. break;
  1060. }
  1061. RELEASE_DPC_SPIN_LOCK (&Address->SpinLock);
  1062. //
  1063. // Now dereference the previous address file with
  1064. // the lock released.
  1065. //
  1066. NbfDereferenceAddressFile (prevaddressFile);
  1067. ACQUIRE_DPC_SPIN_LOCK (&Address->SpinLock);
  1068. } // end of loop through the address files.
  1069. RELEASE_DPC_SPIN_LOCK (&Address->SpinLock);
  1070. if (Connection == NULL) {
  1071. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1072. NbfPrint2 ("ProcessNameQuery %lx: no connection [%.16s].\n", Address, Header->SourceName);
  1073. }
  1074. //
  1075. // We still did not find a connection after looping
  1076. // through the address files.
  1077. //
  1078. NbfSendNameRecognized(
  1079. Address,
  1080. 0, // LSN 0 == No listens
  1081. Header,
  1082. SourceAddress,
  1083. SourceRouting,
  1084. SourceRoutingLength);
  1085. //
  1086. // We used to return MORE_PROCESSING_REQUIRED, but
  1087. // since we matched with this address, no other
  1088. // address is going to match, so abandon it.
  1089. //
  1090. return STATUS_ABANDONED;
  1091. }
  1092. } else { // end connection == null
  1093. UsedListeningConnection = TRUE;
  1094. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1095. NbfPrint3 ("ProcessNameQuery %lx: found listen %lx: [%.16s].\n", Address, Connection, Header->SourceName);
  1096. }
  1097. }
  1098. //
  1099. // At this point the connection has a reference of type
  1100. // CREF_LISTENING. Allocate a UI frame from the pool.
  1101. //
  1102. status = NbfCreateConnectionlessFrame (DeviceContext, &RawFrame);
  1103. if (!NT_SUCCESS (status)) { // no resources to respond.
  1104. PANIC ("ProcessNameQuery: Can't get UI Frame, dropping query\n");
  1105. if (ConnectIndicationBlocked) {
  1106. addressFile->ConnectIndicationInProgress = FALSE;
  1107. }
  1108. if (UsedListeningConnection) {
  1109. Connection->Flags2 |= CONNECTION_FLAGS2_WAIT_NQ;
  1110. } else {
  1111. Connection->Flags2 |= CONNECTION_FLAGS2_REQ_COMPLETED;
  1112. NbfStopConnection (Connection, STATUS_INSUFFICIENT_RESOURCES);
  1113. }
  1114. NbfDereferenceConnection("Can't get UI Frame", Connection, CREF_LISTENING);
  1115. return STATUS_ABANDONED;
  1116. }
  1117. //
  1118. // Build the MAC header. NAME_RECOGNIZED frames go out as
  1119. // general-route source routing.
  1120. //
  1121. MacReturnGeneralRouteSR(
  1122. &DeviceContext->MacInfo,
  1123. &GeneralSR,
  1124. &GeneralSRLength);
  1125. MacConstructHeader (
  1126. &DeviceContext->MacInfo,
  1127. RawFrame->Header,
  1128. SourceAddress->Address,
  1129. DeviceContext->LocalAddress.Address,
  1130. sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS),
  1131. GeneralSR,
  1132. GeneralSRLength,
  1133. &HeaderLength);
  1134. //
  1135. // Build the DLC UI frame header.
  1136. //
  1137. NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
  1138. HeaderLength += sizeof(DLC_FRAME);
  1139. //
  1140. // Before we continue, store the remote guy's transport address
  1141. // into the TdiListen's TRANSPORT_CONNECTION buffer. This allows
  1142. // the client to determine who called him.
  1143. //
  1144. Connection->CalledAddress.NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  1145. TdiCopyLookaheadData(
  1146. Connection->CalledAddress.NetbiosName,
  1147. Header->SourceName,
  1148. 16,
  1149. DeviceContext->MacInfo.CopyLookahead ? TDI_RECEIVE_COPY_LOOKAHEAD : 0);
  1150. RtlCopyMemory( Connection->RemoteName, Connection->CalledAddress.NetbiosName, 16 );
  1151. Connection->Flags2 |= CONNECTION_FLAGS2_REMOTE_VALID;
  1152. if (ConnectIndicationBlocked) {
  1153. addressFile->ConnectIndicationInProgress = FALSE;
  1154. }
  1155. //
  1156. // Now formulate a reply.
  1157. //
  1158. NameType = (UCHAR)((Address->Flags & ADDRESS_FLAGS_GROUP) ?
  1159. NETBIOS_NAME_TYPE_GROUP : NETBIOS_NAME_TYPE_UNIQUE);
  1160. //
  1161. // We have a listening connection on the address now. Create a link
  1162. // for it to be associated with and make that link ready. Respond to
  1163. // the sender with a name_recognized frame. then we will receive our
  1164. // first connection-oriented frame, SESSION_INITIALIZE, handled
  1165. // in IFRAMES.C. Then we respond with SESSION_CONFIRM, and then
  1166. // the TdiListen completes.
  1167. //
  1168. // If successful, this adds a link reference which is removed
  1169. // in NbfDisconnectFromLink. It does NOT add a link reference.
  1170. status = NbfCreateLink (
  1171. DeviceContext,
  1172. SourceAddress, // remote hardware address.
  1173. SourceRouting,
  1174. SourceRoutingLength,
  1175. LISTENER_LINK, // for loopback link
  1176. &Link); // resulting link.
  1177. if (NT_SUCCESS (status)) { // link established.
  1178. ACQUIRE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1179. // If successful, this adds a connection reference
  1180. // which is removed in NbfDisconnectFromLink
  1181. if (((Connection->Flags2 & CONNECTION_FLAGS2_STOPPING) == 0) &&
  1182. ((status = NbfConnectToLink (Link, Connection)) == STATUS_SUCCESS)) {
  1183. Connection->Flags |= CONNECTION_FLAGS_WAIT_SI; // wait for SI.
  1184. Connection->Retries = 1;
  1185. Connection->Rsn = Header->Data2Low; // save remote LSN.
  1186. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1187. NbfWaitLink (Link); // start link going.
  1188. ConstructNameRecognized ( // build a good response.
  1189. (PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
  1190. NameType, // type of local name.
  1191. Connection->Lsn, // return our LSN.
  1192. RESPONSE_CORR(Header), // new xmit corr.
  1193. 0, // our response correlator (unused).
  1194. Header->DestinationName,// our NetBIOS name.
  1195. Header->SourceName); // his NetBIOS name.
  1196. HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
  1197. NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
  1198. //
  1199. // Now, to avoid problems with hanging listens, we'll start the
  1200. // connection timer and give a limited period for the connection
  1201. // to succeed. This avoids waiting forever for those first few
  1202. // frames to be exchanged. When the timeout occurs, the
  1203. // the dereference will cause the circuit to be torn down.
  1204. //
  1205. // The maximum delay we can accomodate on a link is
  1206. // NameQueryRetries * NameQueryTimeout (assuming the
  1207. // remote has the same timeous). There are three
  1208. // exchanges of packets until the SESSION_INITIALIZE
  1209. // shows up, to be safe we multiply by four.
  1210. //
  1211. NbfStartConnectionTimer(
  1212. Connection,
  1213. NbfListenTimeout,
  1214. 4 * DeviceContext->NameQueryRetries * DeviceContext->NameQueryTimeout);
  1215. NbfSendUIFrame (
  1216. DeviceContext,
  1217. RawFrame,
  1218. TRUE); // loopback if needed.
  1219. IF_NBFDBG (NBF_DEBUG_SETUP) {
  1220. NbfPrint2("Connection %lx on link %lx\n", Connection, Link);
  1221. }
  1222. NbfDereferenceConnection("ProcessNameQuery", Connection, CREF_LISTENING);
  1223. return STATUS_ABANDONED; // successful!
  1224. }
  1225. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1226. //
  1227. // We don't have a free LSN to allocate, so fall through to
  1228. // report "no resources".
  1229. //
  1230. // We did a link reference since NbfCreateLink succeeded,
  1231. // but since NbfConnectToLink failed we will never remove
  1232. // that reference in NbfDisconnectFromLink, so do it here.
  1233. NbfDereferenceLink ("No more LSNS", Link, LREF_CONNECTION);
  1234. ASSERT (Connection->Lsn == 0);
  1235. }
  1236. //
  1237. // If we fall through here, then we couldn't get resources to set
  1238. // up this connection, so just send him a "no resources" reply.
  1239. //
  1240. if (UsedListeningConnection) {
  1241. Connection->Flags2 |= CONNECTION_FLAGS2_WAIT_NQ; // put this back.
  1242. } else {
  1243. Connection->Flags2 |= CONNECTION_FLAGS2_REQ_COMPLETED;
  1244. NbfStopConnection (Connection, STATUS_INSUFFICIENT_RESOURCES);
  1245. }
  1246. //
  1247. // We should send a NR with LSN 0xff, indicating
  1248. // no resources, but LM 2.0 does not interpret
  1249. // that correctly. So, we send LSN 0 (no listens)
  1250. // instead.
  1251. //
  1252. ConstructNameRecognized (
  1253. (PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
  1254. NameType,
  1255. 0, // LSN=0 means no listens
  1256. RESPONSE_CORR(Header),
  1257. 0,
  1258. Header->DestinationName, // our NetBIOS name.
  1259. Header->SourceName); // his NetBIOS name.
  1260. HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
  1261. NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
  1262. NbfSendUIFrame (
  1263. DeviceContext,
  1264. RawFrame,
  1265. TRUE); // loopback if needed.
  1266. NbfDereferenceConnection("ProcessNameQuery done", Connection, CREF_LISTENING);
  1267. }
  1268. return STATUS_ABANDONED;
  1269. } /* ProcessNameQuery */
  1270. NTSTATUS
  1271. ProcessAddNameResponse(
  1272. IN PDEVICE_CONTEXT DeviceContext,
  1273. IN PTP_ADDRESS Address,
  1274. IN PNBF_HDR_CONNECTIONLESS Header,
  1275. IN PHARDWARE_ADDRESS SourceAddress,
  1276. IN PUCHAR SourceRouting,
  1277. IN UINT SourceRoutingLength
  1278. )
  1279. /*++
  1280. Routine Description:
  1281. This routine processes an incoming ADD_NAME_RESPONSE frame.
  1282. When we return STATUS_MORE_PROCESSING_REQUIRED, the caller of
  1283. this routine will continue to call us for each address for the device
  1284. context. When we return STATUS_SUCCESS, the caller will switch to the
  1285. next address. When we return any other status code, including
  1286. STATUS_ABANDONED, the caller will stop distributing the frame.
  1287. Arguments:
  1288. DeviceContext - Pointer to our device context.
  1289. Address - Pointer to the transport address object.
  1290. Header - Pointer to the connectionless NetBIOS header of the frame.
  1291. SourceAddress - Pointer to the source hardware address in the received
  1292. frame.
  1293. SourceRouting - Pointer to the source routing information in
  1294. the frame.
  1295. SourceRoutingLength - Length of the source routing information.
  1296. Return Value:
  1297. NTSTATUS - status of operation.
  1298. --*/
  1299. {
  1300. BOOLEAN SendNameInConflict = FALSE;
  1301. UNREFERENCED_PARAMETER(DeviceContext);
  1302. ACQUIRE_DPC_SPIN_LOCK (&Address->SpinLock);
  1303. //
  1304. // If we aren't trying to register this address, then the sender of
  1305. // this frame is bogus. We cannot allow our state to change based
  1306. // on the reception of a random frame.
  1307. //
  1308. if (!(Address->Flags & ADDRESS_FLAGS_REGISTERING)) {
  1309. RELEASE_DPC_SPIN_LOCK (&Address->SpinLock);
  1310. IF_NBFDBG (NBF_DEBUG_ADDRESS | NBF_DEBUG_UFRAMES) {
  1311. NbfPrint2("ProcessAddNameResponse %lx: not registering [%.16s]\n", Address, Header->SourceName);
  1312. }
  1313. return STATUS_ABANDONED; // just destroy the packet.
  1314. }
  1315. //
  1316. // Unfortunately, we are registering this address and another host
  1317. // on the network is also attempting to register the same NetBIOS
  1318. // name on the same network. Because he got to us first, we cannot
  1319. // register our name. Thus, the address must die. We set this flag
  1320. // and on the next timeout we will shut down.
  1321. //
  1322. Address->Flags |= ADDRESS_FLAGS_DUPLICATE_NAME;
  1323. if (Header->Data2Low == NETBIOS_NAME_TYPE_UNIQUE) {
  1324. //
  1325. // If we have already gotten a response from someone saying
  1326. // this address is uniquely owned, then make sure any future
  1327. // responses come from the same MAC address.
  1328. //
  1329. if ((*((LONG UNALIGNED *)Address->UniqueResponseAddress) == 0) &&
  1330. (*((SHORT UNALIGNED *)(&Address->UniqueResponseAddress[4])) == 0)) {
  1331. RtlMoveMemory(Address->UniqueResponseAddress, SourceAddress->Address, 6);
  1332. } else if (!RtlEqualMemory(
  1333. Address->UniqueResponseAddress,
  1334. SourceAddress->Address,
  1335. 6)) {
  1336. if (!Address->NameInConflictSent) {
  1337. SendNameInConflict = TRUE;
  1338. }
  1339. }
  1340. } else {
  1341. //
  1342. // For group names, make sure nobody else decided that it was
  1343. // a unique address.
  1344. //
  1345. if ((*((LONG UNALIGNED *)Address->UniqueResponseAddress) != 0) ||
  1346. (*((SHORT UNALIGNED *)(&Address->UniqueResponseAddress[4])) != 0)) {
  1347. if (!Address->NameInConflictSent) {
  1348. SendNameInConflict = TRUE;
  1349. }
  1350. }
  1351. }
  1352. RELEASE_DPC_SPIN_LOCK (&Address->SpinLock);
  1353. if (SendNameInConflict) {
  1354. Address->NameInConflictSent = TRUE;
  1355. NbfSendNameInConflict(
  1356. Address,
  1357. (PUCHAR)Header->DestinationName);
  1358. }
  1359. IF_NBFDBG (NBF_DEBUG_ADDRESS | NBF_DEBUG_UFRAMES) {
  1360. NbfPrint2("ProcessAddNameResponse %lx: stopping [%.16s]\n", Address, Header->SourceName);
  1361. }
  1362. return STATUS_ABANDONED; // done with this frame.
  1363. } /* ProcessAddNameResponse */
  1364. NTSTATUS
  1365. ProcessNameRecognized(
  1366. IN PDEVICE_CONTEXT DeviceContext,
  1367. IN PTP_ADDRESS Address,
  1368. IN PNBF_HDR_CONNECTIONLESS Header,
  1369. IN PHARDWARE_ADDRESS SourceAddress,
  1370. IN PUCHAR SourceRouting,
  1371. IN UINT SourceRoutingLength
  1372. )
  1373. /*++
  1374. Routine Description:
  1375. This routine processes an incoming NAME_RECOGNIZED frame. This frame
  1376. is received because we issued a NAME_QUERY frame to actively initiate
  1377. a connection with a remote host.
  1378. When we return STATUS_MORE_PROCESSING_REQUIRED, the caller of
  1379. this routine will continue to call us for each address for the device
  1380. context. When we return STATUS_SUCCESS, the caller will switch to the
  1381. next address. When we return any other status code, including
  1382. STATUS_ABANDONED, the caller will stop distributing the frame.
  1383. Arguments:
  1384. DeviceContext - Pointer to our device context.
  1385. Address - Pointer to the transport address object.
  1386. Header - Pointer to the connectionless NetBIOS header of the frame.
  1387. SourceAddress - Pointer to the source hardware address in the received
  1388. frame.
  1389. SourceRouting - Pointer to the source routing information in
  1390. the frame.
  1391. SourceRoutingLength - Length of the source routing information.
  1392. Return Value:
  1393. NTSTATUS - status of operation.
  1394. --*/
  1395. {
  1396. NTSTATUS status;
  1397. PTP_CONNECTION Connection;
  1398. PTP_LINK Link;
  1399. BOOLEAN TimerCancelled;
  1400. if (Address->Flags & (ADDRESS_FLAGS_REGISTERING | ADDRESS_FLAGS_DEREGISTERING | ADDRESS_FLAGS_CONFLICT)) {
  1401. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1402. NbfPrint2 ("ProcessNameRecognized %lx: address not stable [%.16s].\n", Address, Header->SourceName);
  1403. }
  1404. return STATUS_ABANDONED; // invalid address state, drop packet.
  1405. }
  1406. //
  1407. // Find names and connections both require a TP_CONNECTION to work.
  1408. // In either case, the ConnectionId field of the TP_CONNECTION object
  1409. // was sent as the response correlator in the NAME_QUERY frame, so
  1410. // we should get the same correlator back in this frame in the
  1411. // transmit correlator. Because this number is unique across
  1412. // all the connections on an address, we can determine if the frame
  1413. // was for this address or not.
  1414. //
  1415. // this causes a reference which is removed before this function returns.
  1416. Connection = NbfLookupConnectionById (
  1417. Address,
  1418. TRANSMIT_CORR(Header));
  1419. //
  1420. // has he been deleted while we were waiting?
  1421. //
  1422. if (Connection == NULL) {
  1423. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1424. NbfPrint2 ("ProcessNameRecognized %lx: no connection [%.16s].\n", Address, Header->SourceName);
  1425. }
  1426. return STATUS_ABANDONED;
  1427. }
  1428. //
  1429. // This frame is a response to a NAME_QUERY frame that we previously
  1430. // sent to him. Either he's returning "insufficient resources",
  1431. // indicating that a session cannot be established, or he's initiated
  1432. // his side of the connection.
  1433. //
  1434. ACQUIRE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1435. if ((Connection->Flags2 & CONNECTION_FLAGS2_STOPPING) != 0) {
  1436. //
  1437. // Connection is stopping, don't process this.
  1438. //
  1439. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1440. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1441. NbfPrint3 ("ProcessNameRecognized %lx: connection %lx stopping [%.16s].\n", Address, Connection, Header->SourceName);
  1442. }
  1443. NbfDereferenceConnection("Name Recognized, stopping", Connection, CREF_BY_ID);
  1444. return STATUS_ABANDONED;
  1445. }
  1446. if (Header->Data2Low == 0x00 ||
  1447. (Header->Data2Low > 0x00 && (Connection->Flags2 & CONNECTION_FLAGS2_WAIT_NR_FN))) { // no listens, or FIND.NAME response.
  1448. if (!(Connection->Flags2 & CONNECTION_FLAGS2_CONNECTOR)) {
  1449. //
  1450. // This is just a find name request, we are not trying to
  1451. // establish a connection. Currently, there is no reason
  1452. // for this to occur, so just save some room to add this
  1453. // extra feature later to support NETBIOS find name.
  1454. //
  1455. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1456. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1457. NbfPrint3 ("ProcessNameRecognized %lx: connection %lx not connector [%.16s].\n", Address, Connection, Header->SourceName);
  1458. }
  1459. NbfDereferenceConnection("Unexpected FN Response", Connection, CREF_BY_ID);
  1460. return STATUS_ABANDONED; // we processed the frame.
  1461. }
  1462. //
  1463. // We're setting up a session. If we are waiting for the first NAME
  1464. // RECOGNIZED, then setup the link and send the second NAME_QUERY.
  1465. // If we're waiting for the second NAME_RECOGNIZED, then he didn't
  1466. // have an LSN to finish the connection, so tear it down.
  1467. //
  1468. if (Connection->Flags2 & CONNECTION_FLAGS2_WAIT_NR_FN) {
  1469. //
  1470. // Now that we know the data link address of the remote host
  1471. // we're connecting to, we need to create a TP_LINK object to
  1472. // represent the data link between these two machines. If there
  1473. // is already a data link there, then the object will be reused.
  1474. //
  1475. Connection->Flags2 &= ~CONNECTION_FLAGS2_WAIT_NR_FN;
  1476. if (Header->Data2High == NETBIOS_NAME_TYPE_UNIQUE) {
  1477. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1478. //
  1479. // The Netbios address we are connecting to is a
  1480. // unique name
  1481. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1482. NbfPrint3 ("ProcessNameRecognized %lx: connection %lx send 2nd NQ [%.16s].\n", Address, Connection, Header->SourceName);
  1483. }
  1484. // If successful, this adds a link reference which is removed
  1485. // in NbfDisconnectFromLink
  1486. status = NbfCreateLink (
  1487. DeviceContext,
  1488. SourceAddress, // remote hardware address.
  1489. SourceRouting,
  1490. SourceRoutingLength,
  1491. CONNECTOR_LINK, // for loopback link
  1492. &Link); // resulting link.
  1493. if (!NT_SUCCESS (status)) { // no resources.
  1494. NbfStopConnection (Connection, STATUS_INSUFFICIENT_RESOURCES);
  1495. NbfDereferenceConnection ("No Resources for link", Connection, CREF_BY_ID);
  1496. return STATUS_ABANDONED;
  1497. }
  1498. ACQUIRE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1499. // If successful, this adds a connection reference which is
  1500. // removed in NbfDisconnectFromLink. It does NOT add a link ref.
  1501. if ((Connection->Flags2 & CONNECTION_FLAGS2_STOPPING) ||
  1502. ((status = NbfConnectToLink (Link, Connection)) != STATUS_SUCCESS)) {
  1503. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1504. // Connection stopping or no LSN's available on this link.
  1505. // We did a link reference since NbfCreateLink succeeded,
  1506. // but since NbfConnectToLink failed we will never remove
  1507. // that reference in NbfDisconnectFromLink, so do it here.
  1508. NbfDereferenceLink ("Can't connect to link", Link, LREF_CONNECTION); // most likely destroys this.
  1509. NbfStopConnection (Connection, STATUS_INSUFFICIENT_RESOURCES);
  1510. NbfDereferenceConnection ("Cant connect to link", Connection, CREF_BY_ID);
  1511. return STATUS_ABANDONED;
  1512. }
  1513. (VOID)InterlockedIncrement(&Link->NumberOfConnectors);
  1514. } else {
  1515. //
  1516. // We are connecting to a group name; we have to
  1517. // assign an LSN now, but we don't connect to
  1518. // the link until we get a committed name response.
  1519. //
  1520. Connection->Flags2 |= CONNECTION_FLAGS2_GROUP_LSN;
  1521. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1522. NbfPrint3 ("ProcessNameRecognized %lx: connection %lx send 2nd NQ GROUP [%.16s].\n", Address, Connection, Header->SourceName);
  1523. }
  1524. if (NbfAssignGroupLsn(Connection) != STATUS_SUCCESS) {
  1525. //
  1526. // Could not find an empty LSN; have to fail.
  1527. //
  1528. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1529. NbfStopConnection (Connection, STATUS_INSUFFICIENT_RESOURCES);
  1530. NbfDereferenceConnection("Can't get group LSN", Connection, CREF_BY_ID);
  1531. return STATUS_ABANDONED;
  1532. }
  1533. }
  1534. //
  1535. // Send the second NAME_QUERY frame, committing our LSN to
  1536. // the remote guy.
  1537. //
  1538. Connection->Flags2 |= CONNECTION_FLAGS2_WAIT_NR;
  1539. Connection->Retries = (USHORT)DeviceContext->NameQueryRetries;
  1540. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1541. NbfStartConnectionTimer (
  1542. Connection,
  1543. ConnectionEstablishmentTimeout,
  1544. DeviceContext->NameQueryTimeout);
  1545. KeQueryTickCount (&Connection->ConnectStartTime);
  1546. NbfSendNameQuery(
  1547. Connection,
  1548. TRUE);
  1549. NbfDereferenceConnection ("Done with lookup", Connection, CREF_BY_ID); // release lookup hold.
  1550. return STATUS_ABANDONED; // we processed the frame.
  1551. } else if (Connection->Flags2 & CONNECTION_FLAGS2_WAIT_NR) {
  1552. if (Connection->Link) {
  1553. if (RtlEqualMemory(
  1554. Connection->Link->HardwareAddress.Address,
  1555. SourceAddress->Address,
  1556. 6)) {
  1557. //
  1558. // Unfortunately, he's telling us that he doesn't have resources
  1559. // to allocate an LSN. We set a flag to record this and
  1560. // ignore the frame.
  1561. //
  1562. Connection->Flags2 |= CONNECTION_FLAGS2_NO_LISTEN;
  1563. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1564. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1565. NbfPrint3 ("ProcessNameRecognized %lx: connection %lx no listens [%.16s].\n", Address, Connection, Header->SourceName);
  1566. }
  1567. } else {
  1568. //
  1569. // This response comes from a different remote from the
  1570. // last one. For unique names this indicates a duplicate
  1571. // name on the network.
  1572. //
  1573. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1574. if (Header->Data2High == NETBIOS_NAME_TYPE_UNIQUE) {
  1575. if (!Address->NameInConflictSent) {
  1576. Address->NameInConflictSent = TRUE;
  1577. NbfSendNameInConflict(
  1578. Address,
  1579. (PUCHAR)Header->SourceName);
  1580. }
  1581. }
  1582. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1583. NbfPrint3 ("ProcessNameRecognized %lx: connection %lx name in conflict [%.16s].\n", Address, Connection, Header->SourceName);
  1584. }
  1585. }
  1586. } else {
  1587. //
  1588. // The response came back so fast the connection is
  1589. // not stable, ignore it.
  1590. //
  1591. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1592. }
  1593. NbfDereferenceConnection ("No remote resources", Connection, CREF_BY_ID); // release our lookup hold.
  1594. return STATUS_ABANDONED; // we processed the frame.
  1595. } else {
  1596. //
  1597. // Strange state. This should never happen, because we should be
  1598. // either waiting for a first or second name recognized frame. It
  1599. // is possible that the remote station received two frames because
  1600. // of our retransmits, and so he responded to both. Toss the frame.
  1601. //
  1602. if (Connection->Link) {
  1603. if (!RtlEqualMemory(
  1604. Connection->Link->HardwareAddress.Address,
  1605. SourceAddress->Address,
  1606. 6)) {
  1607. //
  1608. // This response comes from a different remote from the
  1609. // last one. For unique names this indicates a duplicate
  1610. // name on the network.
  1611. //
  1612. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1613. if (Header->Data2High == NETBIOS_NAME_TYPE_UNIQUE) {
  1614. if (!Address->NameInConflictSent) {
  1615. Address->NameInConflictSent = TRUE;
  1616. NbfSendNameInConflict(
  1617. Address,
  1618. (PUCHAR)Header->SourceName);
  1619. }
  1620. }
  1621. } else {
  1622. //
  1623. // This is the same remote, just ignore it.
  1624. //
  1625. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1626. }
  1627. } else {
  1628. //
  1629. // The response came back so fast the connection is
  1630. // not stable, ignore it.
  1631. //
  1632. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1633. }
  1634. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1635. NbfPrint3 ("ProcessNameRecognized %lx: connection %lx unexpected [%.16s].\n", Address, Connection, Header->SourceName);
  1636. }
  1637. NbfDereferenceConnection ("Tossing second response Done with lookup", Connection, CREF_BY_ID); // release our lookup hold.
  1638. return STATUS_ABANDONED; // we processed the frame.
  1639. }
  1640. } else if (Header->Data2Low == 0xff) { // no resources to complete connection.
  1641. if (Connection->Flags2 & CONNECTION_FLAGS2_WAIT_NR) {
  1642. //
  1643. // The recipient of our previously-sent NAME_QUERY frame that we sent
  1644. // to actively establish a connection has unfortunately run out of
  1645. // resources and cannot setup his side of the connection. We have to
  1646. // report "no resources" on the TdiConnect.
  1647. //
  1648. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1649. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1650. NbfPrint3 ("ProcessNameRecognized %lx: connection %lx no resources [%.16s].\n", Address, Connection, Header->SourceName);
  1651. }
  1652. IF_NBFDBG (NBF_DEBUG_TEARDOWN) {
  1653. NbfPrint0 ("ProcessNameRecognized: No resources.\n");
  1654. }
  1655. NbfStopConnection (Connection, STATUS_REMOTE_RESOURCES);
  1656. NbfDereferenceConnection ("No Resources", Connection, CREF_BY_ID); // release our lookup hold.
  1657. return STATUS_ABANDONED; // we processed the frame.
  1658. } else {
  1659. //
  1660. // We don't have a committed NAME_QUERY out there, so
  1661. // we ignore this frame.
  1662. //
  1663. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1664. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1665. NbfPrint3 ("ProcessNameRecognized %lx: connection %lx unexpected no resources [%.16s].\n", Address, Connection, Header->SourceName);
  1666. }
  1667. NbfDereferenceConnection ("Tossing second response Done with lookup", Connection, CREF_BY_ID); // release our lookup hold.
  1668. return STATUS_ABANDONED; // we processed the frame.
  1669. }
  1670. } else { // Data2Low is in the range 0x01-0xfe
  1671. if (Connection->Flags2 & CONNECTION_FLAGS2_WAIT_NR) {
  1672. //
  1673. // This is a successful response to a second NAME_QUERY we sent when
  1674. // we started processing a TdiConnect request. Clear the "waiting
  1675. // for Name Recognized" bit in the connection flags so that the
  1676. // connection timer doesn't blow us away when it times out.
  1677. //
  1678. // What prevents the timeout routine from running while
  1679. // we're in here and destroying the connection/link by
  1680. // calling NbfStopConnection?
  1681. //
  1682. Connection->Flags2 &= ~CONNECTION_FLAGS2_WAIT_NR;
  1683. //
  1684. // Before we continue, store the remote guy's transport address
  1685. // into the TdiConnect's TRANSPORT_CONNECTION buffer. This allows
  1686. // the client to determine who responded to his TdiConnect.
  1687. //
  1688. // this used to be done prior to sending the second
  1689. // Name Query, but since I fixed the Buffer2 problem, meaning
  1690. // that I really do overwrite the input buffer with the
  1691. // output buffer, that was screwing up the second query.
  1692. // Note that doing the copy after sending is probably unsafe
  1693. // in the case where the second Name Recognized arrives
  1694. // right away.
  1695. //
  1696. Connection->CalledAddress.NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  1697. TdiCopyLookaheadData(
  1698. Connection->CalledAddress.NetbiosName,
  1699. Header->SourceName,
  1700. 16,
  1701. DeviceContext->MacInfo.CopyLookahead ? TDI_RECEIVE_COPY_LOOKAHEAD : 0);
  1702. RtlCopyMemory( Connection->RemoteName, Header->SourceName, 16 );
  1703. Connection->Rsn = Header->Data2Low; // save his remote LSN.
  1704. //
  1705. // Save the correlator from the NR for eventual use in the
  1706. // SESSION_INITIALIZE frame.
  1707. //
  1708. Connection->NetbiosHeader.TransmitCorrelator = RESPONSE_CORR(Header);
  1709. //
  1710. // Cancel the timer; it would have no effect since WAIT_NR
  1711. // is not set, but there is no need for it to run. We cancel
  1712. // it with the lock held so it won't interfere with the
  1713. // timer's use when a connection is closing.
  1714. //
  1715. TimerCancelled = KeCancelTimer (&Connection->Timer);
  1716. if ((Connection->Flags2 & CONNECTION_FLAGS2_GROUP_LSN) != 0) {
  1717. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1718. //
  1719. // The Netbios address we are connecting to is a
  1720. // group name; we need to connect to the link
  1721. // now that we have the committed session.
  1722. //
  1723. // If successful, this adds a link reference which is removed
  1724. // in NbfDisconnectFromLink
  1725. status = NbfCreateLink (
  1726. DeviceContext,
  1727. SourceAddress, // remote hardware address.
  1728. SourceRouting,
  1729. SourceRoutingLength,
  1730. CONNECTOR_LINK, // for loopback link
  1731. &Link); // resulting link.
  1732. if (!NT_SUCCESS (status)) { // no resources.
  1733. NbfStopConnection (Connection, STATUS_INSUFFICIENT_RESOURCES);
  1734. NbfDereferenceConnection ("No Resources for link", Connection, CREF_BY_ID);
  1735. if (TimerCancelled) {
  1736. NbfDereferenceConnection("NR received, cancel timer", Connection, CREF_TIMER);
  1737. }
  1738. return STATUS_ABANDONED;
  1739. }
  1740. ACQUIRE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1741. // If successful, this adds a connection reference which is
  1742. // removed in NbfDisconnectFromLink. It does NOT add a link ref.
  1743. if ((Connection->Flags2 & CONNECTION_FLAGS2_STOPPING) ||
  1744. ((status = NbfConnectToLink (Link, Connection)) != STATUS_SUCCESS)) {
  1745. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1746. if (TimerCancelled) {
  1747. NbfDereferenceConnection("NR received, cancel timer", Connection, CREF_TIMER);
  1748. }
  1749. // Connection stopping or no LSN's available on this link.
  1750. // We did a link reference since NbfCreateLink succeeded,
  1751. // but since NbfConnectToLink failed we will never remove
  1752. // that reference in NbfDisconnectFromLink, so do it here.
  1753. NbfDereferenceLink ("Can't connect to link", Link, LREF_CONNECTION); // most likely destroys this.
  1754. NbfStopConnection (Connection, STATUS_INSUFFICIENT_RESOURCES);
  1755. NbfDereferenceConnection ("Cant connect to link", Connection, CREF_BY_ID);
  1756. return STATUS_ABANDONED;
  1757. }
  1758. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1759. (VOID)InterlockedIncrement(&Link->NumberOfConnectors);
  1760. } else {
  1761. //
  1762. // It's to a unique address, we set up the link
  1763. // before we sent out the committed NAME_QUERY.
  1764. //
  1765. Link = Connection->Link;
  1766. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1767. }
  1768. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1769. NbfPrint3 ("ProcessNameRecognized %lx: connection %lx session up! [%.16s].\n", Address, Connection, Header->SourceName);
  1770. }
  1771. //
  1772. // When we sent the committed NAME_QUERY, we stored that
  1773. // time in Connection->ConnectStartTime; we can now use
  1774. // that for a rough estimate of the link delay, if this
  1775. // is the first connection on the link. For async lines
  1776. // we do not do this because the delay introduced by the
  1777. // gateway messes up the timing.
  1778. //
  1779. if (!DeviceContext->MacInfo.MediumAsync) {
  1780. ACQUIRE_DPC_SPIN_LOCK (&Link->SpinLock);
  1781. if (Link->State == LINK_STATE_ADM) {
  1782. //
  1783. // HACK: Set the necessary variables in the link
  1784. // so that FakeUpdateBaseT1Timeout works. These
  1785. // variables are the same ones that FakeStartT1 sets.
  1786. //
  1787. Link->CurrentPollSize = Link->HeaderLength + sizeof(DLC_FRAME) + sizeof(NBF_HDR_CONNECTIONLESS);
  1788. Link->CurrentTimerStart = Connection->ConnectStartTime;
  1789. FakeUpdateBaseT1Timeout (Link);
  1790. }
  1791. RELEASE_DPC_SPIN_LOCK (&Link->SpinLock);
  1792. }
  1793. if (TimerCancelled) {
  1794. NbfDereferenceConnection("NR received, cancel timer", Connection, CREF_TIMER);
  1795. }
  1796. NbfActivateLink (Connection->Link); // start link going.
  1797. //
  1798. // We'll get control again in LINK.C when the data link has either
  1799. // been established, denied, or destroyed. This happens at I/O
  1800. // completion time from NbfCreateLink's PdiConnect request.
  1801. //
  1802. } else {
  1803. //
  1804. // We don't have a committed NAME_QUERY out there, so
  1805. // we ignore this frame.
  1806. //
  1807. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  1808. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1809. NbfPrint3 ("ProcessNameRecognized %lx: connection %lx unexpected session up! [%.16s].\n", Address, Connection, Header->SourceName);
  1810. }
  1811. NbfDereferenceConnection ("Tossing second response Done with lookup", Connection, CREF_BY_ID); // release our lookup hold.
  1812. return STATUS_ABANDONED; // we processed the frame.
  1813. }
  1814. }
  1815. NbfDereferenceConnection("ProcessNameRecognized lookup", Connection, CREF_BY_ID);
  1816. return STATUS_ABANDONED; // don't distribute packet.
  1817. } /* ProcessNameRecognized */
  1818. NTSTATUS
  1819. NbfProcessUi(
  1820. IN PDEVICE_CONTEXT DeviceContext,
  1821. IN PHARDWARE_ADDRESS SourceAddress,
  1822. IN PUCHAR Header,
  1823. IN PUCHAR DlcHeader,
  1824. IN ULONG DlcLength,
  1825. IN PUCHAR SourceRouting,
  1826. IN UINT SourceRoutingLength,
  1827. OUT PTP_ADDRESS * DatagramAddress
  1828. )
  1829. /*++
  1830. Routine Description:
  1831. This routine receives control from the data link provider as an
  1832. indication that a DLC UI-frame has been received on the data link.
  1833. Here we dispatch to the correct UI-frame handler.
  1834. Part of this routine's job is to optionally distribute the frame to
  1835. every address that needs to look at it.
  1836. We accomplish this by lock-stepping through the address database,
  1837. and for each address that matches the address this frame is aimed at,
  1838. calling the frame handler.
  1839. Arguments:
  1840. DeviceContext - Pointer to our device context.
  1841. SourceAddress - Pointer to the source hardware address in the received
  1842. frame.
  1843. Header - Points to the MAC header of the incoming packet.
  1844. DlcHeader - Points to the DLC header of the incoming packet.
  1845. DlcLength - Actual length in bytes of the packet, starting at the
  1846. DlcHeader.
  1847. SourceRouting - Source routing information in the MAC header.
  1848. SourceRoutingLength - The length of SourceRouting.
  1849. DatagramAddress - If this function returns STATUS_MORE_PROCESSING_
  1850. REQUIRED, this will be the address the datagram should be
  1851. indicated to.
  1852. Return Value:
  1853. NTSTATUS - status of operation.
  1854. --*/
  1855. {
  1856. PTP_ADDRESS Address;
  1857. PNBF_HDR_CONNECTIONLESS UiFrame;
  1858. NTSTATUS status;
  1859. PLIST_ENTRY Flink;
  1860. UCHAR MatchType;
  1861. BOOLEAN MatchedAddress;
  1862. PUCHAR MatchName;
  1863. ULONG NetbiosLength = DlcLength - 3;
  1864. UiFrame = (PNBF_HDR_CONNECTIONLESS)(DlcHeader + 3);
  1865. //
  1866. // Verify that this frame is long enough to examine and that it
  1867. // has the proper signature. We can't test the signature as a
  1868. // 16-bit word as specified in the NetBIOS Formats and Protocols
  1869. // manual because this is processor-dependent.
  1870. //
  1871. if ((NetbiosLength < sizeof (NBF_HDR_CONNECTIONLESS)) ||
  1872. (HEADER_LENGTH(UiFrame) != sizeof (NBF_HDR_CONNECTIONLESS)) ||
  1873. (HEADER_SIGNATURE(UiFrame) != NETBIOS_SIGNATURE)) {
  1874. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1875. NbfPrint0 ("NbfProcessUi: Bad size or NetBIOS signature.\n");
  1876. }
  1877. return STATUS_ABANDONED; // frame too small or too large.
  1878. }
  1879. //
  1880. // If this frame has a correlator with the high bit on, it was due
  1881. // to a FIND.NAME request; we don't handle those here since they
  1882. // are not per-address.
  1883. //
  1884. if ((UiFrame->Command == NBF_CMD_NAME_RECOGNIZED) &&
  1885. (TRANSMIT_CORR(UiFrame) & 0x8000)) {
  1886. //
  1887. // Make sure the frame is sent to our reserved address;
  1888. // if not, drop it.
  1889. //
  1890. if (RtlEqualMemory(
  1891. UiFrame->DestinationName,
  1892. DeviceContext->ReservedNetBIOSAddress,
  1893. NETBIOS_NAME_LENGTH)) {
  1894. return NbfProcessQueryNameRecognized(
  1895. DeviceContext,
  1896. Header,
  1897. UiFrame);
  1898. } else {
  1899. return STATUS_ABANDONED;
  1900. }
  1901. }
  1902. //
  1903. // If this is a STATUS_RESPONSE, process that separately.
  1904. //
  1905. if (UiFrame->Command == NBF_CMD_STATUS_RESPONSE) {
  1906. //
  1907. // Make sure the frame is sent to our reserved address;
  1908. // if not, drop it.
  1909. //
  1910. if (RtlEqualMemory(
  1911. UiFrame->DestinationName,
  1912. DeviceContext->ReservedNetBIOSAddress,
  1913. NETBIOS_NAME_LENGTH)) {
  1914. return STATUS_MORE_PROCESSING_REQUIRED;
  1915. } else {
  1916. return STATUS_ABANDONED;
  1917. }
  1918. }
  1919. //
  1920. // If this is a STATUS_QUERY, check if it is to our reserved
  1921. // address. If so, we process it. If not, we fall through to
  1922. // the normal checking. This ensures that queries to our
  1923. // reserved address are always processed, even if nobody
  1924. // has opened that address yet.
  1925. //
  1926. if (UiFrame->Command == NBF_CMD_STATUS_QUERY) {
  1927. if (RtlEqualMemory(
  1928. UiFrame->DestinationName,
  1929. DeviceContext->ReservedNetBIOSAddress,
  1930. NETBIOS_NAME_LENGTH)) {
  1931. return NbfProcessStatusQuery(
  1932. DeviceContext,
  1933. NULL,
  1934. UiFrame,
  1935. SourceAddress,
  1936. SourceRouting,
  1937. SourceRoutingLength);
  1938. }
  1939. }
  1940. //
  1941. // We have a valid connectionless NetBIOS protocol frame that's not a
  1942. // datagram, so deliver it to every address which matches the destination
  1943. // name in the frame. Some frames
  1944. // (NAME_QUERY) cannot be delivered to multiple recipients. Therefore,
  1945. // if a frame handler returns STATUS_MORE_PROCESSING_REQUIRED, we continue
  1946. // through the remaining addresses. Otherwise simply get out and assume
  1947. // that the frame was eaten. Thus, STATUS_SUCCESS means that the handler
  1948. // ate the frame and that no other addresses can have it.
  1949. //
  1950. //
  1951. // Determine what kind of lookup we want to do.
  1952. //
  1953. switch (UiFrame->Command) {
  1954. case NBF_CMD_NAME_QUERY:
  1955. case NBF_CMD_DATAGRAM:
  1956. case NBF_CMD_DATAGRAM_BROADCAST:
  1957. case NBF_CMD_ADD_NAME_QUERY:
  1958. case NBF_CMD_STATUS_QUERY:
  1959. case NBF_CMD_ADD_NAME_RESPONSE:
  1960. case NBF_CMD_NAME_RECOGNIZED:
  1961. MatchType = NETBIOS_NAME_TYPE_EITHER;
  1962. break;
  1963. case NBF_CMD_ADD_GROUP_NAME_QUERY:
  1964. case NBF_CMD_NAME_IN_CONFLICT:
  1965. MatchType = NETBIOS_NAME_TYPE_UNIQUE;
  1966. break;
  1967. default:
  1968. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  1969. NbfPrint1 ("NbfProcessUi: Frame delivered; Unrecognized command %x.\n",
  1970. UiFrame->Command);
  1971. }
  1972. return STATUS_SUCCESS;
  1973. break;
  1974. }
  1975. if ((UiFrame->Command == NBF_CMD_ADD_GROUP_NAME_QUERY) ||
  1976. (UiFrame->Command == NBF_CMD_ADD_NAME_QUERY)) {
  1977. MatchName = (PUCHAR)UiFrame->SourceName;
  1978. } else if (UiFrame->Command == NBF_CMD_DATAGRAM_BROADCAST) {
  1979. MatchName = NULL;
  1980. } else {
  1981. MatchName = (PUCHAR)UiFrame->DestinationName;
  1982. }
  1983. if (MatchName && DeviceContext->AddressCounts[MatchName[0]] == 0) {
  1984. status = STATUS_ABANDONED;
  1985. goto RasIndication;
  1986. }
  1987. MatchedAddress = FALSE;
  1988. ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
  1989. for (Flink = DeviceContext->AddressDatabase.Flink;
  1990. Flink != &DeviceContext->AddressDatabase;
  1991. Flink = Flink->Flink) {
  1992. Address = CONTAINING_RECORD (
  1993. Flink,
  1994. TP_ADDRESS,
  1995. Linkage);
  1996. if ((Address->Flags & ADDRESS_FLAGS_STOPPING) != 0) {
  1997. continue;
  1998. }
  1999. if (NbfMatchNetbiosAddress (Address,
  2000. MatchType,
  2001. MatchName)) {
  2002. NbfReferenceAddress ("UI Frame", Address, AREF_PROCESS_UI); // prevent address from being destroyed.
  2003. MatchedAddress = TRUE;
  2004. break;
  2005. }
  2006. }
  2007. RELEASE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
  2008. if (MatchedAddress) {
  2009. //
  2010. // If the datagram's destination name does not match the address's
  2011. // network name and TSAP components, then skip this address. Some
  2012. // frames have the source and destination names backwards for this
  2013. // algorithm, so we account for that here. Also, broadcast datagrams
  2014. // have no destination name in the frame, but get delivered to every
  2015. // address anyway.
  2016. //
  2017. #if 0
  2018. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  2019. USHORT i;
  2020. NbfPrint0 ("NbfProcessUi: SourceName: ");
  2021. for (i=0;i<16;i++) {
  2022. NbfPrint1 ("%c",UiFrame->SourceName[i]);
  2023. }
  2024. NbfPrint0 (" Destination Name:");
  2025. for (i=0;i<16;i++) {
  2026. NbfPrint1 ("%c",UiFrame->DestinationName[i]);
  2027. }
  2028. NbfPrint0 ("\n");
  2029. }
  2030. #endif
  2031. //
  2032. // Deliver the frame to the current address.
  2033. //
  2034. switch (UiFrame->Command) {
  2035. case NBF_CMD_NAME_QUERY:
  2036. status = ProcessNameQuery (
  2037. DeviceContext,
  2038. Address,
  2039. UiFrame,
  2040. SourceAddress,
  2041. SourceRouting,
  2042. SourceRoutingLength);
  2043. break;
  2044. case NBF_CMD_DATAGRAM:
  2045. case NBF_CMD_DATAGRAM_BROADCAST:
  2046. //
  2047. // Reference the datagram so it sticks around until the
  2048. // ReceiveComplete, when it is processed.
  2049. //
  2050. if ((Address->Flags & ADDRESS_FLAGS_CONFLICT) == 0) {
  2051. NbfReferenceAddress ("Datagram indicated", Address, AREF_PROCESS_DATAGRAM);
  2052. *DatagramAddress = Address;
  2053. status = STATUS_MORE_PROCESSING_REQUIRED;
  2054. } else {
  2055. status = STATUS_ABANDONED;
  2056. }
  2057. break;
  2058. case NBF_CMD_ADD_GROUP_NAME_QUERY:
  2059. //
  2060. // did this frame originate with us? If so, we don't want to
  2061. // do any processing of it.
  2062. //
  2063. if (RtlEqualMemory (
  2064. SourceAddress,
  2065. DeviceContext->LocalAddress.Address,
  2066. DeviceContext->MacInfo.AddressLength)) {
  2067. if ((Address->Flags & ADDRESS_FLAGS_REGISTERING) != 0) {
  2068. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  2069. NbfPrint0 ("NbfProcessUI: loopback AddGroupNameQuery dropped\n");
  2070. }
  2071. status = STATUS_ABANDONED;
  2072. break;
  2073. }
  2074. }
  2075. status = ProcessAddGroupNameQuery (
  2076. DeviceContext,
  2077. Address,
  2078. UiFrame,
  2079. SourceAddress,
  2080. SourceRouting,
  2081. SourceRoutingLength);
  2082. break;
  2083. case NBF_CMD_ADD_NAME_QUERY:
  2084. //
  2085. // did this frame originate with us? If so, we don't want to
  2086. // do any processing of it.
  2087. //
  2088. if (RtlEqualMemory (
  2089. SourceAddress,
  2090. DeviceContext->LocalAddress.Address,
  2091. DeviceContext->MacInfo.AddressLength)) {
  2092. if ((Address->Flags & ADDRESS_FLAGS_REGISTERING) != 0) {
  2093. IF_NBFDBG (NBF_DEBUG_UFRAMES) {
  2094. NbfPrint0 ("NbfProcessUI: loopback AddNameQuery dropped\n");
  2095. }
  2096. status = STATUS_ABANDONED;
  2097. break;
  2098. }
  2099. }
  2100. status = ProcessAddNameQuery (
  2101. DeviceContext,
  2102. Address,
  2103. UiFrame,
  2104. SourceAddress,
  2105. SourceRouting,
  2106. SourceRoutingLength);
  2107. break;
  2108. case NBF_CMD_NAME_IN_CONFLICT:
  2109. status = ProcessNameInConflict (
  2110. DeviceContext,
  2111. Address,
  2112. UiFrame,
  2113. SourceAddress,
  2114. SourceRouting,
  2115. SourceRoutingLength);
  2116. break;
  2117. case NBF_CMD_STATUS_QUERY:
  2118. status = NbfProcessStatusQuery (
  2119. DeviceContext,
  2120. Address,
  2121. UiFrame,
  2122. SourceAddress,
  2123. SourceRouting,
  2124. SourceRoutingLength);
  2125. break;
  2126. case NBF_CMD_ADD_NAME_RESPONSE:
  2127. status = ProcessAddNameResponse (
  2128. DeviceContext,
  2129. Address,
  2130. UiFrame,
  2131. SourceAddress,
  2132. SourceRouting,
  2133. SourceRoutingLength);
  2134. break;
  2135. case NBF_CMD_NAME_RECOGNIZED:
  2136. status = ProcessNameRecognized (
  2137. DeviceContext,
  2138. Address,
  2139. UiFrame,
  2140. SourceAddress,
  2141. SourceRouting,
  2142. SourceRoutingLength);
  2143. break;
  2144. default:
  2145. ASSERT(FALSE);
  2146. } /* switch on NetBIOS frame command code */
  2147. NbfDereferenceAddress ("Done", Address, AREF_PROCESS_UI); // done with previous address.
  2148. } else {
  2149. status = STATUS_ABANDONED;
  2150. }
  2151. RasIndication:;
  2152. //
  2153. // Let the RAS clients have a crack at this if they want
  2154. //
  2155. if (DeviceContext->IndicationQueuesInUse) {
  2156. //
  2157. // If RAS has datagram indications posted, and this is a
  2158. // datagram that nobody wanted, then receive it anyway.
  2159. //
  2160. if ((UiFrame->Command == NBF_CMD_DATAGRAM) &&
  2161. (status == STATUS_ABANDONED)) {
  2162. *DatagramAddress = NULL;
  2163. status = STATUS_MORE_PROCESSING_REQUIRED;
  2164. } else if ((UiFrame->Command == NBF_CMD_ADD_NAME_QUERY) ||
  2165. (UiFrame->Command == NBF_CMD_ADD_GROUP_NAME_QUERY) ||
  2166. (UiFrame->Command == NBF_CMD_NAME_QUERY)) {
  2167. NbfActionQueryIndication(
  2168. DeviceContext,
  2169. UiFrame);
  2170. }
  2171. }
  2172. return status;
  2173. } /* NbfProcessUi */