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.

1566 lines
54 KiB

  1. /* (C) 1997-1999 Microsoft Corp.
  2. *
  3. * file : DomPDU.c
  4. * author : Erik Mavrinac
  5. *
  6. * description: Encode/decode functions for MCS domain PDUs. Domain PDUs are
  7. * encoded with ASN.1 packed encoding rules (PER). Included in this file
  8. * are local functions to PER-decode and -encode various types used in MCS
  9. * PDUs. Note that this implementation follows closely the T.122/T.125 LITE
  10. * specification published by the IMTC, reducing the number of fully-
  11. * implemented code paths and providing default behavior for unimplemented
  12. * functions.
  13. *
  14. * NOTE: Bit numbers used in comments are decoded as follows:
  15. *
  16. * Byte: 0101 1001 ( = 0x59)
  17. * Bit: 7654 3210
  18. *
  19. * History:
  20. * 11-Aug-97 jparsons Set byte counts for outbufs.
  21. */
  22. #include "precomp.h"
  23. #pragma hdrstop
  24. #include <MCSImpl.h>
  25. #include "domain.h"
  26. /*
  27. * Prototypes for unpacking functions, defined across the indicated files.
  28. */
  29. // Defined below.
  30. BOOLEAN __fastcall HandlePlumbDomainInd(PDomain, BYTE *, unsigned, unsigned *);
  31. BOOLEAN __fastcall HandleErectDomainReq(PDomain, BYTE *, unsigned, unsigned *);
  32. // Defined in MergePDU.c.
  33. BOOLEAN __fastcall HandleMergeChannelsReq(PDomain, BYTE *, unsigned, unsigned *);
  34. BOOLEAN __fastcall HandleMergeChannelsCon(PDomain, BYTE *, unsigned, unsigned *);
  35. BOOLEAN __fastcall HandlePurgeChannelsInd(PDomain, BYTE *, unsigned, unsigned *);
  36. BOOLEAN __fastcall HandleMergeTokensReq(PDomain, BYTE *, unsigned, unsigned *);
  37. BOOLEAN __fastcall HandleMergeTokensCon(PDomain, BYTE *, unsigned, unsigned *);
  38. BOOLEAN __fastcall HandlePurgeTokensInd(PDomain, BYTE *, unsigned, unsigned *);
  39. // Defined below.
  40. BOOLEAN __fastcall HandleDisconnectProviderUlt(PDomain, BYTE *, unsigned, unsigned *);
  41. BOOLEAN __fastcall HandleRejectMCSPDUUlt(PDomain, BYTE *, unsigned, unsigned *);
  42. BOOLEAN __fastcall HandleAttachUserReq(PDomain, BYTE *, unsigned, unsigned *);
  43. BOOLEAN __fastcall HandleAttachUserCon(PDomain, BYTE *, unsigned, unsigned *);
  44. BOOLEAN __fastcall HandleDetachUserReq(PDomain, BYTE *, unsigned, unsigned *);
  45. BOOLEAN __fastcall HandleDetachUserInd(PDomain, BYTE *, unsigned, unsigned *);
  46. BOOLEAN __fastcall HandleChannelJoinReq(PDomain, BYTE *, unsigned, unsigned *);
  47. BOOLEAN __fastcall HandleChannelJoinCon(PDomain, BYTE *, unsigned, unsigned *);
  48. BOOLEAN __fastcall HandleChannelLeaveReq(PDomain, BYTE *, unsigned, unsigned *);
  49. // Defined in CnvChPDU.c.
  50. BOOLEAN __fastcall HandleChannelConveneReq(PDomain, BYTE *, unsigned, unsigned *);
  51. BOOLEAN __fastcall HandleChannelConveneCon(PDomain, BYTE *, unsigned, unsigned *);
  52. BOOLEAN __fastcall HandleChannelDisbandReq(PDomain, BYTE *, unsigned, unsigned *);
  53. BOOLEAN __fastcall HandleChannelDisbandInd(PDomain, BYTE *, unsigned, unsigned *);
  54. BOOLEAN __fastcall HandleChannelAdmitReq(PDomain, BYTE *, unsigned, unsigned *);
  55. BOOLEAN __fastcall HandleChannelAdmitInd(PDomain, BYTE *, unsigned, unsigned *);
  56. BOOLEAN __fastcall HandleChannelExpelReq(PDomain, BYTE *, unsigned, unsigned *);
  57. BOOLEAN __fastcall HandleChannelExpelInd(PDomain, BYTE *, unsigned, unsigned *);
  58. // Defined below (prototype in MCSImpl.h for visibility in Decode.c).
  59. //BOOLEAN __fastcall HandleAllSendDataPDUs(PDomain, BYTE *, unsigned, unsigned *);
  60. // Defined in TokenPDU.c.
  61. BOOLEAN __fastcall HandleTokenGrabReq(PDomain, BYTE *, unsigned, unsigned *);
  62. BOOLEAN __fastcall HandleTokenGrabCon(PDomain, BYTE *, unsigned, unsigned *);
  63. BOOLEAN __fastcall HandleTokenInhibitReq(PDomain, BYTE *, unsigned, unsigned *);
  64. BOOLEAN __fastcall HandleTokenInhibitCon(PDomain, BYTE *, unsigned, unsigned *);
  65. BOOLEAN __fastcall HandleTokenGiveReq(PDomain, BYTE *, unsigned, unsigned *);
  66. BOOLEAN __fastcall HandleTokenGiveInd(PDomain, BYTE *, unsigned, unsigned *);
  67. BOOLEAN __fastcall HandleTokenGiveRes(PDomain, BYTE *, unsigned, unsigned *);
  68. BOOLEAN __fastcall HandleTokenGiveCon(PDomain, BYTE *, unsigned, unsigned *);
  69. BOOLEAN __fastcall HandleTokenPleaseReq(PDomain, BYTE *, unsigned, unsigned *);
  70. BOOLEAN __fastcall HandleTokenPleaseInd(PDomain, BYTE *, unsigned, unsigned *);
  71. BOOLEAN __fastcall HandleTokenReleaseReq(PDomain, BYTE *, unsigned, unsigned *);
  72. BOOLEAN __fastcall HandleTokenReleaseCon(PDomain, BYTE *, unsigned, unsigned *);
  73. BOOLEAN __fastcall HandleTokenTestReq(PDomain, BYTE *, unsigned, unsigned *);
  74. BOOLEAN __fastcall HandleTokenTestCon(PDomain, BYTE *, unsigned, unsigned *);
  75. /*
  76. * These are listed in the 0-based enumeration order specified in the T.125
  77. * spec. Decode the 6-bit PER encoded PDU type enumeration bits and cast to
  78. * an index into this table to get the info.
  79. */
  80. const MCSPDUInfo DomainPDUTable[] =
  81. {
  82. // 0
  83. StrOnDbg("Plumb Domain Indication", NULL /* HandlePlumbDomainInd */),
  84. StrOnDbg("Erect Domain Request", HandleErectDomainReq),
  85. StrOnDbg("Merge Channels Request", NULL /* HandleMergeChannelsReq */),
  86. StrOnDbg("Merge Channels Confirm", NULL /* HandleMergeChannelsCon */),
  87. StrOnDbg("Purge Channels Indication", NULL /* HandlePurgeChannelsInd */),
  88. // 5
  89. StrOnDbg("Merge Tokens Request", NULL /* HandleMergeTokensReq */),
  90. StrOnDbg("Merge Tokens Confirm", NULL /* HandleMergeTokensCon */),
  91. StrOnDbg("Purge Tokens Indication", NULL /* HandlePurgeTokensInd */),
  92. StrOnDbg("Disconnect Provider Ultimatum", HandleDisconnectProviderUlt),
  93. StrOnDbg("Reject MCS PDU Ultimatum", NULL /*HandleRejectMCSPDUUlt */),
  94. // 10
  95. StrOnDbg("Attach User Request", HandleAttachUserReq),
  96. StrOnDbg("Attach User Confirm", NULL /* HandleAttachUserCon */),
  97. StrOnDbg("Detach User Request", NULL /* HandleDetachUserReq */),
  98. StrOnDbg("Detach User Indication", NULL /* HandleDetachUserInd */),
  99. StrOnDbg("Channel Join Request", HandleChannelJoinReq),
  100. // 15
  101. StrOnDbg("Channel Join Confirm", NULL /* HandleChannelJoinCon */),
  102. StrOnDbg("Channel Leave Request", NULL /* HandleChannelLeaveReq */),
  103. StrOnDbg("Channel Convene Request", NULL /* HandleChannelConveneReq */),
  104. StrOnDbg("Channel Convene Confirm", NULL /* HandleChannelConveneCon */),
  105. StrOnDbg("Channel Disband Request", NULL /* HandleChannelDisbandReq */),
  106. // 20
  107. StrOnDbg("Channel Disband Indication", NULL /* HandleChannelDisbandInd */),
  108. StrOnDbg("Channel Admit Request", NULL /* HandleChannelAdmitReq */),
  109. StrOnDbg("Channel Admit Indication", NULL /* HandleChannelAdmitInd */),
  110. StrOnDbg("Channel Expel Request", NULL /* HandleChannelExpelReq */),
  111. StrOnDbg("Channel Expel Indication", NULL /* HandleChannelExpelInd */),
  112. // 25
  113. StrOnDbg("Send Data Request", HandleAllSendDataPDUs),
  114. StrOnDbg("Send Data Indication", HandleAllSendDataPDUs),
  115. StrOnDbg("Uniform Send Data Request", HandleAllSendDataPDUs),
  116. StrOnDbg("Uniform Send Data Indication", HandleAllSendDataPDUs),
  117. StrOnDbg("Token Grab Request", NULL /* HandleTokenGrabReq */),
  118. // 30
  119. StrOnDbg("Token Grab Confirm", NULL /* HandleTokenGrabCon */),
  120. StrOnDbg("Token Inhibit Request", NULL /* HandleTokenInhibitReq */),
  121. StrOnDbg("Token Inhibit Confirm", NULL /* HandleTokenInhibitCon */),
  122. StrOnDbg("Token Give Request", NULL /* HandleTokenGiveReq */),
  123. StrOnDbg("Token Give Indication", NULL /* HandleTokenGiveInd */),
  124. // 35
  125. StrOnDbg("Token Give Response", NULL /* HandleTokenGiveRes */),
  126. StrOnDbg("Token Give Confirm", NULL /* HandleTokenGiveCon */),
  127. StrOnDbg("Token Please Request", NULL /* HandleTokenPleaseReq */),
  128. StrOnDbg("Token Please Indication", NULL /* HandleTokenPleaseInd */),
  129. StrOnDbg("Token Release Request", NULL /* HandleTokenReleaseReq */),
  130. // 40
  131. StrOnDbg("Token Release Confirm", NULL /* HandleTokenReleaseCon */),
  132. StrOnDbg("Token Test Request", NULL /* HandleTokenTestReq */),
  133. StrOnDbg("Token Test Confirm", NULL /* HandleTokenTestCon */)
  134. };
  135. /*
  136. * Returns the number of bytes total that will be used to encode this length.
  137. */
  138. int GetTotalLengthDeterminantEncodingSize(int Length) {
  139. int N16KBlocks;
  140. if (Length <= 127) return 1;
  141. if (Length <= 16383) return 2;
  142. N16KBlocks = Length / 16384;
  143. if (N16KBlocks > 4) N16KBlocks = 4;
  144. // 1 byte for # 16K blocks up to 4, then remainder encoded separately.
  145. return 1 + GetTotalLengthDeterminantEncodingSize(Length - N16KBlocks *
  146. 16384);
  147. }
  148. /*
  149. * Encodes a length determinant.
  150. * Note that bit references here are in the range 7..0 where 7 is the high bit.
  151. * The ASN.1 spec uses 8..1.
  152. */
  153. void __fastcall EncodeLengthDeterminantPER(
  154. BYTE *pBuffer, // [IN], where to encode.
  155. unsigned Length, // [IN], length number to encode.
  156. unsigned *pLengthEncoded, // [OUT], number of bytes that were encoded.
  157. BOOLEAN *pbLarge, // [OUT] TRUE if more encoded blocks are needed to encode this length.
  158. unsigned *pNBytesConsumed) // [OUT] Count of bytes consumed in encoding.
  159. {
  160. *pbLarge = FALSE;
  161. *pLengthEncoded = Length;
  162. *pNBytesConsumed = 1;
  163. if (Length <= 0x7F) {
  164. // <= 127 means encode in lower 7 bits of first byte, so that bit 7
  165. // is zero.
  166. *pBuffer = (BYTE)Length;
  167. }
  168. else if (Length <= 16383) {
  169. // Set bit 7 but not bit 6, encode length in last 6 bits
  170. // of 1st byte and entire 2nd byte (14 bits total).
  171. PutByteswappedShort(pBuffer, (Length | 0x8000));
  172. *pNBytesConsumed = 2;
  173. }
  174. else {
  175. // Set bits 7 and 6, encode up to four blocks of 16K (16384) into
  176. // one byte, pass back that block is large for future coding.
  177. int N16KBlocks = Length / 16384;
  178. // We never expect more than 64K of data owing to X.224 limits.
  179. ASSERT(N16KBlocks <= 4);
  180. if (N16KBlocks > 4) N16KBlocks = 4;
  181. *pBuffer = N16KBlocks | 0xC0;
  182. *pLengthEncoded = N16KBlocks * 16384;
  183. *pbLarge = TRUE;
  184. }
  185. }
  186. /*
  187. * Handler functions
  188. */
  189. #ifdef MCS_Future
  190. /*
  191. * PDU 0
  192. *
  193. * PDin ::= [APPLICATION 0] IMPLICIT SEQUENCE {
  194. * heightLimit INTEGER (0..MAX)
  195. * }
  196. *
  197. * This PDU is sent from the top provider downward when a new node is added
  198. * to the domain. It is intended to ferret out loops in the domain, as well
  199. * as enforce the negotiated maximum domain height.
  200. */
  201. // pBuffer should point to the place where the X.224 header will start. Total
  202. // size specified by PDinPDUSize.
  203. void CreatePlumbDomainInd(
  204. unsigned short HeightLimit,
  205. BYTE *pBuffer)
  206. {
  207. // Set up first byte with the type.
  208. pBuffer[X224_DataHeaderSize] = MCS_PLUMB_DOMAIN_INDICATION_ENUM << 2;
  209. // Add HeightLimit.
  210. PutByteswappedShort(pBuffer + X224_DataHeaderSize + 1, HeightLimit);
  211. // Set up X224 header based on the final size of the packet.
  212. CreateX224DataHeader(pBuffer, PDinBaseSize, TRUE);
  213. }
  214. BOOLEAN __fastcall HandlePlumbDomainInd(
  215. PDomain pDomain,
  216. BYTE *Frame,
  217. unsigned BytesLeft,
  218. unsigned *pNBytesConsumed)
  219. {
  220. if (BytesLeft < PDinBaseSize)
  221. return FALSE;
  222. #if 0
  223. // Data unpacking code, not used right now since we should not receive this PDU.
  224. int HeightLimit;
  225. // Get HeightLimit.
  226. HeightLimit = (int)GetByteswappedShort(Frame + 1);
  227. #endif
  228. if (pDomain->bTopProvider) {
  229. ErrOut(pDomain->pContext, "Plumb-domain indication PDU received; "
  230. "we are top provider, this should never happen, rejecting");
  231. ReturnRejectPDU(pDomain, Diag_ForbiddenPDUUpward, Frame, PDinBaseSize);
  232. }
  233. else {
  234. ErrOut(pDomain->pContext, "Plumb-domain indication PDU received, "
  235. "not supported");
  236. ASSERT(FALSE);
  237. //MCS FUTURE: Unpack, check if height limit is zero. If so, we need
  238. // to disconnect all providers lower than us, since this means
  239. // we have reached the maximum allowable depth in the domain.
  240. }
  241. // Skip the bytes received no matter what.
  242. *pNBytesConsumed = PDinBaseSize;
  243. return TRUE;
  244. }
  245. #endif // MCS_Future
  246. /*
  247. * PDU 1
  248. *
  249. * EDrq ::= [APPLICATION 1] IMPLICIT SEQUENCE {
  250. * subHeight INTEGER (0..MAX)
  251. * subInterval INTEGER (0..MAX)
  252. * }
  253. *
  254. * This PDU is sent upwards by a lower node to its upward connection when
  255. * either its height in the domain changes (which occurs only when
  256. * domains are merged) or its requirements for throughput enforcement
  257. * change.
  258. * Though this PDU may be sent by a lower node upon completion of a
  259. * domain connection, its information is unneeded for this implementation.
  260. */
  261. BOOLEAN __fastcall HandleErectDomainReq(
  262. PDomain pDomain,
  263. BYTE *Frame,
  264. unsigned BytesLeft,
  265. unsigned *pNBytesConsumed)
  266. {
  267. if (BytesLeft < EDrqBaseSize)
  268. return FALSE;
  269. if (pDomain->bTopProvider) {
  270. // We don't unpack the PDU, just ignore for this implementation.
  271. TraceOut(pDomain->pContext, "Erect-domain request PDU received, ignored");
  272. #if 0
  273. // PDU unpacking code, unneeded for the current implementation.
  274. int SubHeight, SubInterval;
  275. // Get parameters.
  276. SubHeight = (int)GetByteswappedShort(Frame + 1);
  277. SubInterval = (int)GetByteswappedShort(Frame + 3);
  278. // Actions at this point would be to update the internal database
  279. // of subordinate nodes with the new information and, possibly,
  280. // pass the PDU upward again (though the latter is not well
  281. // specified in the T.125 spec).
  282. #endif
  283. }
  284. else {
  285. ErrOut(pDomain->pContext, "Erect-domain request PDU received, "
  286. "not supported");
  287. ASSERT(FALSE);
  288. // MCS FUTURE: Forward PDU to upward connection.
  289. }
  290. // Skip the bytes for this PDU no matter what.
  291. *pNBytesConsumed = EDrqBaseSize;
  292. return TRUE;
  293. }
  294. /*
  295. * PDU 8
  296. *
  297. * DPum ::= [APPLICATION 8] IMPLICIT SEQUENCE {
  298. * reason Reason
  299. * }
  300. *
  301. * This PDU is sent upward or downward on a connection when it is about
  302. * to be destroyed. There is no reply to this PDU; it simply means a node
  303. * is going away, irrevocably.
  304. */
  305. // pBuffer points to where the X.224 header will start. Total size is given
  306. // in DPumPDUSize.
  307. void CreateDisconnectProviderUlt(int Reason, BYTE *pBuffer)
  308. {
  309. // Set up first byte with the type.
  310. pBuffer[X224_DataHeaderSize] = MCS_DISCONNECT_PROVIDER_ULTIMATUM_ENUM << 2;
  311. // Add Reason to first and second bytes.
  312. pBuffer[X224_DataHeaderSize + 1] = 0;
  313. Put3BitFieldAtBit1(pBuffer + X224_DataHeaderSize, Reason);
  314. // Set up X224 header based on the final size of the packet.
  315. CreateX224DataHeader(pBuffer, DPumBaseSize, TRUE);
  316. }
  317. BOOLEAN __fastcall HandleDisconnectProviderUlt(
  318. PDomain pDomain,
  319. BYTE *Frame,
  320. unsigned BytesLeft,
  321. unsigned *pNBytesConsumed)
  322. {
  323. NTSTATUS Status;
  324. DisconnectProviderIndicationIoctl DPin;
  325. if (BytesLeft < DPumBaseSize)
  326. return FALSE;
  327. *pNBytesConsumed = DPumBaseSize;
  328. TraceOut(pDomain->pContext, "Received DPum PDU");
  329. // If we already received a DPum or X.224 disconnect, do not send the
  330. // indications upward.
  331. if (pDomain->State == State_Disconnected) {
  332. ErrOut(pDomain->pContext, "Received an extra DPum PDU, ignoring");
  333. return TRUE;
  334. }
  335. // We do not check the connection state other than disconnected -- it
  336. // is a small client bug that it will send a DPum no matter if
  337. // we've connected yet.
  338. pDomain->State = State_Disconnected;
  339. // Begin filling out disconnect-provider indication for the node
  340. // controller.
  341. DPin.Header.hUser = NULL; // Node controller.
  342. DPin.Header.Type = MCS_DISCONNECT_PROVIDER_INDICATION;
  343. DPin.hConn = NULL;
  344. // Reason is a 3-bit field starting at bit 1 of the 1st byte.
  345. DPin.Reason = (int)Get3BitFieldAtBit1(Frame);
  346. // Disconnect remote users only.
  347. DisconnectProvider(pDomain, FALSE, DPin.Reason);
  348. pDomain->bEndConnectionPacketReceived = TRUE;
  349. if (!pDomain->bChannelBound || !pDomain->bT120StartReceived) {
  350. if (!pDomain->bChannelBound)
  351. TraceOut(pDomain->pContext, "HandleDisconnProvUlt(): Cannot "
  352. "send DISCONNECT_PROV_IND to user mode, "
  353. "QueryVirtBindings not received or server-side "
  354. "disconnect occurred");
  355. else
  356. TraceOut(pDomain->pContext, "HandleDisconnProvUlt(): Cannot "
  357. "send DISCONN_PROV_IND to user mode, T120_START not "
  358. "received");
  359. pDomain->bDPumReceivedNotInput = TRUE;
  360. pDomain->DelayedDPumReason = DPin.Reason;
  361. }
  362. else {
  363. //
  364. // Let TD know that the comming disconnection is expected
  365. //
  366. ICA_STACK_BROKENREASON brkReason;
  367. SD_IOCTL SdIoctl;
  368. brkReason.BrokenReason = TD_USER_BROKENREASON_TERMINATING;
  369. //
  370. // Send an IOCTL down to notify that this is an expected
  371. // disconnection otherwise the broken reason would
  372. // eventually make it's way back to termsrv as
  373. // 'BrokenReason_Unexpected' and this causes problems
  374. // e.g see whistler bug 17714
  375. //
  376. SdIoctl.IoControlCode = IOCTL_ICA_STACK_SET_BROKENREASON;
  377. SdIoctl.InputBuffer = &brkReason;
  378. SdIoctl.InputBufferLength = sizeof(brkReason);
  379. SdIoctl.OutputBuffer = NULL;
  380. SdIoctl.OutputBufferLength = 0;
  381. Status = IcaCallNextDriver(pDomain->pContext,
  382. SD$IOCTL,
  383. &SdIoctl);
  384. if (!NT_SUCCESS(Status)) {
  385. WarnOut1(pDomain->pContext, "HandleDisconnProvUlt(): "
  386. "Could not send broken reason notifcation to next driver"
  387. "status=%X, ignoring error", Status);
  388. }
  389. // Send the DPin to the node controller channel.
  390. TraceOut(pDomain->pContext, "HandleDisconnProvUlt(): Sending "
  391. "DISCONNECT_PROV_IND upward");
  392. Status = IcaChannelInput(pDomain->pContext, Channel_Virtual,
  393. Virtual_T120ChannelNum, NULL, (BYTE *)&DPin, sizeof(DPin));
  394. if (!NT_SUCCESS(Status)) {
  395. // We ignore the error -- if the stack is coming down, the link
  396. // may have been broken, so this is not a major concern.
  397. WarnOut1(pDomain->pContext, "HandleDisconnProvUlt(): "
  398. "Could not send notification to node controller, "
  399. "status=%X, ignoring error", Status);
  400. }
  401. }
  402. return TRUE;
  403. }
  404. /*
  405. * PDU 9
  406. *
  407. * RJum ::= [APPLICATION 9] IMPLICIT SEQUENCE {
  408. * diagnostic Diagnostic,
  409. * initialOctets OCTET STRING
  410. * }
  411. */
  412. NTSTATUS ReturnRejectPDU(
  413. PDomain pDomain,
  414. int Diagnostic,
  415. BYTE *BadPDUData,
  416. unsigned BadPDUSize)
  417. {
  418. POUTBUF pOutBuf;
  419. NTSTATUS Status;
  420. unsigned Size;
  421. // Determine the largest chunk that will fit in a maximum-sized PDU.
  422. Size = RJumPDUSize(BadPDUSize);
  423. if (Size > pDomain->DomParams.MaxPDUSize)
  424. BadPDUSize = pDomain->DomParams.MaxPDUSize;
  425. // Alloc buffer for return. Must be constrained by the largest size of
  426. // return PDU.
  427. Status = IcaBufferAlloc(pDomain->pContext, FALSE, TRUE,
  428. RJumPDUSize(BadPDUSize), NULL, &pOutBuf);
  429. if (Status != STATUS_SUCCESS) {
  430. ErrOut(pDomain->pContext, "Could not allocate an OutBuf for an RJum PDU "
  431. "send, send ignored");
  432. // No asserts, if we cannot send this PDU it's like the incoming PDU
  433. // was ignored.
  434. return Status;
  435. }
  436. CreateRejectMCSPDUUlt(Diagnostic, BadPDUData, BadPDUSize, pOutBuf->pBuffer);
  437. pOutBuf->ByteCount = RJumPDUSize(BadPDUSize);
  438. // MCS FUTURE: This would have to change to make sure we send to the
  439. // right connection instead of the implicit downward connection.
  440. Status = SendOutBuf(pDomain, pOutBuf);
  441. if (!NT_SUCCESS(Status))
  442. ErrOut(pDomain->pContext, "Could not send a RJum PDU, send ignored");
  443. return Status;
  444. }
  445. // pBuffer points to the beginning of the space where the X.224 data header
  446. // will start. Total size is given in macro RJumPDUSize().
  447. void CreateRejectMCSPDUUlt(
  448. int Diagnostic,
  449. BYTE *BadPDUData,
  450. unsigned BadPDUSize,
  451. BYTE *pBuffer)
  452. {
  453. BOOLEAN bLarge;
  454. unsigned NBytesConsumed, EncodedLength;
  455. // Set up first byte with the type.
  456. pBuffer[X224_DataHeaderSize] = MCS_REJECT_ULTIMATUM_ENUM << 2;
  457. // Add Diagnostic to first and second bytes.
  458. pBuffer[X224_DataHeaderSize + 1] = 0;
  459. Put4BitFieldAtBit1(pBuffer + X224_DataHeaderSize, Diagnostic);
  460. // Encode the PDU size.
  461. EncodeLengthDeterminantPER(
  462. pBuffer + X224_DataHeaderSize + 2,
  463. BadPDUSize,
  464. &EncodedLength,
  465. &bLarge,
  466. &NBytesConsumed);
  467. // We won't handle greater than 16383 bytes of encoded length right now.
  468. ASSERT(!bLarge);
  469. // Copy offending data into the output PDU.
  470. RtlCopyMemory(pBuffer + X224_DataHeaderSize + 2 + NBytesConsumed,
  471. BadPDUData, BadPDUSize);
  472. // Set up X224 header based on the final size of the packet.
  473. CreateX224DataHeader(pBuffer, RJumBaseSize(BadPDUSize), TRUE);
  474. }
  475. BOOLEAN __fastcall HandleRejectMCSPDUUlt(
  476. PDomain pDomain,
  477. BYTE *Frame,
  478. unsigned BytesLeft,
  479. unsigned *pNBytesConsumed)
  480. {
  481. BOOLEAN bLarge;
  482. unsigned Diagnostic, DataLength, NBytesConsumed;
  483. // There must at least be Diagnostic field.
  484. if (BytesLeft < 2)
  485. return FALSE;
  486. // Get Diagnostic code -- 4-bit enumeration bitfield, starting at bit 1 of
  487. // byte 1, shifted to make a code starting at 0.
  488. Diagnostic = Get4BitFieldAtBit1(Frame);
  489. // Get DataLength. This is a special case requiring handling a length
  490. // determinant.
  491. if (!DecodeLengthDeterminantPER(Frame + 2, BytesLeft - 2, &bLarge,
  492. &DataLength, &NBytesConsumed))
  493. return FALSE;
  494. // We are not handling more than 16383 bytes encoded length right now.
  495. ASSERT(!bLarge);
  496. // Raw data is at Frame + 2 + NBytesConsumed.
  497. if (BytesLeft < (2 + NBytesConsumed + DataLength))
  498. return FALSE;
  499. ErrOut1(pDomain->pContext, "Received reject PDU ultimatum, type byte is 0x%X",
  500. Frame[2 + NBytesConsumed + X224_DataHeaderSize]);
  501. *pNBytesConsumed = 2 + NBytesConsumed + DataLength;
  502. return TRUE;
  503. }
  504. /*
  505. * PDU 10
  506. *
  507. * AUrq ::= [APPLICATION 10] IMPLICIT SEQUENCE {
  508. * }
  509. */
  510. BOOLEAN __fastcall HandleAttachUserReq(
  511. PDomain pDomain,
  512. BYTE *Frame,
  513. unsigned BytesLeft,
  514. unsigned *pNBytesConsumed)
  515. {
  516. TraceOut(pDomain->pContext, "Received an AttachUserReq PDU");
  517. // We don't need to do any decoding here -- this is a null packet beyond
  518. // the initial PDU type byte.
  519. *pNBytesConsumed = AUrqBaseSize;
  520. if (pDomain->bTopProvider) {
  521. POUTBUF pOutBuf;
  522. BOOLEAN bCompleted;
  523. unsigned MaxSendSize;
  524. NTSTATUS Status;
  525. MCSError MCSErr;
  526. UserAttachment *pUA;
  527. // Alloc buffer for largest size of return PDU.
  528. // This allocation is vital to stack communication and must succeed.
  529. do {
  530. Status = IcaBufferAlloc(pDomain->pContext, FALSE, TRUE,
  531. AUcfPDUSize(TRUE), NULL, &pOutBuf);
  532. if (Status != STATUS_SUCCESS)
  533. ErrOut(pDomain->pContext, "Could not allocate an OutBuf for an "
  534. "AUcf PDU send, retrying");
  535. } while (Status != STATUS_SUCCESS);
  536. // Call the kernel mode API. We will munge extra info below as needed.
  537. MCSErr = MCSAttachUserRequest(pDomain, NULL, NULL, NULL, &pUA,
  538. &MaxSendSize, &bCompleted);
  539. if (MCSErr == MCS_NO_ERROR) {
  540. ASSERT(bCompleted);
  541. CreateAttachUserCon(RESULT_SUCCESSFUL, TRUE, pUA->UserID,
  542. pOutBuf->pBuffer);
  543. pOutBuf->ByteCount = AUcfPDUSize(TRUE);
  544. // Change the UA to show that user is nonlocal.
  545. pUA->bLocal = FALSE;
  546. }
  547. else {
  548. CreateAttachUserCon(RESULT_UNSPECIFIED_FAILURE, FALSE,
  549. NULL_ChannelID, pOutBuf->pBuffer);
  550. pOutBuf->ByteCount = AUcfPDUSize(FALSE);
  551. }
  552. Status = SendOutBuf(pDomain, pOutBuf);
  553. if (!NT_SUCCESS(Status)) {
  554. // This should only occur if the stack is going down; the
  555. // requester will not ever receive a reply.
  556. ErrOut(pDomain->pContext, "Problem sending AUcf PDU to TD");
  557. // Remove the user from the user list, quietly.
  558. SListRemove(&pDomain->UserAttachmentList, (UINT_PTR)pUA, &pUA);
  559. ASSERT(FALSE);
  560. return TRUE;
  561. }
  562. }
  563. else {
  564. ErrOut(pDomain->pContext, "Attach-user request PDU received, "
  565. "not supported");
  566. ASSERT(FALSE);
  567. // MCS FUTURE: Forward PDU to upward connection.
  568. }
  569. return TRUE;
  570. }
  571. /*
  572. * PDU 11
  573. *
  574. * AUcf ::= [APPLICATION 11] IMPLICIT SEQUENCE {
  575. * result Result,
  576. * initiator UserId OPTIONAL
  577. * }
  578. */
  579. // pBuffer points to beginning of space where X.224 data header will start.
  580. // Total size needed given by macro AUcfPDUSize().
  581. void CreateAttachUserCon(
  582. int Result,
  583. BOOLEAN bInitiatorPresent,
  584. UserID Initiator,
  585. BYTE *pBuffer)
  586. {
  587. // Set up first byte with the type and whether Initiator is present.
  588. pBuffer[X224_DataHeaderSize] = MCS_ATTACH_USER_CONFIRM_ENUM << 2;
  589. if (bInitiatorPresent) pBuffer[X224_DataHeaderSize] |= 0x02;
  590. // Add Result to first and second bytes.
  591. pBuffer[X224_DataHeaderSize + 1] = 0;
  592. Put4BitFieldAtBit0(pBuffer + X224_DataHeaderSize, Result);
  593. // Add Initiator, if present.
  594. if (bInitiatorPresent)
  595. PutUserID(pBuffer + X224_DataHeaderSize + 2, Initiator);
  596. // Set up X224 header based on the final size of the packet.
  597. CreateX224DataHeader(pBuffer, AUcfBaseSize(bInitiatorPresent), TRUE);
  598. }
  599. #ifdef MCS_Future
  600. BOOLEAN __fastcall HandleAttachUserCon(
  601. PDomain pDomain,
  602. BYTE *Frame,
  603. unsigned BytesLeft,
  604. unsigned *pNBytesConsumed)
  605. {
  606. BOOLEAN bInitiatorPresent;
  607. unsigned Size;
  608. // At least enough bytes to get to bInitiatorPresent bit and Result.
  609. if (BytesLeft < 2)
  610. return FALSE;
  611. // Bit 1 in byte 1 is a flag for whether the initiator UserID is present
  612. // (it is OPTIONAL in the ASN.1 source for this PDU).
  613. bInitiatorPresent = (*Frame & 0x02);
  614. // We did not receive the whole frame.
  615. Size = AUcfBaseSize(bInitiatorPresent);
  616. if (BytesLeft < Size)
  617. return FALSE;
  618. if (pDomain->bTopProvider) {
  619. ErrOut(pDomain->pContext, "Attach-user confirm PDU received; "
  620. "we are top provider, this should never happen, rejecting");
  621. ReturnRejectPDU(pDomain, Diag_ForbiddenPDUUpward, Frame, Size);
  622. }
  623. else {
  624. ErrOut(pDomain->pContext, "Attach-user confirm PDU received, "
  625. "not supported");
  626. ASSERT(FALSE);
  627. #if 0
  628. // Decode code not used right now.
  629. int Result;
  630. UserID InitiatorID;
  631. // Result, starting at bit 0 of the 1st byte.
  632. Result = Get4BitFieldAtBit0(Frame);
  633. // Get Initiator.
  634. if (bUserIDPresent) UserID = GetUserID(Frame + 2);
  635. //MCS FUTURE: Actions here are to state-transition past a waiting-
  636. // for-AU confirm state, check the Result code, store the Initiator
  637. // userID as our new UserID.
  638. #endif
  639. }
  640. // At least skip the bytes in the PDU.
  641. *pNBytesConsumed = Size;
  642. return TRUE;
  643. }
  644. #endif // MCS_Future
  645. /*
  646. * PDU 12
  647. *
  648. * DUrq ::= [APPLICATION 12] IMPLICIT SEQUENCE {
  649. * reason Reason,
  650. * userIds SET OF UserId
  651. * }
  652. */
  653. BOOLEAN __fastcall HandleDetachUserReq(
  654. PDomain pDomain,
  655. BYTE *Frame,
  656. unsigned BytesLeft,
  657. unsigned *pNBytesConsumed)
  658. {
  659. UserID CurUserID;
  660. BOOLEAN bLarge, bFound;
  661. unsigned i, Reason, NUsers, NBytesConsumed, Size;
  662. NTSTATUS Status;
  663. UserHandle hUser;
  664. UserAttachment *pUA;
  665. // Must at least have Reason bytes.
  666. if (BytesLeft < 2)
  667. return FALSE;
  668. // Get NUsers. This is a special case requiring handling a length
  669. // determinant.
  670. if (!DecodeLengthDeterminantPER(Frame + 2, BytesLeft - 2, &bLarge,
  671. &NUsers, &NBytesConsumed))
  672. return FALSE;
  673. // We are not handling more than 16383 detach users in a PDU.
  674. ASSERT(!bLarge);
  675. Size = DUrqBaseSize(NUsers);
  676. if (BytesLeft < Size)
  677. return FALSE;
  678. if (pDomain->bTopProvider) {
  679. MCSError MCSErr;
  680. // Get Reason.
  681. Reason = Get3BitFieldAtBit1(Frame);
  682. // User IDs are a byteswapped word array starting at Frame + 2 +
  683. // NBytesConsumed.
  684. // Iterate all listed users, find in attachment list, remove.
  685. for (i = 0; i < NUsers; i++) {
  686. CurUserID = GetUserID(Frame + 2 + NBytesConsumed +
  687. sizeof(short) * i);
  688. // We do not have a list indexed by UserID, so we have to do the
  689. // search here.
  690. bFound = FALSE;
  691. SListResetIteration(&pDomain->UserAttachmentList);
  692. while (SListIterate(&pDomain->UserAttachmentList,
  693. (UINT_PTR *)&hUser, &pUA)) {
  694. if (pUA->UserID == CurUserID) {
  695. bFound = TRUE;
  696. break;
  697. }
  698. }
  699. if (bFound)
  700. MCSErr = DetachUser(pDomain, hUser, REASON_USER_REQUESTED,
  701. FALSE);
  702. else
  703. ErrOut(pDomain->pContext, "A UserID received in a detach-user "
  704. "request PDU is not present");
  705. }
  706. }
  707. else {
  708. ErrOut(pDomain->pContext, "Detach-user request PDU received, "
  709. "not supported");
  710. ASSERT(FALSE);
  711. // MCS FUTURE: Forward PDU to upward connection.
  712. }
  713. *pNBytesConsumed = Size;
  714. return TRUE;
  715. }
  716. /*
  717. * PDU 13
  718. *
  719. * DUin ::= [APPLICATION 13] IMPLICIT SEQUENCE {
  720. * reason Reason,
  721. * userIds SET OF UserId
  722. * }
  723. */
  724. // pBuffer is a pointer to the beginning of where the X.224 data header
  725. // will be. Required encoding size for the whole PDU is given in
  726. // macro DUinPDUSize().
  727. void CreateDetachUserInd(
  728. MCSReason Reason, // [IN] Reason code.
  729. int NUserIDs, // [IN] # of user IDs to encode.
  730. UserID *UserIDs, // [IN] Array of UserIDs.
  731. BYTE *pBuffer) // [IN] Pointer to buffer in which to encode.
  732. {
  733. int i, EncodedLength, NBytesConsumed;
  734. BOOLEAN bLarge;
  735. // Set up first byte with the type.
  736. pBuffer[X224_DataHeaderSize] = MCS_DETACH_USER_INDICATION_ENUM << 2;
  737. // Add Reason to first and second bytes.
  738. pBuffer[X224_DataHeaderSize + 1] = 0;
  739. Put3BitFieldAtBit1(pBuffer + X224_DataHeaderSize, Reason);
  740. // Encode the number of User IDs.
  741. EncodeLengthDeterminantPER(
  742. pBuffer + X224_DataHeaderSize + 2,
  743. NUserIDs,
  744. &EncodedLength,
  745. &bLarge,
  746. &NBytesConsumed);
  747. // We are not handling more than 16383 UserIDs.
  748. ASSERT(!bLarge);
  749. // Encode user ID array.
  750. for (i = 0; i < NUserIDs; i++)
  751. PutUserID(pBuffer + X224_DataHeaderSize + 2 + NBytesConsumed
  752. + sizeof(short) * i, UserIDs[i]);
  753. // Set up X224 header based on the final size of the packet.
  754. CreateX224DataHeader(pBuffer, DUinBaseSize(NUserIDs), TRUE);
  755. }
  756. #ifdef MCS_Future
  757. BOOLEAN __fastcall HandleDetachUserInd(
  758. PDomain pDomain,
  759. BYTE *Frame,
  760. unsigned BytesLeft,
  761. unsigned *pNBytesConsumed)
  762. {
  763. BOOLEAN bLarge;
  764. unsigned NUsers, NBytesConsumed, Size;
  765. // Must at least have Reason bytes.
  766. if (BytesLeft < 2) return FALSE; // Only cover Reason bytes.
  767. // Get NUsers. This is a special case requiring handling a length
  768. // determinant.
  769. if (!DecodeLengthDeterminantPER(Frame + 2, BytesLeft - 2, &bLarge,
  770. &NUsers, &NBytesConsumed))
  771. return FALSE;
  772. // We are not handling more than 16383 detached users in a PDU.
  773. ASSERT(!bLarge);
  774. Size = DUinBaseSize(NUsers);
  775. if (BytesLeft < Size)
  776. return FALSE;
  777. if (pDomain->bTopProvider) {
  778. ErrOut(pDomain->pContext, "Detach-user indication PDU received; "
  779. "we are top provider, this should never happen, rejecting");
  780. ReturnRejectPDU(pDomain, Diag_ForbiddenPDUUpward, Frame, Size);
  781. }
  782. else {
  783. ErrOut(pDomain->pContext, "Detach-user indication PDU received, "
  784. "not supported");
  785. ASSERT(FALSE);
  786. #if 0
  787. // This is decode code, which is not needed because we should not
  788. // receive this PDU.
  789. int Reason;
  790. // Get Reason.
  791. Reason = Get3BitFieldAtBit1(Frame);
  792. // User IDs are a byteswapped word array starting at Frame + 2 +
  793. // NBytesConsumed.
  794. #endif
  795. }
  796. *pNBytesConsumed = Size;
  797. return TRUE;
  798. }
  799. #endif // MCS_Future
  800. /*
  801. * PDU 14
  802. *
  803. * CJrq ::= [APPLICATION 14] IMPLICIT SEQUENCE {
  804. * initiator UserId,
  805. * channelId ChannelId
  806. * }
  807. */
  808. BOOLEAN __fastcall HandleChannelJoinReq(
  809. PDomain pDomain,
  810. BYTE *Frame,
  811. unsigned BytesLeft,
  812. unsigned *pNBytesConsumed)
  813. {
  814. TraceOut(pDomain->pContext, "Received a ChannelJoinReq PDU");
  815. if (BytesLeft < CJrqBaseSize)
  816. return FALSE;
  817. *pNBytesConsumed = CJrqBaseSize;
  818. if (pDomain->bTopProvider) {
  819. UserID Initiator;
  820. POUTBUF pOutBuf;
  821. BOOLEAN bFound, bCompleted;
  822. MCSError MCSErr;
  823. NTSTATUS Status;
  824. MCSResult Result;
  825. ChannelID ChannelID;
  826. ChannelHandle hChannel;
  827. UserAttachment *pUA;
  828. Initiator = GetUserID(Frame + 1);
  829. ChannelID = GetChannelID(Frame + 3);
  830. // We do not have a list indexed by UserID, so we have to do the
  831. // search here.
  832. bFound = FALSE;
  833. SListResetIteration(&pDomain->UserAttachmentList);
  834. while (SListIterate(&pDomain->UserAttachmentList,
  835. (UINT_PTR *)&pUA, &pUA)) {
  836. if (pUA->UserID == Initiator) {
  837. bFound = TRUE;
  838. break;
  839. }
  840. }
  841. if (bFound) {
  842. // Call kernel-mode API.
  843. MCSErr = MCSChannelJoinRequest(pUA, ChannelID, &hChannel,
  844. &bCompleted);
  845. if (MCSErr == MCS_NO_ERROR) {
  846. ASSERT(bCompleted);
  847. Result = RESULT_SUCCESSFUL;
  848. }
  849. else if (MCSErr == MCS_NO_SUCH_USER) {
  850. Result = RESULT_NO_SUCH_USER;
  851. }
  852. else if (MCSErr == MCS_DUPLICATE_CHANNEL) {
  853. goto EXIT_POINT;
  854. }
  855. else {
  856. Result = RESULT_UNSPECIFIED_FAILURE;
  857. }
  858. }
  859. else {
  860. ErrOut(pDomain->pContext, "Initiator UserID received in a "
  861. "channel-join request PDU is not in user list");
  862. Result = RESULT_NO_SUCH_USER;
  863. }
  864. // Alloc buffer for largest size of return PDU.
  865. // This allocation is vital to stack communication and must succeed.
  866. do {
  867. Status = IcaBufferAlloc(pDomain->pContext, FALSE, TRUE,
  868. CJcfPDUSize(TRUE), NULL, &pOutBuf);
  869. if (Status != STATUS_SUCCESS)
  870. ErrOut(pDomain->pContext, "Could not allocate an OutBuf for a "
  871. "CJcf PDU send, retrying");
  872. } while (Status != STATUS_SUCCESS);
  873. if (Result == RESULT_SUCCESSFUL) {
  874. CreateChannelJoinCon(Result, Initiator, ChannelID,
  875. TRUE, ChannelID, pOutBuf->pBuffer);
  876. pOutBuf->ByteCount = CJcfPDUSize(TRUE) ;
  877. }
  878. else {
  879. CreateChannelJoinCon(Result, Initiator, ChannelID,
  880. FALSE, NULL_ChannelID, pOutBuf->pBuffer);
  881. pOutBuf->ByteCount = CJcfPDUSize(FALSE) ;
  882. }
  883. Status = SendOutBuf(pDomain, pOutBuf);
  884. if (!NT_SUCCESS(Status)) {
  885. // This should only occur if the stack is going down; the
  886. // requester will not ever receive a reply.
  887. ErrOut(pDomain->pContext, "Problem sending CJcf PDU to TD");
  888. return TRUE;
  889. }
  890. }
  891. else {
  892. ErrOut(pDomain->pContext, "Channel-join request received, "
  893. "not supported");
  894. ASSERT(FALSE);
  895. // MCS FUTURE: Forward the PDU to the upward connection.
  896. }
  897. EXIT_POINT:
  898. return TRUE; // We don't have user data to which to skip.
  899. }
  900. /*
  901. * PDU 15
  902. *
  903. * CJcf ::= [APPLICATION 15] IMPLICIT SEQUENCE {
  904. * result Result,
  905. * initiator UserId,
  906. * requested ChannelId,
  907. * channelId ChannelId OPTIONAL
  908. * }
  909. */
  910. // pBuffer points to the beginning of the space where the X.224 data header
  911. // will start. Total bytes required given by CJcfPDUSize() macro.
  912. void CreateChannelJoinCon(
  913. int Result,
  914. UserID Initiator,
  915. ChannelID RequestedChannelID,
  916. BOOLEAN bJoinedChannelIDPresent,
  917. ChannelID JoinedChannelID,
  918. BYTE *pBuffer)
  919. {
  920. // Set up first byte with the type and whether JoinedChannelID is present.
  921. pBuffer[X224_DataHeaderSize] = MCS_CHANNEL_JOIN_CONFIRM_ENUM << 2;
  922. if (bJoinedChannelIDPresent) pBuffer[X224_DataHeaderSize] |= 0x02;
  923. // Add Result to first and second bytes.
  924. pBuffer[X224_DataHeaderSize + 1] = 0;
  925. Put4BitFieldAtBit0(pBuffer + X224_DataHeaderSize, Result);
  926. // Add Initiator, RequestedChannelID.
  927. PutUserID(pBuffer + X224_DataHeaderSize + 2, Initiator);
  928. PutChannelID(pBuffer + X224_DataHeaderSize + 4, RequestedChannelID);
  929. // Add JoinedChannelID, if present.
  930. if (bJoinedChannelIDPresent)
  931. PutChannelID(pBuffer + X224_DataHeaderSize + 6, JoinedChannelID);
  932. // Set up X224 header based on the final size of the packet.
  933. CreateX224DataHeader(pBuffer, CJcfBaseSize(bJoinedChannelIDPresent), TRUE);
  934. }
  935. #ifdef MCS_Future
  936. BOOLEAN __fastcall HandleChannelJoinCon(
  937. PDomain pDomain,
  938. BYTE *Frame,
  939. unsigned BytesLeft,
  940. unsigned *pNBytesConsumed)
  941. {
  942. BOOLEAN bJoinedChannelIDPresent;
  943. unsigned Size;
  944. // First byte containing the bJoinedChannelIDPresent bit is guaranteed
  945. // to be present since it had to be present to decode the PDU type.
  946. // Bit 1 in 1st byte is a flag for whether the joined ChannelID is present
  947. // (it is OPTIONAL in the ASN.1 source for this PDU).
  948. bJoinedChannelIDPresent = (*Frame & 0x02);
  949. Size = CJcfBaseSize(bJoinedChannelIDPresent);
  950. if (BytesLeft < Size)
  951. return FALSE;
  952. if (pDomain->bTopProvider) {
  953. ErrOut(pDomain->pContext, "Channel-join confirm PDU received;"
  954. "we are top provider, this should never happen, rejecting");
  955. ReturnRejectPDU(pDomain, Diag_ForbiddenPDUUpward, Frame, Size);
  956. }
  957. else {
  958. ErrOut(pDomain->pContext, "Channel-join confirm PDU received, "
  959. "not supported");
  960. ASSERT(FALSE);
  961. //MCS FUTURE: Decode and handle
  962. #if 0
  963. /*
  964. * This is decode code which is not used for now because we always expect
  965. * to be top provider.
  966. */
  967. int Result;
  968. UserID Initiator;
  969. ChannelID RequestedChannelID, JoinedChannelID;
  970. if (BytesLeft < (6 + (bJoinedChannelPresent ? 2 : 0))) return FALSE;
  971. Result = Get4BitFieldAtBit0(Frame);
  972. Initiator = GetUserID(Frame + 2);
  973. RequestedChannelID = GetChannelID(Frame + 4);
  974. if (bJoinedChannelIDPresent) JoinedChannelID = GetChannelID(Frame + 6);
  975. #endif
  976. }
  977. *pNBytesConsumed = Size;
  978. return TRUE;
  979. }
  980. #endif // MCS_Future
  981. /*
  982. * PDU 16
  983. *
  984. * CLrq ::= [APPLICATION 16] IMPLICIT SEQUENCE {
  985. * channelIds SET OF ChannelId
  986. * }
  987. */
  988. BOOLEAN __fastcall HandleChannelLeaveReq(
  989. PDomain pDomain,
  990. BYTE *Frame,
  991. unsigned BytesLeft,
  992. unsigned *pNBytesConsumed)
  993. {
  994. BOOLEAN bLarge, bChannelRemoved;
  995. unsigned i, UserID, NChannels, NBytesConsumed, Size;
  996. NTSTATUS Status;
  997. ChannelID ChannelID;
  998. MCSChannel *pMCSChannel;
  999. UserAttachment *pUA;
  1000. // Get NChannels. This is a special case requiring handling a length
  1001. // determinant.
  1002. if (!DecodeLengthDeterminantPER(Frame + 1, BytesLeft - 1, &bLarge,
  1003. &NChannels, &NBytesConsumed))
  1004. return FALSE;
  1005. // We are not handling more than 16383 channels to join.
  1006. ASSERT(!bLarge);
  1007. Size = CLrqBaseSize(NChannels);
  1008. if (BytesLeft < Size)
  1009. return FALSE;
  1010. *pNBytesConsumed = Size;
  1011. if (pDomain->bTopProvider) {
  1012. // MCS FUTURE: Be aware that this PDU does not include user
  1013. // attachments, so if we move to multiple connections per PD this
  1014. // will have to be differentiated to make sure only users joined
  1015. // from the connection this arrived on will be removed from the
  1016. // channel list.
  1017. MCSError MCSErr;
  1018. // For each channel listed, remove all nonlocal users.
  1019. for (i = 0; i < NChannels; i++) {
  1020. ChannelID = GetChannelID(Frame + 1 + NBytesConsumed +
  1021. sizeof(short) * i);
  1022. if (!SListGetByKey(&pDomain->ChannelList, ChannelID,
  1023. &pMCSChannel)) {
  1024. ErrOut(pDomain->pContext, "A channel specified in a "
  1025. "channel-leave request PDU does not exist");
  1026. continue;
  1027. }
  1028. // Iterate user list in the channel, check for nonlocal users.
  1029. SListResetIteration(&pMCSChannel->UserList);
  1030. while (SListIterate(&pMCSChannel->UserList, (UINT_PTR *)&pUA,
  1031. &pUA)) {
  1032. if (!pUA->bLocal) {
  1033. // Call central code in MCSCore.c.
  1034. MCSErr = ChannelLeave(pUA, pMCSChannel, &bChannelRemoved);
  1035. if (bChannelRemoved)
  1036. // The MCSChannel beneath us went away, do not continue
  1037. // trying to access list data.
  1038. break;
  1039. }
  1040. }
  1041. }
  1042. }
  1043. else {
  1044. ErrOut(pDomain->pContext, "Channel-leave request received, "
  1045. "not supported");
  1046. ASSERT(FALSE);
  1047. // MCS FUTURE: Forward the PDU to the upward connection.
  1048. }
  1049. return TRUE; // We don't have user data to which to skip.
  1050. }
  1051. /*
  1052. * PDUs 25-28
  1053. *
  1054. * SDrq/SDin/USrq/USin ::= [APPLICATION 25-28] IMPLICIT SEQUENCE {
  1055. * initiator UserId,
  1056. * channelId ChannelId,
  1057. * dataPriority DataPriority,
  1058. * segmentation Segmentation,
  1059. * userData OCTET STRING
  1060. * }
  1061. */
  1062. /*
  1063. * Create function for all SendData PDUs. Prepends header to beginning of
  1064. * data specified in MCSSendDataRequestIoctl.pData, returns in
  1065. * pNewDataStart the new beginning of the data, i.e. the beginning of the
  1066. * PDU.
  1067. * Assumes that enough space has already been allocated before the
  1068. * start of the user data.
  1069. */
  1070. // Does not return indications that ASN.1 segmentation has occurred --
  1071. // requires caller to understand and encode separately any segment
  1072. // data.
  1073. void CreateSendDataPDUHeader(
  1074. int PDUType, // MCS_SEND_DATA_INDICATION_ENUM, etc.
  1075. UserID Initiator,
  1076. ChannelID ChannelID,
  1077. MCSPriority Priority,
  1078. Segmentation Segmentation,
  1079. BYTE **ppData,
  1080. unsigned *pDataLength)
  1081. {
  1082. int NBytesConsumed, EncodedLength, PDULength;
  1083. BYTE *pCurData, *pData;
  1084. BOOLEAN bLarge;
  1085. unsigned DataLength;
  1086. // Save original pData and DataLength.
  1087. pData = *ppData;
  1088. DataLength = *pDataLength;
  1089. // First get the length determinant. It is a maximum of 2 bytes, so
  1090. // encode it at (pData-2) and shift it forward if it is smaller.
  1091. EncodeLengthDeterminantPER(
  1092. pData - 2,
  1093. DataLength,
  1094. &EncodedLength,
  1095. &bLarge,
  1096. &NBytesConsumed);
  1097. // We ignore bLarge, EncodedLength, see above comment.
  1098. if (NBytesConsumed == 1)
  1099. *(pData - 1) = *(pData - 2);
  1100. // Set the beginning of the rest of the data (which is 6 bytes).
  1101. pCurData = pData - NBytesConsumed - 6;
  1102. // Set up first byte with the type.
  1103. *pCurData = PDUType << 2;
  1104. pCurData++;
  1105. // Add Initiator, ChannelID.
  1106. PutUserID(pCurData, Initiator);
  1107. PutChannelID(pCurData + 2, ChannelID);
  1108. pCurData += 4;
  1109. // Add DataPriority (2 bits in bits 7 and 6) and Segmentation (2 bits
  1110. // into bits 5 and 4) into 6th byte. Note that the Segmentation flags
  1111. // (SEGMENTATION_BEGIN, SEGMENTATION_END) are assumed to be defined
  1112. // in their exact bit positions corresponding to the positons required
  1113. // here for encoding.
  1114. *pCurData = (BYTE)(Priority << 6) + (BYTE)Segmentation;
  1115. // Set up X.224 header based on the final size of the packet.
  1116. PDULength = NBytesConsumed + 6 + DataLength;
  1117. pCurData = pData - NBytesConsumed - 6 - X224_DataHeaderSize;
  1118. CreateX224DataHeader(pCurData, PDULength, TRUE);
  1119. *ppData = pCurData;
  1120. *pDataLength = PDULength + X224_DataHeaderSize;
  1121. }
  1122. /*
  1123. * Handler function for all SendData PDUs.
  1124. */
  1125. BOOLEAN __fastcall HandleAllSendDataPDUs(
  1126. PDomain pDomain,
  1127. BYTE *Frame,
  1128. unsigned BytesLeft,
  1129. unsigned *pNBytesConsumed)
  1130. {
  1131. BYTE *pBuffer;
  1132. UserID SenderID;
  1133. BOOLEAN bLarge, bFound;
  1134. unsigned NBytesConsumed, Size, PDUNum, DataLength;
  1135. UINT_PTR CurUserID;
  1136. NTSTATUS Status;
  1137. ChannelID ChannelID;
  1138. MCSChannel *pMCSChannel;
  1139. UserHandle hUser;
  1140. MCSPriority Priority;
  1141. Segmentation Segmentation;
  1142. UserAttachment *pUA;
  1143. // TraceOut(pDomain->pContext, "Received a SendData PDU");
  1144. // MCS FUTURE: We should forward the data upward here, since below we
  1145. // will modify the encoded buffer for ASN.1 segmentation.
  1146. // Get the PDU number again since this function handles multiple PDUs.
  1147. PDUNum = (*Frame) >> 2;
  1148. ASSERT(PDUNum >= MCS_SEND_DATA_REQUEST_ENUM &&
  1149. PDUNum <= MCS_UNIFORM_SEND_DATA_INDICATION_ENUM);
  1150. #if DBG
  1151. // Enforce hierarchical requirements on PDUs -- indications move only
  1152. // away from the top provider, requests move only toward it.
  1153. // MCS FUTURE: For indications moving toward TP from any downlevel
  1154. // connection we should send a reject-MCS-PDU back down the link.
  1155. // MCS FUTURE: If we are not TP and a request is coming from the upward
  1156. // direction send back up rejected.
  1157. // TODO FUTURE: With cross server shadowing we have two top providers
  1158. // talking to each other. Need to decide how this is best represented.
  1159. if (pDomain->StackClass == Stack_Primary) {
  1160. if (pDomain->bTopProvider && (PDUNum == MCS_SEND_DATA_INDICATION_ENUM ||
  1161. PDUNum == MCS_UNIFORM_SEND_DATA_INDICATION_ENUM)) {
  1162. ErrOut(pDomain->pContext, "HandleAllSendDataPDUs(): Received a "
  1163. "(uniform)send-data indication when we are top provider!");
  1164. // Ignore the error.
  1165. }
  1166. }
  1167. #endif
  1168. // At least to DataLength should be present.
  1169. if (BytesLeft < 6)
  1170. return FALSE;
  1171. // Get initiator, ChannelID.
  1172. SenderID = GetUserID(Frame + 1);
  1173. ChannelID = GetChannelID(Frame + 3);
  1174. // Get DataPriority, a 2-bit bitfield stored in bits 7 and 6 of byte 6,
  1175. // shifted right to get a number in range 0..3.
  1176. Priority = ((*(Frame + 5)) & 0xC0) >> 6;
  1177. // Get Segmentation, a 2-bit bitfield stored in bits 5 and 4 of byte 6.
  1178. // Note that the flag values bits defined for SEGMENTATION_BEGIN and
  1179. // SEGMENTATION_END correspond to these exact bit positions, no further
  1180. // shifting is required.
  1181. Segmentation = ((*(Frame + 5)) & 0x30);
  1182. // Get DataLength. This is a special case requiring handling a length
  1183. // determinant. bLarge (meaning ASN.1 segmentation occurred) will be
  1184. // handled below.
  1185. if (!DecodeLengthDeterminantPER(Frame + 6, BytesLeft - 6, &bLarge,
  1186. &DataLength, &NBytesConsumed))
  1187. return FALSE;
  1188. Size = 6 + NBytesConsumed + DataLength;
  1189. if (BytesLeft < Size)
  1190. return FALSE;
  1191. if (bLarge) {
  1192. // The packet is ASN.1 segmented. This means that there is a second
  1193. // length determinant embedded in the data buffer. The header
  1194. // encoded size contained only a multiple of 16K blocks; we
  1195. // have to get the remainder length determinant and then shift
  1196. // the remaining data onto the determinant to make a contiguous
  1197. // block.
  1198. unsigned Remainder, ExtraBytesConsumed;
  1199. if (!DecodeLengthDeterminantPER(Frame + 6 + NBytesConsumed +
  1200. DataLength, BytesLeft - 6 - NBytesConsumed - DataLength,
  1201. &bLarge, &Remainder, &ExtraBytesConsumed))
  1202. return FALSE;
  1203. ASSERT(!bLarge);
  1204. Size += ExtraBytesConsumed + Remainder;
  1205. if (BytesLeft < Size)
  1206. return FALSE;
  1207. RtlMoveMemory(Frame + 6 + NBytesConsumed + DataLength,
  1208. Frame + 6 + NBytesConsumed + DataLength +
  1209. ExtraBytesConsumed, Remainder);
  1210. DataLength += Remainder;
  1211. // Leave NBytesConsumed alone, it's still the size of the first length
  1212. // determinant.
  1213. }
  1214. // We have received an entire SendData frame.
  1215. *pNBytesConsumed = Size;
  1216. // MCS FUTURE: We do not handle MCS segmentation at all -- do we want to
  1217. //reconstruct here since we're already doing a memcpy()? If so, need to
  1218. //allocate a buffer for this priority and copy.
  1219. if (pDomain->bTopProvider ||
  1220. (!pDomain->bTopProvider && PDUNum != MCS_UNIFORM_SEND_DATA_REQUEST)) {
  1221. #if DBG
  1222. // Verify that Initiator exists. We do not have a list indexed by
  1223. // UserID, so we have to do the search here.
  1224. bFound = FALSE;
  1225. SListResetIteration(&pDomain->UserAttachmentList);
  1226. while (SListIterate(&pDomain->UserAttachmentList, (UINT_PTR *)&hUser,
  1227. &pUA)) {
  1228. if (pUA->UserID == SenderID) {
  1229. bFound = TRUE;
  1230. break;
  1231. }
  1232. }
  1233. if (!bFound && pDomain->bTopProvider) {
  1234. // Not knowing initiator is bad when coming from downlevel,
  1235. // but okay coming from upward connection since this node may
  1236. // not have seen the attach-user request pass by.
  1237. // In this case we will signal an error and ignore the send.
  1238. ErrOut2(pDomain->pContext, "%s: Initiator UserID[%lx] received in a "
  1239. "send-data PDU is not present, ignoring send",
  1240. pDomain->StackClass == Stack_Shadow ? "Shadow stack" :
  1241. (pDomain->StackClass == Stack_Passthru ? "Passthru stack" :
  1242. "Primary stack"), SenderID);
  1243. return TRUE;
  1244. }
  1245. #endif
  1246. // Find channel in channel list.
  1247. if (!SListGetByKey(&pDomain->ChannelList, ChannelID, &pMCSChannel)) {
  1248. // Ignore sends on missing channels. This means that no one
  1249. // has joined the channel. Give a warning only.
  1250. WarnOut1(pDomain->pContext, "ChannelID %d received in a send-data "
  1251. "PDU does not exist", ChannelID);
  1252. //MCS FUTURE: If we are not top provider, send to upward
  1253. // connection.
  1254. return TRUE;
  1255. }
  1256. // Send indication to all local attachments.
  1257. SListResetIteration(&pMCSChannel->UserList);
  1258. while (SListIterate(&pMCSChannel->UserList, &CurUserID, &pUA)) {
  1259. //If SDCallback fails, we need to return FALSE
  1260. if (pUA->bLocal)
  1261. if (!(pUA->SDCallback)(
  1262. (Frame + 6 + NBytesConsumed), // pData
  1263. DataLength,
  1264. pUA->UserDefined, // UserDefined
  1265. pUA, // hUser
  1266. (BOOLEAN)(PDUNum == MCS_UNIFORM_SEND_DATA_REQUEST), // bUniform
  1267. pMCSChannel, // hChannel
  1268. Priority,
  1269. SenderID,
  1270. Segmentation)) {
  1271. return FALSE;
  1272. }
  1273. // WD_Close can jump in to clean the Channel list and user list
  1274. // during the pUA->SDCallback when disconnecting
  1275. // at this time pDomain->bCanSendData will be set to FALSE
  1276. if (!pDomain->bCanSendData) {
  1277. return FALSE;
  1278. }
  1279. }
  1280. // MCS FUTURE: We do not handle indications and requests differently
  1281. // and enforce standard usage.
  1282. // MCS FUTURE: We need to check if there are any other downlevel attachments
  1283. // and forward the data down to them.
  1284. }
  1285. else {
  1286. //MCS FUTURE: Forward (Uniform)SendData PDU to upward connection.
  1287. }
  1288. return TRUE;
  1289. }