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.

2528 lines
62 KiB

  1. /*++
  2. Copyright (c) 1989, 1990, 1991 Microsoft Corporation
  3. Module Name:
  4. framesnd.c
  5. Abstract:
  6. This module contains routines which build and send NetBIOS Frames Protocol
  7. frames and data link frames for other modules. These routines call on the
  8. ones in FRAMECON.C to do the construction work.
  9. Author:
  10. David Beaver (dbeaver) 1-July-1991
  11. Environment:
  12. Kernel mode
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #if DBG
  18. ULONG NbfSendsIssued = 0;
  19. ULONG NbfSendsCompletedInline = 0;
  20. ULONG NbfSendsCompletedOk = 0;
  21. ULONG NbfSendsCompletedFail = 0;
  22. ULONG NbfSendsPended = 0;
  23. ULONG NbfSendsCompletedAfterPendOk = 0;
  24. ULONG NbfSendsCompletedAfterPendFail = 0;
  25. ULONG NbfPacketPanic = 0;
  26. #endif
  27. NTSTATUS
  28. NbfSendAddNameQuery(
  29. IN PTP_ADDRESS Address
  30. )
  31. /*++
  32. Routine Description:
  33. This routine sends a ADD_NAME_QUERY frame to register the specified
  34. address.
  35. Arguments:
  36. Address - Pointer to a transport address object.
  37. Return Value:
  38. none.
  39. --*/
  40. {
  41. NTSTATUS Status;
  42. PDEVICE_CONTEXT DeviceContext;
  43. PTP_UI_FRAME RawFrame;
  44. PUCHAR SingleSR;
  45. UINT SingleSRLength;
  46. UINT HeaderLength;
  47. DeviceContext = Address->Provider;
  48. //
  49. // Allocate a UI frame from the pool.
  50. //
  51. Status = NbfCreateConnectionlessFrame (DeviceContext, &RawFrame);
  52. if (!NT_SUCCESS (Status)) { // couldn't make frame.
  53. return STATUS_INSUFFICIENT_RESOURCES;
  54. }
  55. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  56. NbfPrint3 ("NbfSendAddNameQuery: Sending Frame: %lx, NdisPacket: %lx MacHeader: %lx\n",
  57. RawFrame, RawFrame->NdisPacket, RawFrame->Header);
  58. }
  59. //
  60. // Build the MAC header. ADD_NAME_QUERY frames go out as
  61. // single-route source routing.
  62. //
  63. MacReturnSingleRouteSR(
  64. &DeviceContext->MacInfo,
  65. &SingleSR,
  66. &SingleSRLength);
  67. MacConstructHeader (
  68. &DeviceContext->MacInfo,
  69. RawFrame->Header,
  70. DeviceContext->NetBIOSAddress.Address,
  71. DeviceContext->LocalAddress.Address,
  72. sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS),
  73. SingleSR,
  74. SingleSRLength,
  75. &HeaderLength);
  76. //
  77. // Build the DLC UI frame header.
  78. //
  79. NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
  80. HeaderLength += sizeof(DLC_FRAME);
  81. //
  82. // Build the appropriate Netbios header based on the type
  83. // of the address.
  84. //
  85. if ((Address->Flags & ADDRESS_FLAGS_GROUP) != 0) {
  86. ConstructAddGroupNameQuery (
  87. (PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
  88. 0, // correlator we don't use.
  89. Address->NetworkName->NetbiosName);
  90. } else {
  91. ConstructAddNameQuery (
  92. (PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
  93. 0, // correlator we don't use.
  94. Address->NetworkName->NetbiosName);
  95. }
  96. HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
  97. //
  98. // Munge the packet length and send the it.
  99. //
  100. NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
  101. NbfSendUIFrame (
  102. DeviceContext,
  103. RawFrame,
  104. FALSE); // no loopback (MC frame).
  105. return STATUS_SUCCESS;
  106. } /* NbfSendAddNameQuery */
  107. VOID
  108. NbfSendNameQuery(
  109. IN PTP_CONNECTION Connection,
  110. IN BOOLEAN SourceRoutingOptional
  111. )
  112. /*++
  113. Routine Description:
  114. This routine sends a NAME_QUERY frame of the appropriate type given the
  115. state of the specified connection.
  116. Arguments:
  117. Connection - Pointer to a transport connection object.
  118. SourceRoutingOptional - TRUE if source routing should be removed if
  119. we are configured that way.
  120. Return Value:
  121. none.
  122. --*/
  123. {
  124. NTSTATUS Status;
  125. PDEVICE_CONTEXT DeviceContext;
  126. PTP_ADDRESS Address;
  127. PTP_UI_FRAME RawFrame;
  128. PUCHAR NameQuerySR;
  129. UINT NameQuerySRLength;
  130. PUCHAR NameQueryAddress;
  131. UINT HeaderLength;
  132. UCHAR Lsn;
  133. UCHAR NameType;
  134. Address = Connection->AddressFile->Address;
  135. DeviceContext = Address->Provider;
  136. //
  137. // Allocate a UI frame from the pool.
  138. //
  139. Status = NbfCreateConnectionlessFrame(DeviceContext, &RawFrame);
  140. if (!NT_SUCCESS (Status)) { // couldn't make frame.
  141. return;
  142. }
  143. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  144. NbfPrint2 ("NbfSendNameQuery: Sending Frame: %lx, NdisPacket: %lx\n",
  145. RawFrame, RawFrame->NdisPacket);
  146. }
  147. //
  148. // Build the MAC header.
  149. //
  150. if (((Connection->Flags2 & CONNECTION_FLAGS2_WAIT_NR) != 0) &&
  151. ((Connection->Flags2 & CONNECTION_FLAGS2_GROUP_LSN) == 0)) {
  152. //
  153. // This is the second find name to a unique name; this
  154. // means that we already have a link and we can send this
  155. // frame directed to it.
  156. //
  157. ASSERT (Connection->Link != NULL);
  158. MacReturnSourceRouting(
  159. &DeviceContext->MacInfo,
  160. Connection->Link->Header,
  161. &NameQuerySR,
  162. &NameQuerySRLength);
  163. NameQueryAddress = Connection->Link->HardwareAddress.Address;
  164. } else {
  165. //
  166. // Standard NAME_QUERY frames go out as
  167. // single-route source routing, except if
  168. // it is optional and we are configured
  169. // that way.
  170. //
  171. if (SourceRoutingOptional &&
  172. Connection->Provider->MacInfo.QueryWithoutSourceRouting) {
  173. NameQuerySR = NULL;
  174. NameQuerySRLength = 0;
  175. } else {
  176. MacReturnSingleRouteSR(
  177. &DeviceContext->MacInfo,
  178. &NameQuerySR,
  179. &NameQuerySRLength);
  180. }
  181. NameQueryAddress = DeviceContext->NetBIOSAddress.Address;
  182. }
  183. MacConstructHeader (
  184. &DeviceContext->MacInfo,
  185. RawFrame->Header,
  186. NameQueryAddress,
  187. DeviceContext->LocalAddress.Address,
  188. sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS),
  189. NameQuerySR,
  190. NameQuerySRLength,
  191. &HeaderLength);
  192. //
  193. // Build the DLC UI frame header.
  194. //
  195. NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
  196. HeaderLength += sizeof(DLC_FRAME);
  197. //
  198. // Build the Netbios header.
  199. //
  200. Lsn = (UCHAR)((Connection->Flags2 & CONNECTION_FLAGS2_WAIT_NR_FN) ?
  201. NAME_QUERY_LSN_FIND_NAME : Connection->Lsn);
  202. NameType = (UCHAR)((Connection->AddressFile->Address->Flags & ADDRESS_FLAGS_GROUP) ?
  203. NETBIOS_NAME_TYPE_GROUP : NETBIOS_NAME_TYPE_UNIQUE);
  204. ConstructNameQuery (
  205. (PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
  206. NameType, // type of our name.
  207. Lsn, // calculated, above.
  208. (USHORT)Connection->ConnectionId, // corr. in 1st NAME_RECOGNIZED.
  209. Address->NetworkName->NetbiosName, // NetBIOS name of sender.
  210. Connection->CalledAddress.NetbiosName); // NetBIOS name of receiver.
  211. HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
  212. //
  213. // Munge the packet length and send the it.
  214. //
  215. NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
  216. NbfSendUIFrame (
  217. DeviceContext,
  218. RawFrame,
  219. FALSE); // no loopback (MC frame)
  220. } /* NbfSendNameQuery */
  221. VOID
  222. NbfSendNameRecognized(
  223. IN PTP_ADDRESS Address,
  224. IN UCHAR LocalSessionNumber, // LSN assigned to session.
  225. IN PNBF_HDR_CONNECTIONLESS Header,
  226. IN PHARDWARE_ADDRESS SourceAddress,
  227. IN PUCHAR SourceRouting,
  228. IN UINT SourceRoutingLength
  229. )
  230. /*++
  231. Routine Description:
  232. This routine sends a NAME_RECOGNIZED frame of the appropriate type
  233. in response to the NAME_QUERY pointed to by Header.
  234. Arguments:
  235. Address - Pointer to a transport address object.
  236. LocalSessionNumber - The LSN to use in the frame.
  237. Header - Pointer to the connectionless NetBIOS header of the
  238. NAME_QUERY frame.
  239. SourceAddress - Pointer to the source hardware address in the received
  240. frame.
  241. SourceRoutingInformation - Pointer to source routing information, if any.
  242. Return Value:
  243. none.
  244. --*/
  245. {
  246. NTSTATUS Status;
  247. PDEVICE_CONTEXT DeviceContext;
  248. PTP_UI_FRAME RawFrame;
  249. UINT HeaderLength;
  250. PUCHAR ReplySR;
  251. UINT ReplySRLength;
  252. UCHAR TempSR[MAX_SOURCE_ROUTING];
  253. UCHAR NameType;
  254. DeviceContext = Address->Provider;
  255. //
  256. // Allocate a UI frame from the pool.
  257. //
  258. Status = NbfCreateConnectionlessFrame (DeviceContext, &RawFrame);
  259. if (!NT_SUCCESS (Status)) { // couldn't make frame.
  260. return;
  261. }
  262. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  263. NbfPrint2 ("NbfSendNameRecognized: Sending Frame: %lx, NdisPacket: %lx\n",
  264. RawFrame, RawFrame->NdisPacket);
  265. }
  266. //
  267. // Build the MAC header. NAME_RECOGNIZED frames go out as
  268. // directed source routing unless configured for general-route.
  269. //
  270. if (DeviceContext->MacInfo.AllRoutesNameRecognized) {
  271. MacReturnGeneralRouteSR(
  272. &DeviceContext->MacInfo,
  273. &ReplySR,
  274. &ReplySRLength);
  275. } else {
  276. if (SourceRouting != NULL) {
  277. RtlCopyMemory(
  278. TempSR,
  279. SourceRouting,
  280. SourceRoutingLength);
  281. MacCreateNonBroadcastReplySR(
  282. &DeviceContext->MacInfo,
  283. TempSR,
  284. SourceRoutingLength,
  285. &ReplySR);
  286. ReplySRLength = SourceRoutingLength;
  287. } else {
  288. ReplySR = NULL;
  289. }
  290. }
  291. MacConstructHeader (
  292. &DeviceContext->MacInfo,
  293. RawFrame->Header,
  294. SourceAddress->Address,
  295. DeviceContext->LocalAddress.Address,
  296. sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS),
  297. ReplySR,
  298. ReplySRLength,
  299. &HeaderLength);
  300. //
  301. // Build the DLC UI frame header.
  302. //
  303. NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
  304. HeaderLength += sizeof(DLC_FRAME);
  305. //
  306. // Build the Netbios header.
  307. //
  308. NameType = (UCHAR)((Address->Flags & ADDRESS_FLAGS_GROUP) ?
  309. NETBIOS_NAME_TYPE_GROUP : NETBIOS_NAME_TYPE_UNIQUE);
  310. ConstructNameRecognized ( // build a good response.
  311. (PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
  312. NameType, // type of local name.
  313. LocalSessionNumber, // return our LSN.
  314. RESPONSE_CORR(Header), // new xmit corr.
  315. 0, // our response correlator (unused).
  316. Header->DestinationName, // our NetBIOS name.
  317. Header->SourceName); // his NetBIOS name.
  318. //
  319. // Use Address->NetworkName->Address[0].Address[0].NetbiosName
  320. // instead of Header->DestinationName?
  321. //
  322. HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
  323. //
  324. // Munge the packet length and send the it.
  325. //
  326. NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
  327. NbfSendUIFrame (
  328. DeviceContext,
  329. RawFrame,
  330. FALSE); // no loopback (MC frame)
  331. } /* NbfSendNameRecognized */
  332. VOID
  333. NbfSendNameInConflict(
  334. IN PTP_ADDRESS Address,
  335. IN PUCHAR ConflictingName
  336. )
  337. /*++
  338. Routine Description:
  339. This routine sends a NAME_IN_CONFLICT frame.
  340. Arguments:
  341. Address - Pointer to a transport address object.
  342. ConflictingName - The NetBIOS name which is in conflict.
  343. Return Value:
  344. none.
  345. --*/
  346. {
  347. NTSTATUS Status;
  348. PDEVICE_CONTEXT DeviceContext;
  349. PTP_UI_FRAME RawFrame;
  350. UINT HeaderLength;
  351. PUCHAR SingleSR;
  352. UINT SingleSRLength;
  353. DeviceContext = Address->Provider;
  354. //
  355. // Allocate a UI frame from the pool.
  356. //
  357. Status = NbfCreateConnectionlessFrame (DeviceContext, &RawFrame);
  358. if (!NT_SUCCESS (Status)) { // couldn't make frame.
  359. return;
  360. }
  361. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  362. NbfPrint2 ("NbfSendNameRecognized: Sending Frame: %lx, NdisPacket: %lx\n",
  363. RawFrame, RawFrame->NdisPacket);
  364. }
  365. //
  366. // Build the MAC header. ADD_NAME_QUERY frames go out as
  367. // single-route source routing.
  368. //
  369. MacReturnSingleRouteSR(
  370. &DeviceContext->MacInfo,
  371. &SingleSR,
  372. &SingleSRLength);
  373. MacConstructHeader (
  374. &DeviceContext->MacInfo,
  375. RawFrame->Header,
  376. DeviceContext->NetBIOSAddress.Address,
  377. DeviceContext->LocalAddress.Address,
  378. sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS),
  379. SingleSR,
  380. SingleSRLength,
  381. &HeaderLength);
  382. //
  383. // Build the DLC UI frame header.
  384. //
  385. NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
  386. HeaderLength += sizeof(DLC_FRAME);
  387. //
  388. // Build the Netbios header.
  389. //
  390. ConstructNameInConflict (
  391. (PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
  392. ConflictingName, // his NetBIOS name.
  393. DeviceContext->ReservedNetBIOSAddress); // our reserved NetBIOS name.
  394. HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
  395. //
  396. // Munge the packet length and send the it.
  397. //
  398. NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
  399. NbfSendUIFrame (
  400. DeviceContext,
  401. RawFrame,
  402. FALSE); // no loopback (MC frame)
  403. } /* NbfSendNameInConflict */
  404. VOID
  405. NbfSendSessionInitialize(
  406. IN PTP_CONNECTION Connection
  407. )
  408. /*++
  409. Routine Description:
  410. This routine sends a SESSION_INITIALIZE frame on the specified connection.
  411. NOTE: THIS ROUTINE MUST BE CALLED AT DPC LEVEL.
  412. Arguments:
  413. Connection - Pointer to a transport connection object.
  414. Return Value:
  415. none.
  416. --*/
  417. {
  418. NTSTATUS Status;
  419. PTP_PACKET Packet;
  420. PDEVICE_CONTEXT DeviceContext;
  421. PTP_LINK Link;
  422. NbfReferenceConnection("send Session Initialize", Connection, CREF_FRAME_SEND);
  423. DeviceContext = Connection->Provider;
  424. Link = Connection->Link;
  425. Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
  426. if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
  427. #if DBG
  428. if (NbfPacketPanic) {
  429. PANIC ("NbfSendSessionInitialize: NbfCreatePacket failed.\n");
  430. }
  431. #endif
  432. NbfWaitPacket (Connection, CONNECTION_FLAGS_SEND_SI);
  433. NbfDereferenceConnection("Couldn't get SI packet", Connection, CREF_FRAME_SEND);
  434. return;
  435. }
  436. //
  437. // Initialize the Netbios header.
  438. //
  439. ConstructSessionInitialize (
  440. (PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
  441. SESSION_INIT_OPTIONS_20 | SESSION_INIT_NO_ACK |
  442. SESSION_INIT_OPTIONS_LF, // supported options Set LF correctly.
  443. (USHORT)(Connection->Link->MaxFrameSize - sizeof(NBF_HDR_CONNECTION) - sizeof(DLC_I_FRAME)),
  444. // maximum frame size/this session.
  445. Connection->NetbiosHeader.TransmitCorrelator, // correlator from NAME_RECOGNIZED.
  446. 0, // correlator for expected SESSION_CONFIRM.
  447. Connection->Lsn, // our local session number.
  448. Connection->Rsn); // his session number (our RSN).
  449. //
  450. // Now send the packet on the connection via the link. If there are
  451. // conditions on the link which make it impossible to send the packet,
  452. // then the packet will be queued to the WackQ, and then timeouts will
  453. // restart the link. This is acceptable when the traffic level is so
  454. // high that we encounter this condition.
  455. //
  456. //
  457. // Set this so NbfDestroyPacket will dereference the connection.
  458. //
  459. Packet->Owner = Connection;
  460. Packet->Action = PACKET_ACTION_CONNECTION;
  461. Packet->NdisIFrameLength =
  462. Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
  463. MacModifyHeader(
  464. &DeviceContext->MacInfo,
  465. Packet->Header,
  466. sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
  467. NbfSetNdisPacketLength(
  468. Packet->NdisPacket,
  469. Packet->NdisIFrameLength);
  470. ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  471. Status = SendOnePacket (Connection, Packet, FALSE, NULL); // fire and forget.
  472. if (Status == STATUS_LINK_FAILED) {
  473. NbfDereferencePacket (Packet); // destroy the packet.
  474. }
  475. return;
  476. } /* NbfSendSessionInitialize */
  477. VOID
  478. NbfSendSessionConfirm(
  479. IN PTP_CONNECTION Connection
  480. )
  481. /*++
  482. Routine Description:
  483. This routine sends a SESSION_CONFIRM frame on the specified connection.
  484. Arguments:
  485. Connection - Pointer to a transport connection object.
  486. Return Value:
  487. none.
  488. --*/
  489. {
  490. NTSTATUS Status;
  491. PTP_PACKET Packet;
  492. PDEVICE_CONTEXT DeviceContext;
  493. PTP_LINK Link;
  494. NbfReferenceConnection("send Session Confirm", Connection, CREF_FRAME_SEND);
  495. DeviceContext = Connection->Provider;
  496. Link = Connection->Link;
  497. Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
  498. if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
  499. #if DBG
  500. if (NbfPacketPanic) {
  501. PANIC ("NbfSendSessionConfirm: NbfCreatePacket failed.\n");
  502. }
  503. #endif
  504. NbfWaitPacket (Connection, CONNECTION_FLAGS_SEND_SC);
  505. NbfDereferenceConnection("Couldn't get SC packet", Connection, CREF_FRAME_SEND);
  506. return;
  507. }
  508. //
  509. // Initialize the Netbios header.
  510. //
  511. ConstructSessionConfirm (
  512. (PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
  513. SESSION_CONFIRM_OPTIONS_20 | SESSION_CONFIRM_NO_ACK, // supported options.
  514. (USHORT)(Connection->Link->MaxFrameSize - sizeof(NBF_HDR_CONNECTION) - sizeof(DLC_I_FRAME)),
  515. // maximum frame size/this session.
  516. Connection->NetbiosHeader.TransmitCorrelator, // correlator from NAME_RECOGNIZED.
  517. Connection->Lsn, // our local session number.
  518. Connection->Rsn); // his session number (our RSN).
  519. //
  520. // Now send the packet on the connection via the link. If there are
  521. // conditions on the link which make it impossible to send the packet,
  522. // then the packet will be queued to the WackQ, and then timeouts will
  523. // restart the link. This is acceptable when the traffic level is so
  524. // high that we encounter this condition.
  525. //
  526. //
  527. // Set this so NbfDestroyPacket will dereference the connection.
  528. //
  529. Packet->Owner = Connection;
  530. Packet->Action = PACKET_ACTION_CONNECTION;
  531. Packet->NdisIFrameLength =
  532. Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
  533. MacModifyHeader(
  534. &DeviceContext->MacInfo,
  535. Packet->Header,
  536. sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
  537. NbfSetNdisPacketLength(
  538. Packet->NdisPacket,
  539. Packet->NdisIFrameLength);
  540. ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  541. Status = SendOnePacket (Connection, Packet, FALSE, NULL); // fire and forget.
  542. if (Status == STATUS_LINK_FAILED) {
  543. NbfDereferencePacket (Packet); // destroy the packet.
  544. }
  545. return;
  546. } /* NbfSendSessionConfirm */
  547. VOID
  548. NbfSendSessionEnd(
  549. IN PTP_CONNECTION Connection,
  550. IN BOOLEAN Abort
  551. )
  552. /*++
  553. Routine Description:
  554. This routine sends a SESSION_END frame on the specified connection.
  555. Arguments:
  556. Connection - Pointer to a transport connection object.
  557. Abort - Boolean set to TRUE if the connection is abnormally terminating.
  558. Return Value:
  559. none.
  560. --*/
  561. {
  562. NTSTATUS Status;
  563. PTP_PACKET Packet;
  564. PDEVICE_CONTEXT DeviceContext;
  565. PTP_LINK Link;
  566. NbfReferenceConnection("send Session End", Connection, CREF_FRAME_SEND);
  567. DeviceContext = Connection->Provider;
  568. Link = Connection->Link;
  569. Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
  570. if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
  571. #if DBG
  572. if (NbfPacketPanic) {
  573. PANIC ("NbfSendSessionEnd: NbfCreatePacket failed.\n");
  574. }
  575. #endif
  576. NbfWaitPacket (Connection, CONNECTION_FLAGS_SEND_SE);
  577. NbfDereferenceConnection("Couldn't get SE packet", Connection, CREF_FRAME_SEND);
  578. return;
  579. }
  580. //
  581. // The following statements instruct the packet destructor to run
  582. // down this connection when the packet is acknowleged.
  583. //
  584. Packet->Owner = Connection;
  585. Packet->Action = PACKET_ACTION_END;
  586. //
  587. // Initialize the Netbios header.
  588. //
  589. ConstructSessionEnd (
  590. (PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
  591. (USHORT)(Abort ? // reason for termination.
  592. SESSION_END_REASON_ABEND :
  593. SESSION_END_REASON_HANGUP),
  594. Connection->Lsn, // our local session number.
  595. Connection->Rsn); // his session number (our RSN).
  596. //
  597. // Now send the packet on the connection via the link. If there are
  598. // conditions on the link which make it impossible to send the packet,
  599. // then the packet will be queued to the WackQ, and then timeouts will
  600. // restart the link. This is acceptable when the traffic level is so
  601. // high that we encounter this condition.
  602. //
  603. // Note that we force an ack for this packet, as we want to make sure we
  604. // run down the connection and link correctly.
  605. //
  606. Packet->NdisIFrameLength =
  607. Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
  608. MacModifyHeader(
  609. &DeviceContext->MacInfo,
  610. Packet->Header,
  611. sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
  612. NbfSetNdisPacketLength(
  613. Packet->NdisPacket,
  614. Packet->NdisIFrameLength);
  615. ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  616. Status = SendOnePacket (Connection, Packet, TRUE, NULL); // fire and forget.
  617. if (Status == STATUS_LINK_FAILED) {
  618. NbfDereferencePacket (Packet); // destroy the packet.
  619. }
  620. return;
  621. } /* NbfSendSessionEnd */
  622. VOID
  623. NbfSendNoReceive(
  624. IN PTP_CONNECTION Connection
  625. )
  626. /*++
  627. Routine Description:
  628. This routine sends a NO_RECEIVE frame on the specified connection.
  629. Arguments:
  630. Connection - Pointer to a transport connection object.
  631. Return Value:
  632. none.
  633. --*/
  634. {
  635. NTSTATUS Status;
  636. PTP_PACKET Packet;
  637. PDEVICE_CONTEXT DeviceContext;
  638. PTP_LINK Link;
  639. USHORT MessageBytesToAck;
  640. NbfReferenceConnection("send No Receive", Connection, CREF_FRAME_SEND);
  641. DeviceContext = Connection->Provider;
  642. Link = Connection->Link;
  643. Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
  644. if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
  645. #if DBG
  646. if (NbfPacketPanic) {
  647. PANIC ("NbfSendNoReceive: NbfCreatePacket failed.\n");
  648. }
  649. #endif
  650. NbfDereferenceConnection("Couldn't get NR packet", Connection, CREF_FRAME_SEND);
  651. return;
  652. }
  653. ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  654. MessageBytesToAck = (USHORT)
  655. (Connection->MessageBytesReceived + Connection->MessageInitAccepted - Connection->MessageBytesAcked);
  656. Connection->Flags |= CONNECTION_FLAGS_W_RESYNCH;
  657. //
  658. // Initialize the Netbios header.
  659. //
  660. ConstructNoReceive (
  661. (PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
  662. (USHORT)0, // options
  663. MessageBytesToAck, // number of bytes accepted.
  664. Connection->Lsn, // our local session number.
  665. Connection->Rsn); // his session number (our RSN).
  666. //
  667. // Now send the packet on the connection via the link. If there are
  668. // conditions on the link which make it impossible to send the packet,
  669. // then the packet will be queued to the WackQ, and then timeouts will
  670. // restart the link. This is acceptable when the traffic level is so
  671. // high that we encounter this condition.
  672. //
  673. //
  674. // Set this so NbfDestroyPacket will dereference the connection.
  675. //
  676. Packet->Owner = Connection;
  677. Packet->Action = PACKET_ACTION_CONNECTION;
  678. Packet->NdisIFrameLength =
  679. Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
  680. MacModifyHeader(
  681. &DeviceContext->MacInfo,
  682. Packet->Header,
  683. sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
  684. NbfSetNdisPacketLength(
  685. Packet->NdisPacket,
  686. Packet->NdisIFrameLength);
  687. Status = SendOnePacket (Connection, Packet, FALSE, NULL); // fire and forget.
  688. if (Status != STATUS_LINK_FAILED) {
  689. ExInterlockedAddUlong(
  690. &Connection->MessageBytesAcked,
  691. MessageBytesToAck,
  692. Connection->LinkSpinLock);
  693. } else {
  694. NbfDereferencePacket (Packet); // destroy the packet.
  695. }
  696. return;
  697. } /* NbfSendNoReceive */
  698. VOID
  699. NbfSendReceiveContinue(
  700. IN PTP_CONNECTION Connection
  701. )
  702. /*++
  703. Routine Description:
  704. This routine sends a RECEIVE_CONTINUE frame on the specified connection.
  705. Arguments:
  706. Connection - Pointer to a transport connection object.
  707. Return Value:
  708. none.
  709. --*/
  710. {
  711. NTSTATUS Status;
  712. PTP_PACKET Packet;
  713. PDEVICE_CONTEXT DeviceContext;
  714. PTP_LINK Link;
  715. USHORT MessageBytesToAck;
  716. NbfReferenceConnection("send Receive Continue", Connection, CREF_FRAME_SEND);
  717. DeviceContext = Connection->Provider;
  718. Link = Connection->Link;
  719. Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
  720. if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
  721. #if DBG
  722. if (NbfPacketPanic) {
  723. PANIC ("NbfSendReceiveContinue: NbfCreatePacket failed.\n");
  724. }
  725. #endif
  726. NbfWaitPacket (Connection, CONNECTION_FLAGS_SEND_RC);
  727. NbfDereferenceConnection("Couldn't get RC packet", Connection, CREF_FRAME_SEND);
  728. return;
  729. }
  730. //
  731. // Save this variable now since it is what we are implicitly ack'ing.
  732. //
  733. ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  734. MessageBytesToAck = (USHORT)
  735. (Connection->MessageBytesReceived + Connection->MessageInitAccepted - Connection->MessageBytesAcked);
  736. //
  737. // Initialize the Netbios header.
  738. //
  739. ConstructReceiveContinue (
  740. (PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
  741. Connection->NetbiosHeader.TransmitCorrelator, // correlator from DFM
  742. Connection->Lsn, // our local session number.
  743. Connection->Rsn); // his session number (our RSN).
  744. //
  745. // Now send the packet on the connection via the link. If there are
  746. // conditions on the link which make it impossible to send the packet,
  747. // then the packet will be queued to the WackQ, and then timeouts will
  748. // restart the link. This is acceptable when the traffic level is so
  749. // high that we encounter this condition.
  750. //
  751. //
  752. // Set this so NbfDestroyPacket will dereference the connection.
  753. //
  754. Packet->Owner = Connection;
  755. Packet->Action = PACKET_ACTION_CONNECTION;
  756. Packet->NdisIFrameLength =
  757. Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
  758. MacModifyHeader(
  759. &DeviceContext->MacInfo,
  760. Packet->Header,
  761. sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
  762. NbfSetNdisPacketLength(
  763. Packet->NdisPacket,
  764. Packet->NdisIFrameLength);
  765. Status = SendOnePacket (Connection, Packet, FALSE, NULL); // fire and forget.
  766. if (Status != STATUS_LINK_FAILED) {
  767. ExInterlockedAddUlong(
  768. &Connection->MessageBytesAcked,
  769. MessageBytesToAck,
  770. Connection->LinkSpinLock);
  771. } else {
  772. NbfDereferencePacket (Packet); // destroy the packet.
  773. }
  774. return;
  775. } /* NbfSendReceiveContinue */
  776. VOID
  777. NbfSendReceiveOutstanding(
  778. IN PTP_CONNECTION Connection
  779. )
  780. /*++
  781. Routine Description:
  782. This routine sends a RECEIVE_OUTSTANDING frame on the specified connection.
  783. Arguments:
  784. Connection - Pointer to a transport connection object.
  785. Return Value:
  786. none.
  787. --*/
  788. {
  789. NTSTATUS Status;
  790. PTP_PACKET Packet;
  791. PDEVICE_CONTEXT DeviceContext;
  792. PTP_LINK Link;
  793. USHORT MessageBytesToAck;
  794. NbfReferenceConnection("send Receive Outstanding", Connection, CREF_FRAME_SEND);
  795. DeviceContext = Connection->Provider;
  796. Link = Connection->Link;
  797. Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
  798. if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
  799. #if DBG
  800. if (NbfPacketPanic) {
  801. PANIC ("NbfSendReceiveOutstanding: NbfCreatePacket failed.\n");
  802. }
  803. #endif
  804. NbfWaitPacket (Connection, CONNECTION_FLAGS_SEND_RO);
  805. NbfDereferenceConnection("Couldn't get RO packet", Connection, CREF_FRAME_SEND);
  806. return;
  807. }
  808. ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  809. MessageBytesToAck = (USHORT)
  810. (Connection->MessageBytesReceived + Connection->MessageInitAccepted - Connection->MessageBytesAcked);
  811. Connection->Flags |= CONNECTION_FLAGS_W_RESYNCH;
  812. //
  813. // Initialize the Netbios header.
  814. //
  815. ConstructReceiveOutstanding (
  816. (PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
  817. MessageBytesToAck, // number of bytes accepted.
  818. Connection->Lsn, // our local session number.
  819. Connection->Rsn); // his session number (our RSN).
  820. //
  821. // Now send the packet on the connection via the link. If there are
  822. // conditions on the link which make it impossible to send the packet,
  823. // then the packet will be queued to the WackQ, and then timeouts will
  824. // restart the link. This is acceptable when the traffic level is so
  825. // high that we encounter this condition.
  826. //
  827. //
  828. // Set this so NbfDestroyPacket will dereference the connection.
  829. //
  830. Packet->Owner = Connection;
  831. Packet->Action = PACKET_ACTION_CONNECTION;
  832. Packet->NdisIFrameLength =
  833. Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
  834. MacModifyHeader(
  835. &DeviceContext->MacInfo,
  836. Packet->Header,
  837. sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
  838. NbfSetNdisPacketLength(
  839. Packet->NdisPacket,
  840. Packet->NdisIFrameLength);
  841. Status = SendOnePacket (Connection, Packet, FALSE, NULL); // fire and forget.
  842. if (Status != STATUS_LINK_FAILED) {
  843. ExInterlockedAddUlong(
  844. &Connection->MessageBytesAcked,
  845. MessageBytesToAck,
  846. Connection->LinkSpinLock);
  847. } else {
  848. NbfDereferencePacket (Packet); // destroy the packet.
  849. }
  850. return;
  851. } /* NbfSendReceiveOutstanding */
  852. VOID
  853. NbfSendDataAck(
  854. IN PTP_CONNECTION Connection
  855. )
  856. /*++
  857. Routine Description:
  858. This routine sends a DATA_ACK frame on the specified connection.
  859. Arguments:
  860. Connection - Pointer to a transport connection object.
  861. Return Value:
  862. none.
  863. --*/
  864. {
  865. NTSTATUS Status;
  866. PTP_PACKET Packet;
  867. PDEVICE_CONTEXT DeviceContext;
  868. PTP_LINK Link;
  869. NbfReferenceConnection("send Data Ack", Connection, CREF_FRAME_SEND);
  870. DeviceContext = Connection->Provider;
  871. Link = Connection->Link;
  872. Status = NbfCreatePacket (DeviceContext, Connection->Link, &Packet);
  873. if (!NT_SUCCESS (Status)) { // if we couldn't make frame.
  874. #if DBG
  875. if (NbfPacketPanic) {
  876. PANIC ("NbfSendDataAck: NbfCreatePacket failed.\n");
  877. }
  878. #endif
  879. NbfWaitPacket (Connection, CONNECTION_FLAGS_SEND_DA);
  880. NbfDereferenceConnection("Couldn't get DA packet", Connection, CREF_FRAME_SEND);
  881. return;
  882. }
  883. //
  884. // Initialize the Netbios header.
  885. //
  886. ConstructDataAck (
  887. (PNBF_HDR_CONNECTION)&(Packet->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]),
  888. Connection->NetbiosHeader.TransmitCorrelator, // correlator from DATA_ONLY_LAST.
  889. Connection->Lsn, // our local session number.
  890. Connection->Rsn); // his session number (our RSN).
  891. //
  892. // Now send the packet on the connection via the link. If there are
  893. // conditions on the link which make it impossible to send the packet,
  894. // then the packet will be queued to the WackQ, and then timeouts will
  895. // restart the link. This is acceptable when the traffic level is so
  896. // high that we encounter this condition. Note that Data Ack will be
  897. // seeing this condition frequently when send windows close after large
  898. // sends.
  899. //
  900. //
  901. // Set this so NbfDestroyPacket will dereference the connection.
  902. //
  903. Packet->Owner = Connection;
  904. Packet->Action = PACKET_ACTION_CONNECTION;
  905. Packet->NdisIFrameLength =
  906. Link->HeaderLength + sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION);
  907. MacModifyHeader(
  908. &DeviceContext->MacInfo,
  909. Packet->Header,
  910. sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION));
  911. NbfSetNdisPacketLength(
  912. Packet->NdisPacket,
  913. Packet->NdisIFrameLength);
  914. ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
  915. Status = SendOnePacket (Connection, Packet, FALSE, NULL); // fire and forget.
  916. if (Status == STATUS_LINK_FAILED) {
  917. NbfDereferencePacket (Packet); // destroy the packet.
  918. }
  919. return;
  920. } /* NbfSendDataAck */
  921. VOID
  922. NbfSendDm(
  923. IN PTP_LINK Link,
  924. IN BOOLEAN PollFinal
  925. )
  926. /*++
  927. Routine Description:
  928. This routine sends a DM-r/x DLC frame on the specified link.
  929. NOTE: This routine is called with the link spinlock held,
  930. and returns with it released. IT MUST BE CALLED AT DPC
  931. LEVEL.
  932. Arguments:
  933. Link - Pointer to a transport link object.
  934. PollFinal - TRUE if poll/final bit should be set.
  935. Return Value:
  936. none.
  937. --*/
  938. {
  939. NTSTATUS Status;
  940. PTP_PACKET RawFrame;
  941. PDLC_U_FRAME DlcHeader; // S-format frame alias.
  942. Status = NbfCreatePacket (Link->Provider, Link, &RawFrame);
  943. if (NT_SUCCESS (Status)) {
  944. RawFrame->Owner = NULL;
  945. RawFrame->Action = PACKET_ACTION_NULL;
  946. //
  947. // set the packet length correctly (Note that the NDIS_BUFFER
  948. // gets returned to the proper length in NbfDestroyPacket)
  949. //
  950. MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_FRAME));
  951. NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_FRAME));
  952. //
  953. // Format LLC DM-r/x header.
  954. //
  955. DlcHeader = (PDLC_U_FRAME)&(RawFrame->Header[Link->HeaderLength]);
  956. DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
  957. DlcHeader->Ssap = DSAP_NETBIOS_OVER_LLC | DLC_SSAP_RESPONSE;
  958. DlcHeader->Command = (UCHAR)(DLC_CMD_DM | (PollFinal ? DLC_U_PF : 0));
  959. //
  960. // This releases the spin lock.
  961. //
  962. SendControlPacket (Link, RawFrame);
  963. } else {
  964. RELEASE_DPC_SPIN_LOCK(&Link->SpinLock);
  965. #if DBG
  966. if (NbfPacketPanic) {
  967. PANIC ("NbfSendDm: packet not sent.\n");
  968. }
  969. #endif
  970. }
  971. } /* NbfSendDm */
  972. VOID
  973. NbfSendUa(
  974. IN PTP_LINK Link,
  975. IN BOOLEAN PollFinal
  976. )
  977. /*++
  978. Routine Description:
  979. This routine sends a UA-r/x DLC frame on the specified link.
  980. NOTE: This routine is called with the link spinlock held,
  981. and returns with it released. IT MUST BE CALLED AT DPC
  982. LEVEL.
  983. Arguments:
  984. Link - Pointer to a transport link object.
  985. PollFinal - TRUE if poll/final bit should be set.
  986. OldIrql - The IRQL at which Link->SpinLock was acquired.
  987. Return Value:
  988. none.
  989. --*/
  990. {
  991. NTSTATUS Status;
  992. PTP_PACKET RawFrame;
  993. PDLC_U_FRAME DlcHeader; // U-format frame alias.
  994. Status = NbfCreatePacket (Link->Provider, Link, &RawFrame);
  995. if (NT_SUCCESS (Status)) {
  996. RawFrame->Owner = NULL;
  997. RawFrame->Action = PACKET_ACTION_NULL;
  998. //
  999. // set the packet length correctly (Note that the NDIS_BUFFER
  1000. // gets returned to the proper length in NbfDestroyPacket)
  1001. //
  1002. MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_FRAME));
  1003. NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_FRAME));
  1004. // Format LLC UA-r/x header.
  1005. //
  1006. DlcHeader = (PDLC_U_FRAME)&(RawFrame->Header[Link->HeaderLength]);
  1007. DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
  1008. DlcHeader->Ssap = DSAP_NETBIOS_OVER_LLC | DLC_SSAP_RESPONSE;
  1009. DlcHeader->Command = (UCHAR)(DLC_CMD_UA | (PollFinal ? DLC_U_PF : 0));
  1010. //
  1011. // This releases the spin lock.
  1012. //
  1013. SendControlPacket (Link, RawFrame);
  1014. } else {
  1015. RELEASE_DPC_SPIN_LOCK(&Link->SpinLock);
  1016. #if DBG
  1017. if (NbfPacketPanic) {
  1018. PANIC ("NbfSendUa: packet not sent.\n");
  1019. }
  1020. #endif
  1021. }
  1022. } /* NbfSendUa */
  1023. VOID
  1024. NbfSendSabme(
  1025. IN PTP_LINK Link,
  1026. IN BOOLEAN PollFinal
  1027. )
  1028. /*++
  1029. Routine Description:
  1030. This routine sends a SABME-c/x DLC frame on the specified link.
  1031. NOTE: This routine is called with the link spinlock held,
  1032. and returns with it released.
  1033. Arguments:
  1034. Link - Pointer to a transport link object.
  1035. PollFinal - TRUE if poll/final bit should be set.
  1036. Return Value:
  1037. none.
  1038. --*/
  1039. {
  1040. NTSTATUS Status;
  1041. PLIST_ENTRY p;
  1042. PTP_PACKET RawFrame, packet;
  1043. PDLC_U_FRAME DlcHeader; // S-format frame alias.
  1044. Status = NbfCreatePacket (Link->Provider, Link, &RawFrame);
  1045. if (NT_SUCCESS (Status)) {
  1046. RawFrame->Owner = NULL;
  1047. RawFrame->Action = PACKET_ACTION_NULL;
  1048. //
  1049. // set the packet length correctly (Note that the NDIS_BUFFER
  1050. // gets returned to the proper length in NbfDestroyPacket)
  1051. //
  1052. MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_FRAME));
  1053. NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_FRAME));
  1054. //
  1055. // Format LLC SABME-c/x header.
  1056. //
  1057. DlcHeader = (PDLC_U_FRAME)&(RawFrame->Header[Link->HeaderLength]);
  1058. DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
  1059. DlcHeader->Ssap = DSAP_NETBIOS_OVER_LLC;
  1060. DlcHeader->Command = (UCHAR)(DLC_CMD_SABME | (PollFinal ? DLC_U_PF : 0));
  1061. //
  1062. // Set up so that T1 will be started when the send
  1063. // completes.
  1064. //
  1065. if (PollFinal) {
  1066. if (Link->Provider->MacInfo.MediumAsync) {
  1067. RawFrame->NdisIFrameLength = Link->HeaderLength + sizeof(DLC_S_FRAME);
  1068. RawFrame->Link = Link;
  1069. NbfReferenceLink ("Sabme/p", Link, LREF_START_T1);
  1070. } else {
  1071. StartT1 (Link, Link->HeaderLength + sizeof(DLC_S_FRAME));
  1072. }
  1073. }
  1074. //
  1075. // This releases the spin lock.
  1076. //
  1077. SendControlPacket (Link, RawFrame);
  1078. //
  1079. // Reset the link state based on having sent this packet..
  1080. // Note that a SABME can be sent under some conditions on an existing
  1081. // link. If it is, it means we want to reset this link to a known state.
  1082. // We'll do that; note that that involves ditching any packets outstanding
  1083. // on the link.
  1084. //
  1085. ACQUIRE_DPC_SPIN_LOCK (&Link->SpinLock);
  1086. Link->NextSend = 0;
  1087. Link->LastAckReceived = 0;
  1088. Link->NextReceive = 0; // expect next packet to be sequence 0
  1089. Link->NextReceive = 0;
  1090. Link->LastAckSent = 0;
  1091. Link->NextReceive = 0;
  1092. Link->LastAckSent = 0;
  1093. while (!IsListEmpty (&Link->WackQ)) {
  1094. p = RemoveHeadList (&Link->WackQ);
  1095. RELEASE_DPC_SPIN_LOCK (&Link->SpinLock);
  1096. packet = CONTAINING_RECORD (p, TP_PACKET, Linkage);
  1097. NbfDereferencePacket (packet);
  1098. ACQUIRE_DPC_SPIN_LOCK (&Link->SpinLock);
  1099. }
  1100. RELEASE_DPC_SPIN_LOCK (&Link->SpinLock);
  1101. } else {
  1102. if (PollFinal) {
  1103. StartT1 (Link, Link->HeaderLength + sizeof(DLC_S_FRAME));
  1104. }
  1105. RELEASE_DPC_SPIN_LOCK(&Link->SpinLock);
  1106. #if DBG
  1107. if (NbfPacketPanic) {
  1108. PANIC ("NbfSendSabme: packet not sent.\n");
  1109. }
  1110. #endif
  1111. }
  1112. } /* NbfSendSabme */
  1113. VOID
  1114. NbfSendDisc(
  1115. IN PTP_LINK Link,
  1116. IN BOOLEAN PollFinal
  1117. )
  1118. /*++
  1119. Routine Description:
  1120. This routine sends a DISC-c/x DLC frame on the specified link.
  1121. Arguments:
  1122. Link - Pointer to a transport link object.
  1123. PollFinal - TRUE if poll/final bit should be set.
  1124. Return Value:
  1125. none.
  1126. --*/
  1127. {
  1128. NTSTATUS Status;
  1129. PTP_PACKET RawFrame;
  1130. PDLC_U_FRAME DlcHeader; // S-format frame alias.
  1131. KIRQL oldirql;
  1132. KeRaiseIrql (DISPATCH_LEVEL, &oldirql);
  1133. Status = NbfCreatePacket (Link->Provider, Link, &RawFrame);
  1134. if (NT_SUCCESS (Status)) {
  1135. RawFrame->Owner = NULL;
  1136. RawFrame->Action = PACKET_ACTION_NULL;
  1137. //
  1138. // set the packet length correctly (Note that the NDIS_BUFFER
  1139. // gets returned to the proper length in NbfDestroyPacket)
  1140. //
  1141. MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_FRAME));
  1142. NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_FRAME));
  1143. //
  1144. // Format LLC DISC-c/x header.
  1145. //
  1146. DlcHeader = (PDLC_U_FRAME)&(RawFrame->Header[Link->HeaderLength]);
  1147. DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
  1148. DlcHeader->Ssap = DSAP_NETBIOS_OVER_LLC;
  1149. DlcHeader->Command = (UCHAR)(DLC_CMD_DISC | (PollFinal ? DLC_U_PF : 0));
  1150. ACQUIRE_DPC_SPIN_LOCK (&Link->SpinLock);
  1151. //
  1152. // This releases the spin lock.
  1153. //
  1154. SendControlPacket (Link, RawFrame);
  1155. } else {
  1156. #if DBG
  1157. if (NbfPacketPanic) {
  1158. PANIC ("NbfSendDisc: packet not sent.\n");
  1159. }
  1160. #endif
  1161. }
  1162. KeLowerIrql (oldirql);
  1163. } /* NbfSendDisc */
  1164. VOID
  1165. NbfSendRr(
  1166. IN PTP_LINK Link,
  1167. IN BOOLEAN Command,
  1168. IN BOOLEAN PollFinal
  1169. )
  1170. /*++
  1171. Routine Description:
  1172. This routine sends a RR-x/x DLC frame on the specified link.
  1173. NOTE: This routine is called with the link spinlock held,
  1174. and returns with it released. THIS ROUTINE MUST BE CALLED
  1175. AT DPC LEVEL.
  1176. Arguments:
  1177. Link - Pointer to a transport link object.
  1178. Command - TRUE if command bit should be set.
  1179. PollFinal - TRUE if poll/final bit should be set.
  1180. Return Value:
  1181. none.
  1182. --*/
  1183. {
  1184. NTSTATUS Status;
  1185. PTP_PACKET RawFrame;
  1186. PDLC_S_FRAME DlcHeader; // S-format frame alias.
  1187. Status = NbfCreateRrPacket (Link->Provider, Link, &RawFrame);
  1188. if (NT_SUCCESS (Status)) {
  1189. RawFrame->Owner = NULL;
  1190. //
  1191. // RawFrame->Action will be set to PACKET_ACTION_RR if
  1192. // NbfCreateRrPacket got a packet from the RrPacketPool
  1193. // and PACKET_ACTION_NULL if it got one from the regular
  1194. // pool.
  1195. //
  1196. //
  1197. // set the packet length correctly (Note that the NDIS_BUFFER
  1198. // gets returned to the proper length in NbfDestroyPacket)
  1199. //
  1200. MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_S_FRAME));
  1201. NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_S_FRAME));
  1202. //
  1203. // Format LLC RR-x/x header.
  1204. //
  1205. DlcHeader = (PDLC_S_FRAME)&(RawFrame->Header[Link->HeaderLength]);
  1206. DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
  1207. DlcHeader->Ssap = (UCHAR)(DSAP_NETBIOS_OVER_LLC | (Command ? 0 : DLC_SSAP_RESPONSE));
  1208. DlcHeader->Command = DLC_CMD_RR;
  1209. DlcHeader->RcvSeq = (UCHAR)(PollFinal ? DLC_S_PF : 0);
  1210. //
  1211. // If this is a command frame (which will always be a
  1212. // poll with the current code) set up so that T1 will
  1213. // be started when the send completes.
  1214. //
  1215. if (Command) {
  1216. if (Link->Provider->MacInfo.MediumAsync) {
  1217. RawFrame->NdisIFrameLength = Link->HeaderLength + sizeof(DLC_S_FRAME);
  1218. RawFrame->Link = Link;
  1219. NbfReferenceLink ("Rr/p", Link, LREF_START_T1);
  1220. } else {
  1221. StartT1 (Link, Link->HeaderLength + sizeof(DLC_S_FRAME));
  1222. }
  1223. }
  1224. //
  1225. // This puts Link->NextReceive into DlcHeader->RcvSeq
  1226. // and releases the spinlock.
  1227. //
  1228. SendControlPacket (Link, RawFrame);
  1229. } else {
  1230. if (Command) {
  1231. StartT1 (Link, Link->HeaderLength + sizeof(DLC_S_FRAME));
  1232. }
  1233. RELEASE_DPC_SPIN_LOCK(&Link->SpinLock);
  1234. #if DBG
  1235. if (NbfPacketPanic) {
  1236. PANIC ("NbfSendRr: packet not sent.\n");
  1237. }
  1238. #endif
  1239. }
  1240. } /* NbfSendRr */
  1241. #if 0
  1242. //
  1243. // These functions are not currently called, so they are commented
  1244. // out.
  1245. //
  1246. VOID
  1247. NbfSendRnr(
  1248. IN PTP_LINK Link,
  1249. IN BOOLEAN Command,
  1250. IN BOOLEAN PollFinal
  1251. )
  1252. /*++
  1253. Routine Description:
  1254. This routine sends a RNR-x/x DLC frame on the specified link.
  1255. Arguments:
  1256. Link - Pointer to a transport link object.
  1257. Command - TRUE if command bit should be set.
  1258. PollFinal - TRUE if poll/final bit should be set.
  1259. Return Value:
  1260. none.
  1261. --*/
  1262. {
  1263. NTSTATUS Status;
  1264. PTP_PACKET RawFrame;
  1265. PDLC_S_FRAME DlcHeader; // S-format frame alias.
  1266. KIRQL oldirql;
  1267. KeRaiseIrql (DISPATCH_LEVEL, &oldirql);
  1268. Status = NbfCreatePacket (Link->Provider, Link, &RawFrame);
  1269. if (NT_SUCCESS (Status)) {
  1270. RawFrame->Owner = NULL;
  1271. RawFrame->Action = PACKET_ACTION_NULL;
  1272. //
  1273. // set the packet length correctly (Note that the NDIS_BUFFER
  1274. // gets returned to the proper length in NbfDestroyPacket)
  1275. //
  1276. MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_S_FRAME));
  1277. NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_S_FRAME));
  1278. //
  1279. // Format LLC RR-x/x header.
  1280. //
  1281. DlcHeader = (PDLC_S_FRAME)&(RawFrame->Header[Link->HeaderLength]);
  1282. DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
  1283. DlcHeader->Ssap = (UCHAR)(DSAP_NETBIOS_OVER_LLC | (Command ? 0 : DLC_SSAP_RESPONSE));
  1284. DlcHeader->Command = DLC_CMD_RNR;
  1285. DlcHeader->RcvSeq = (UCHAR)(PollFinal ? DLC_S_PF : 0);
  1286. ACQUIRE_DPC_SPIN_LOCK (&Link->SpinLock);
  1287. //
  1288. // This puts Link->NextReceive into DlcHeader->RcvSeq
  1289. // and releases the spin lock.
  1290. //
  1291. SendControlPacket (Link, RawFrame);
  1292. } else {
  1293. #if DBG
  1294. if (NbfPacketPanic) {
  1295. PANIC ("NbfSendRnr: packet not sent.\n");
  1296. }
  1297. #endif
  1298. }
  1299. KeLowerIrql (oldirql);
  1300. } /* NbfSendRnr */
  1301. VOID
  1302. NbfSendTest(
  1303. IN PTP_LINK Link,
  1304. IN BOOLEAN Command,
  1305. IN BOOLEAN PollFinal,
  1306. IN PMDL Psdu
  1307. )
  1308. /*++
  1309. Routine Description:
  1310. This routine sends a TEST-x/x DLC frame on the specified link.
  1311. Arguments:
  1312. Link - Pointer to a transport link object.
  1313. Command - TRUE if command bit should be set.
  1314. PollFinal - TRUE if poll/final bit should be set.
  1315. Psdu - Pointer to an MDL chain describing received TEST-c frame's storage.
  1316. Return Value:
  1317. none.
  1318. --*/
  1319. {
  1320. Link, Command, PollFinal, Psdu; // prevent compiler warnings
  1321. PANIC ("NbfSendTest: Entered.\n");
  1322. } /* NbfSendTest */
  1323. VOID
  1324. NbfSendFrmr(
  1325. IN PTP_LINK Link,
  1326. IN BOOLEAN PollFinal
  1327. )
  1328. /*++
  1329. Routine Description:
  1330. This routine sends a FRMR-r/x DLC frame on the specified link.
  1331. Arguments:
  1332. Link - Pointer to a transport link object.
  1333. PollFinal - TRUE if poll/final bit should be set.
  1334. Return Value:
  1335. none.
  1336. --*/
  1337. {
  1338. Link, PollFinal; // prevent compiler warnings
  1339. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  1340. NbfPrint0 ("NbfSendFrmr: Entered.\n");
  1341. }
  1342. } /* NbfSendFrmr */
  1343. #endif
  1344. VOID
  1345. NbfSendXid(
  1346. IN PTP_LINK Link,
  1347. IN BOOLEAN Command,
  1348. IN BOOLEAN PollFinal
  1349. )
  1350. /*++
  1351. Routine Description:
  1352. This routine sends an XID-x/x DLC frame on the specified link.
  1353. NOTE: This routine is called with the link spinlock held,
  1354. and returns with it released.
  1355. Arguments:
  1356. Link - Pointer to a transport link object.
  1357. Command - TRUE if command bit should be set.
  1358. PollFinal - TRUE if poll/final bit should be set.
  1359. Return Value:
  1360. none.
  1361. --*/
  1362. {
  1363. Link, Command, PollFinal; // prevent compiler warnings
  1364. RELEASE_DPC_SPIN_LOCK(&Link->SpinLock);
  1365. PANIC ("NbfSendXid: Entered.\n");
  1366. } /* NbfSendXid */
  1367. VOID
  1368. NbfSendRej(
  1369. IN PTP_LINK Link,
  1370. IN BOOLEAN Command,
  1371. IN BOOLEAN PollFinal
  1372. )
  1373. /*++
  1374. Routine Description:
  1375. This routine sends a REJ-x/x DLC frame on the specified link.
  1376. NOTE: This function is called with Link->SpinLock held and
  1377. returns with it released. THIS MUST BE CALLED AT DPC LEVEL.
  1378. Arguments:
  1379. Link - Pointer to a transport link object.
  1380. Command - TRUE if command bit should be set.
  1381. PollFinal - TRUE if poll/final bit should be set.
  1382. Return Value:
  1383. none.
  1384. --*/
  1385. {
  1386. NTSTATUS Status;
  1387. PTP_PACKET RawFrame;
  1388. PDLC_S_FRAME DlcHeader; // S-format frame alias.
  1389. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  1390. NbfPrint0 ("NbfSendRej: Entered.\n");
  1391. }
  1392. Status = NbfCreatePacket (Link->Provider, Link, &RawFrame);
  1393. if (NT_SUCCESS (Status)) {
  1394. RawFrame->Owner = NULL;
  1395. RawFrame->Action = PACKET_ACTION_NULL;
  1396. //
  1397. // set the packet length correctly (Note that the NDIS_BUFFER
  1398. // gets returned to the proper length in NbfDestroyPacket)
  1399. //
  1400. MacModifyHeader(&Link->Provider->MacInfo, RawFrame->Header, sizeof(DLC_S_FRAME));
  1401. NbfSetNdisPacketLength (RawFrame->NdisPacket, Link->HeaderLength + sizeof(DLC_S_FRAME));
  1402. //
  1403. // Format LLC REJ-x/x header.
  1404. //
  1405. DlcHeader = (PDLC_S_FRAME)&(RawFrame->Header[Link->HeaderLength]);
  1406. DlcHeader->Dsap = DSAP_NETBIOS_OVER_LLC;
  1407. DlcHeader->Ssap = (UCHAR)(DSAP_NETBIOS_OVER_LLC | (Command ? 0 : DLC_SSAP_RESPONSE));
  1408. DlcHeader->Command = DLC_CMD_REJ;
  1409. DlcHeader->RcvSeq = (UCHAR)(PollFinal ? DLC_S_PF : 0);
  1410. //
  1411. // This puts Link->NextReceive into DlcHeader->RcvSeq
  1412. // and releases the spin lock.
  1413. //
  1414. SendControlPacket (Link, RawFrame);
  1415. } else {
  1416. RELEASE_DPC_SPIN_LOCK(&Link->SpinLock);
  1417. #if DBG
  1418. if (NbfPacketPanic) {
  1419. PANIC ("NbfSendRej: packet not sent.\n");
  1420. }
  1421. #endif
  1422. }
  1423. } /* NbfSendRej */
  1424. NTSTATUS
  1425. NbfCreateConnectionlessFrame(
  1426. PDEVICE_CONTEXT DeviceContext,
  1427. PTP_UI_FRAME *RawFrame
  1428. )
  1429. /*++
  1430. Routine Description:
  1431. This routine allocates a connectionless frame (either from the local
  1432. device context pool or out of non-paged pool).
  1433. Arguments:
  1434. DeviceContext - Pointer to our device context to charge the frame to.
  1435. RawFrame - Pointer to a place where we will return a pointer to the
  1436. allocated frame.
  1437. Return Value:
  1438. NTSTATUS - status of operation.
  1439. --*/
  1440. {
  1441. KIRQL oldirql;
  1442. PTP_UI_FRAME UIFrame;
  1443. PLIST_ENTRY p;
  1444. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  1445. NbfPrint0 ("NbfCreateConnectionlessFrame: Entered.\n");
  1446. }
  1447. //
  1448. // Make sure that structure padding hasn't happened.
  1449. //
  1450. ASSERT (sizeof(NBF_HDR_CONNECTIONLESS) == 44);
  1451. p = ExInterlockedRemoveHeadList (
  1452. &DeviceContext->UIFramePool,
  1453. &DeviceContext->Interlock);
  1454. if (p == NULL) {
  1455. #if DBG
  1456. if (NbfPacketPanic) {
  1457. PANIC ("NbfCreateConnectionlessFrame: PANIC! no more UI frames in pool!\n");
  1458. }
  1459. #endif
  1460. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
  1461. ++DeviceContext->UIFrameExhausted;
  1462. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  1463. return STATUS_INSUFFICIENT_RESOURCES;
  1464. }
  1465. UIFrame = (PTP_UI_FRAME) CONTAINING_RECORD (p, TP_UI_FRAME, Linkage);
  1466. *RawFrame = UIFrame;
  1467. return STATUS_SUCCESS;
  1468. } /* NbfCreateConnectionlessFrame */
  1469. VOID
  1470. NbfDestroyConnectionlessFrame(
  1471. PDEVICE_CONTEXT DeviceContext,
  1472. PTP_UI_FRAME RawFrame
  1473. )
  1474. /*++
  1475. Routine Description:
  1476. This routine destroys a connectionless frame by either returning it
  1477. to the device context's pool or to the system's non-paged pool.
  1478. Arguments:
  1479. DeviceContext - Pointer to our device context to return the frame to.
  1480. RawFrame - Pointer to a frame to be returned.
  1481. Return Value:
  1482. none.
  1483. --*/
  1484. {
  1485. PNDIS_BUFFER HeaderBuffer;
  1486. PNDIS_BUFFER NdisBuffer;
  1487. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  1488. NbfPrint0 ("NbfDestroyConnectionlessFrame: Entered.\n");
  1489. }
  1490. //
  1491. // Strip off and unmap the buffers describing data and header.
  1492. //
  1493. NdisUnchainBufferAtFront (RawFrame->NdisPacket, &HeaderBuffer);
  1494. // data buffers get thrown away
  1495. NdisUnchainBufferAtFront (RawFrame->NdisPacket, &NdisBuffer);
  1496. while (NdisBuffer != NULL) {
  1497. NdisFreeBuffer (NdisBuffer);
  1498. NdisUnchainBufferAtFront (RawFrame->NdisPacket, &NdisBuffer);
  1499. }
  1500. NDIS_BUFFER_LINKAGE(HeaderBuffer) = (PNDIS_BUFFER)NULL;
  1501. //
  1502. // If this UI frame has some transport-created data,
  1503. // free the buffer now.
  1504. //
  1505. if (RawFrame->DataBuffer) {
  1506. ExFreePool (RawFrame->DataBuffer);
  1507. RawFrame->DataBuffer = NULL;
  1508. }
  1509. NdisChainBufferAtFront (RawFrame->NdisPacket, HeaderBuffer);
  1510. ExInterlockedInsertTailList (
  1511. &DeviceContext->UIFramePool,
  1512. &RawFrame->Linkage,
  1513. &DeviceContext->Interlock);
  1514. } /* NbfDestroyConnectionlessFrame */
  1515. VOID
  1516. NbfSendUIFrame(
  1517. PDEVICE_CONTEXT DeviceContext,
  1518. PTP_UI_FRAME RawFrame,
  1519. IN BOOLEAN Loopback
  1520. )
  1521. /*++
  1522. Routine Description:
  1523. This routine sends a connectionless frame by calling the physical
  1524. provider's Send service. When the request completes, or if the service
  1525. does not return successfully, then the frame is deallocated.
  1526. Arguments:
  1527. DeviceContext - Pointer to our device context.
  1528. RawFrame - Pointer to a connectionless frame to be sent.
  1529. Loopback - A boolean flag set to TRUE if the source hardware address
  1530. of the packet should be set to zeros.
  1531. SourceRoutingInformation - Pointer to optional source routing information.
  1532. Return Value:
  1533. None.
  1534. --*/
  1535. {
  1536. NDIS_STATUS NdisStatus;
  1537. PUCHAR DestinationAddress;
  1538. UNREFERENCED_PARAMETER(Loopback);
  1539. #if DBG
  1540. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  1541. NbfPrint2 ("NbfSendUIFrame: Entered, RawFrame: %lx NdisPacket %lx\n",
  1542. RawFrame, RawFrame->NdisPacket);
  1543. DbgPrint ("NbfSendUIFrame: MacHeader: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x \n",
  1544. RawFrame->Header[0],
  1545. RawFrame->Header[1],
  1546. RawFrame->Header[2],
  1547. RawFrame->Header[3],
  1548. RawFrame->Header[4],
  1549. RawFrame->Header[5],
  1550. RawFrame->Header[6],
  1551. RawFrame->Header[7],
  1552. RawFrame->Header[8],
  1553. RawFrame->Header[9],
  1554. RawFrame->Header[10],
  1555. RawFrame->Header[11],
  1556. RawFrame->Header[12],
  1557. RawFrame->Header[13]);
  1558. }
  1559. #endif
  1560. //
  1561. // Send the packet.
  1562. //
  1563. #if DBG
  1564. NbfSendsIssued++;
  1565. #endif
  1566. //
  1567. // Loopback will be FALSE for multicast frames or other
  1568. // frames that we know are not directly addressed to
  1569. // our hardware address.
  1570. //
  1571. if (Loopback) {
  1572. //
  1573. // See if this frame should be looped back.
  1574. //
  1575. MacReturnDestinationAddress(
  1576. &DeviceContext->MacInfo,
  1577. RawFrame->Header,
  1578. &DestinationAddress);
  1579. if (RtlEqualMemory(
  1580. DestinationAddress,
  1581. DeviceContext->LocalAddress.Address,
  1582. DeviceContext->MacInfo.AddressLength)) {
  1583. NbfInsertInLoopbackQueue(
  1584. DeviceContext,
  1585. RawFrame->NdisPacket,
  1586. LOOPBACK_UI_FRAME
  1587. );
  1588. NdisStatus = NDIS_STATUS_PENDING;
  1589. goto NoNdisSend;
  1590. }
  1591. }
  1592. INCREMENT_COUNTER (DeviceContext, PacketsSent);
  1593. if (DeviceContext->NdisBindingHandle) {
  1594. NdisSend (
  1595. &NdisStatus,
  1596. (NDIS_HANDLE)DeviceContext->NdisBindingHandle,
  1597. RawFrame->NdisPacket);
  1598. }
  1599. else {
  1600. NdisStatus = STATUS_INVALID_DEVICE_STATE;
  1601. }
  1602. NoNdisSend:
  1603. if (NdisStatus != NDIS_STATUS_PENDING) {
  1604. #if DBG
  1605. if (NdisStatus == NDIS_STATUS_SUCCESS) {
  1606. NbfSendsCompletedOk++;
  1607. } else {
  1608. NbfSendsCompletedFail++;
  1609. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  1610. NbfPrint1 ("NbfSendUIFrame: NdisSend failed, status other Pending or Complete: %s.\n",
  1611. NbfGetNdisStatus(NdisStatus));
  1612. }
  1613. }
  1614. #endif
  1615. NbfDestroyConnectionlessFrame (DeviceContext, RawFrame);
  1616. } else {
  1617. #if DBG
  1618. NbfSendsPended++;
  1619. #endif
  1620. }
  1621. } /* NbfSendUIFrame */
  1622. VOID
  1623. NbfSendUIMdlFrame(
  1624. PTP_ADDRESS Address
  1625. )
  1626. /*++
  1627. Routine Description:
  1628. This routine sends a connectionless frame by calling the NbfSendUIFrame.
  1629. It is intended that this routine be used for sending datagrams and
  1630. braodcast datagrams.
  1631. The datagram to be sent is described in the NDIS packet contained
  1632. in the Address. When the send completes, the send completion handler
  1633. returns the NDIS buffer describing the datagram to the buffer pool and
  1634. marks the address ndis packet as usable again. Thus, all datagram and
  1635. UI frames are sequenced through the address they are sent on.
  1636. Arguments:
  1637. Address - pointer to the address from which to send this datagram.
  1638. SourceRoutingInformation - Pointer to optional source routing information.
  1639. Return Value:
  1640. None.
  1641. --*/
  1642. {
  1643. // NTSTATUS Status;
  1644. NDIS_STATUS NdisStatus;
  1645. PDEVICE_CONTEXT DeviceContext;
  1646. PUCHAR DestinationAddress;
  1647. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  1648. NbfPrint0 ("NbfSendUIMdlFrame: Entered.\n");
  1649. }
  1650. //
  1651. // Send the packet.
  1652. //
  1653. DeviceContext = Address->Provider;
  1654. INCREMENT_COUNTER (DeviceContext, PacketsSent);
  1655. MacReturnDestinationAddress(
  1656. &DeviceContext->MacInfo,
  1657. Address->UIFrame->Header,
  1658. &DestinationAddress);
  1659. if (RtlEqualMemory(
  1660. DestinationAddress,
  1661. DeviceContext->LocalAddress.Address,
  1662. DeviceContext->MacInfo.AddressLength)) {
  1663. //
  1664. // This packet is sent to ourselves; we should loop it
  1665. // back.
  1666. //
  1667. NbfInsertInLoopbackQueue(
  1668. DeviceContext,
  1669. Address->UIFrame->NdisPacket,
  1670. LOOPBACK_UI_FRAME
  1671. );
  1672. NdisStatus = NDIS_STATUS_PENDING;
  1673. } else {
  1674. #ifndef NO_STRESS_BUG
  1675. Address->SendFlags |= ADDRESS_FLAGS_SENT_TO_NDIS;
  1676. Address->SendFlags &= ~ADDRESS_FLAGS_RETD_BY_NDIS;
  1677. #endif
  1678. if (Address->Provider->NdisBindingHandle) {
  1679. NdisSend (
  1680. &NdisStatus,
  1681. (NDIS_HANDLE)Address->Provider->NdisBindingHandle,
  1682. Address->UIFrame->NdisPacket);
  1683. }
  1684. else {
  1685. NdisStatus = STATUS_INVALID_DEVICE_STATE;
  1686. }
  1687. }
  1688. if (NdisStatus != NDIS_STATUS_PENDING) {
  1689. NbfSendDatagramCompletion (Address, Address->UIFrame->NdisPacket, NdisStatus);
  1690. #if DBG
  1691. if (NdisStatus != NDIS_STATUS_SUCCESS) { // This is an error, trickle it up
  1692. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  1693. NbfPrint1 ("NbfSendUIMdlFrame: NdisSend failed, status other Pending or Complete: %s.\n",
  1694. NbfGetNdisStatus(NdisStatus));
  1695. }
  1696. }
  1697. #endif
  1698. }
  1699. } /* NbfSendUIMdlFrame */
  1700. VOID
  1701. NbfSendDatagramCompletion(
  1702. IN PTP_ADDRESS Address,
  1703. IN PNDIS_PACKET NdisPacket,
  1704. IN NDIS_STATUS NdisStatus
  1705. )
  1706. /*++
  1707. Routine Description:
  1708. This routine is called as an I/O completion handler at the time a
  1709. NbfSendUIMdlFrame send request is completed. Because this handler is only
  1710. associated with NbfSendUIMdlFrame, and because NbfSendUIMdlFrame is only
  1711. used with datagrams and broadcast datagrams, we know that the I/O being
  1712. completed is a datagram. Here we complete the in-progress datagram, and
  1713. start-up the next one if there is one.
  1714. Arguments:
  1715. Address - Pointer to a transport address on which the datagram
  1716. is queued.
  1717. NdisPacket - pointer to the NDIS packet describing this request.
  1718. Return Value:
  1719. none.
  1720. --*/
  1721. {
  1722. PIRP Irp;
  1723. PLIST_ENTRY p;
  1724. KIRQL oldirql;
  1725. PNDIS_BUFFER HeaderBuffer;
  1726. NdisPacket; // prevent compiler warnings.
  1727. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  1728. NbfPrint0 ("NbfSendDatagramCompletion: Entered.\n");
  1729. }
  1730. #ifndef NO_STRESS_BUG
  1731. Address->SendFlags |= ADDRESS_FLAGS_RETD_BY_NDIS;
  1732. #endif
  1733. //
  1734. // Dequeue the current request and return it to the client. Release
  1735. // our hold on the send datagram queue.
  1736. //
  1737. // *** There may be no current request, if the one that was queued
  1738. // was aborted or timed out. If this is the case, we added a
  1739. // special reference to the address, so we still want to deref
  1740. // when we are done (I don't think this is true - adb 3/22/93).
  1741. //
  1742. ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
  1743. p = RemoveHeadList (&Address->SendDatagramQueue);
  1744. if (p != &Address->SendDatagramQueue) {
  1745. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  1746. Irp = CONTAINING_RECORD (p, IRP, Tail.Overlay.ListEntry);
  1747. IF_NBFDBG (NBF_DEBUG_FRAMESND) {
  1748. NbfPrint0 ("NbfDestroyConnectionlessFrame: Entered.\n");
  1749. }
  1750. //
  1751. // Strip off and unmap the buffers describing data and header.
  1752. //
  1753. NdisUnchainBufferAtFront (Address->UIFrame->NdisPacket, &HeaderBuffer);
  1754. // drop the rest of the packet
  1755. NdisReinitializePacket (Address->UIFrame->NdisPacket);
  1756. NDIS_BUFFER_LINKAGE(HeaderBuffer) = (PNDIS_BUFFER)NULL;
  1757. NdisChainBufferAtFront (Address->UIFrame->NdisPacket, HeaderBuffer);
  1758. //
  1759. // Ignore NdisStatus; datagrams always "succeed". The Information
  1760. // field was filled in when we queued the datagram.
  1761. //
  1762. Irp->IoStatus.Status = STATUS_SUCCESS;
  1763. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  1764. #ifndef NO_STRESS_BUG
  1765. Address->SendFlags &= ~ADDRESS_FLAGS_SENT_TO_NDIS;
  1766. Address->SendFlags &= ~ADDRESS_FLAGS_RETD_BY_NDIS;
  1767. #endif
  1768. ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
  1769. Address->Flags &= ~ADDRESS_FLAGS_SEND_IN_PROGRESS;
  1770. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  1771. //
  1772. // Send more datagrams on the Address if possible.
  1773. //
  1774. NbfSendDatagramsOnAddress (Address); // do more datagrams.
  1775. } else {
  1776. ASSERT (FALSE);
  1777. Address->Flags &= ~ADDRESS_FLAGS_SEND_IN_PROGRESS;
  1778. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  1779. }
  1780. NbfDereferenceAddress ("Complete datagram", Address, AREF_REQUEST);
  1781. } /* NbfSendDatagramCompletion */