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.

484 lines
8.7 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. spxutils.c
  5. Abstract:
  6. This contains all utility routines for the ISN SPX module.
  7. Revision History:
  8. --*/
  9. #include "precomp.h"
  10. #pragma hdrstop
  11. // Define module number for event logging entries
  12. #define FILENUM SPXUTILS
  13. UINT
  14. SpxUtilWstrLength(
  15. IN PWSTR Wstr
  16. )
  17. /*++
  18. Routine Description:
  19. Arguments:
  20. Return Value:
  21. --*/
  22. {
  23. UINT length = 0;
  24. while (*Wstr++)
  25. {
  26. length += sizeof(WCHAR);
  27. }
  28. return length;
  29. }
  30. LONG
  31. SpxRandomNumber(
  32. VOID
  33. )
  34. /*++
  35. Routine Description:
  36. Arguments:
  37. Return Value:
  38. --*/
  39. {
  40. LARGE_INTEGER Li;
  41. static LONG seed = 0;
  42. // Return a positive pseudo-random number; simple linear congruential
  43. // algorithm. ANSI C "rand()" function.
  44. if (seed == 0)
  45. {
  46. KeQuerySystemTime(&Li);
  47. seed = Li.LowPart;
  48. }
  49. seed *= (0x41C64E6D + 0x3039);
  50. return (seed & 0x7FFFFFFF);
  51. }
  52. NTSTATUS
  53. SpxUtilGetSocketType(
  54. PUNICODE_STRING RemainingFileName,
  55. PBYTE SocketType
  56. )
  57. /*++
  58. Routine Description:
  59. For PROTO_SPX, i'd return a device name from the dll of the form
  60. \Device\IsnSpx\SpxStream (for SOCK_STREAM) or
  61. \Device\IsnSpx\Spx (for SOCK_SEQPKT)
  62. and for PROTO_SPXII (the more common case we hope, even if
  63. internally we degrade to SPX1 cause of the remote client's
  64. limitations)
  65. \Device\IsnSpx\Stream (for SOCK_STREAM) or
  66. \Device\IsnSpx (for SOCK_SEQPKT)
  67. Arguments:
  68. Return Value:
  69. --*/
  70. {
  71. NTSTATUS status = STATUS_SUCCESS;
  72. UNICODE_STRING typeString;
  73. *SocketType = SOCKET2_TYPE_SEQPKT;
  74. // Check for the socket type
  75. do
  76. {
  77. if (RemainingFileName->Length == 0)
  78. {
  79. break;
  80. }
  81. if ((UINT)RemainingFileName->Length ==
  82. SpxUtilWstrLength(SOCKET1STREAM_SUFFIX))
  83. {
  84. RtlInitUnicodeString(&typeString, SOCKET1STREAM_SUFFIX);
  85. // Case insensitive compare
  86. if (RtlEqualUnicodeString(&typeString, RemainingFileName, TRUE))
  87. {
  88. *SocketType = SOCKET1_TYPE_STREAM;
  89. break;
  90. }
  91. }
  92. if ((UINT)RemainingFileName->Length ==
  93. SpxUtilWstrLength(SOCKET1_SUFFIX))
  94. {
  95. RtlInitUnicodeString(&typeString, SOCKET1_SUFFIX);
  96. // Case insensitive compare
  97. if (RtlEqualUnicodeString(&typeString, RemainingFileName, TRUE))
  98. {
  99. *SocketType = SOCKET1_TYPE_SEQPKT;
  100. break;
  101. }
  102. }
  103. if ((UINT)RemainingFileName->Length ==
  104. SpxUtilWstrLength(SOCKET2STREAM_SUFFIX))
  105. {
  106. RtlInitUnicodeString(&typeString, SOCKET2STREAM_SUFFIX);
  107. // Case insensitive compare
  108. if (RtlEqualUnicodeString(&typeString, RemainingFileName, TRUE))
  109. {
  110. *SocketType = SOCKET2_TYPE_STREAM;
  111. break;
  112. }
  113. }
  114. status = STATUS_NO_SUCH_DEVICE;
  115. } while (FALSE);
  116. return(status);
  117. }
  118. #define ONE_MS_IN_100ns -10000L // 1ms in 100ns units
  119. VOID
  120. SpxSleep(
  121. IN ULONG TimeInMs
  122. )
  123. /*++
  124. Routine Description:
  125. Arguments:
  126. Return Value:
  127. --*/
  128. {
  129. KTIMER SleepTimer;
  130. ASSERT (KeGetCurrentIrql() == LOW_LEVEL);
  131. KeInitializeTimer(&SleepTimer);
  132. KeSetTimer(&SleepTimer,
  133. RtlConvertLongToLargeInteger(TimeInMs * ONE_MS_IN_100ns),
  134. NULL);
  135. KeWaitForSingleObject(&SleepTimer, UserRequest, KernelMode, FALSE, NULL);
  136. return;
  137. }
  138. TDI_ADDRESS_IPX UNALIGNED *
  139. SpxParseTdiAddress(
  140. IN TRANSPORT_ADDRESS UNALIGNED * TransportAddress
  141. )
  142. /*++
  143. Routine Description:
  144. This routine scans a TRANSPORT_ADDRESS, looking for an address
  145. of type TDI_ADDRESS_TYPE_IPX.
  146. Arguments:
  147. Transport - The generic TDI address.
  148. Return Value:
  149. A pointer to the IPX address, or NULL if none is found.
  150. --*/
  151. {
  152. TA_ADDRESS * addressName;
  153. INT i;
  154. addressName = &TransportAddress->Address[0];
  155. // The name can be passed with multiple entries; we'll take and use only
  156. // the IPX one.
  157. for (i=0;i<TransportAddress->TAAddressCount;i++)
  158. {
  159. if (addressName->AddressType == TDI_ADDRESS_TYPE_IPX)
  160. {
  161. if (addressName->AddressLength >= sizeof(TDI_ADDRESS_IPX))
  162. {
  163. return ((TDI_ADDRESS_IPX UNALIGNED *)(addressName->Address));
  164. }
  165. }
  166. addressName = (TA_ADDRESS *)(addressName->Address +
  167. addressName->AddressLength);
  168. }
  169. return NULL;
  170. } // SpxParseTdiAddress
  171. BOOLEAN
  172. SpxValidateTdiAddress(
  173. IN TRANSPORT_ADDRESS UNALIGNED * TransportAddress,
  174. IN ULONG TransportAddressLength
  175. )
  176. /*++
  177. Routine Description:
  178. This routine scans a TRANSPORT_ADDRESS, verifying that the
  179. components of the address do not extend past the specified
  180. length.
  181. Arguments:
  182. TransportAddress - The generic TDI address.
  183. TransportAddressLength - The specific length of TransportAddress.
  184. Return Value:
  185. TRUE if the address is valid, FALSE otherwise.
  186. --*/
  187. {
  188. PUCHAR AddressEnd = ((PUCHAR)TransportAddress) + TransportAddressLength;
  189. TA_ADDRESS * addressName;
  190. INT i;
  191. if (TransportAddressLength < sizeof(TransportAddress->TAAddressCount))
  192. {
  193. DBGPRINT(TDI, ERR,
  194. ("SpxValidateTdiAddress: runt address\n"));
  195. return FALSE;
  196. }
  197. addressName = &TransportAddress->Address[0];
  198. for (i=0;i<TransportAddress->TAAddressCount;i++)
  199. {
  200. if (addressName->Address > AddressEnd)
  201. {
  202. DBGPRINT(TDI, ERR,
  203. ("SpxValidateTdiAddress: address too short\n"));
  204. return FALSE;
  205. }
  206. addressName = (TA_ADDRESS *)(addressName->Address +
  207. addressName->AddressLength);
  208. }
  209. if ((PUCHAR)addressName > AddressEnd)
  210. {
  211. DBGPRINT(TDI, ERR,
  212. ("SpxValidateTdiAddress: address too short\n"));
  213. return FALSE;
  214. }
  215. return TRUE;
  216. } // SpxValidateTdiAddress
  217. ULONG
  218. SpxBuildTdiAddress(
  219. IN PVOID AddressBuffer,
  220. IN ULONG AddressBufferLength,
  221. IN UCHAR Network[4],
  222. IN UCHAR Node[6],
  223. IN USHORT Socket
  224. )
  225. /*++
  226. Routine Description:
  227. This routine fills in a TRANSPORT_ADDRESS in the specified
  228. buffer, given the socket, network and node. It will write
  229. less than the full address if the buffer is too short.
  230. Arguments:
  231. AddressBuffer - The buffer that will hold the address.
  232. AddressBufferLength - The length of the buffer.
  233. Network - The network number.
  234. Node - The node address.
  235. Socket - The socket.
  236. Return Value:
  237. The number of bytes written into AddressBuffer.
  238. --*/
  239. {
  240. TA_IPX_ADDRESS UNALIGNED * SpxAddress;
  241. TA_IPX_ADDRESS TempAddress;
  242. if (AddressBufferLength >= sizeof(TA_IPX_ADDRESS))
  243. {
  244. SpxAddress = (TA_IPX_ADDRESS UNALIGNED *)AddressBuffer;
  245. }
  246. else
  247. {
  248. SpxAddress = (TA_IPX_ADDRESS UNALIGNED *)&TempAddress;
  249. }
  250. SpxAddress->TAAddressCount = 1;
  251. SpxAddress->Address[0].AddressLength = sizeof(TDI_ADDRESS_IPX);
  252. SpxAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IPX;
  253. SpxAddress->Address[0].Address[0].NetworkAddress = *(UNALIGNED LONG *)Network;
  254. SpxAddress->Address[0].Address[0].Socket = Socket;
  255. RtlCopyMemory(SpxAddress->Address[0].Address[0].NodeAddress, Node, 6);
  256. if (AddressBufferLength >= sizeof(TA_IPX_ADDRESS))
  257. {
  258. return sizeof(TA_IPX_ADDRESS);
  259. }
  260. else
  261. {
  262. RtlCopyMemory(AddressBuffer, &TempAddress, AddressBufferLength);
  263. return AddressBufferLength;
  264. }
  265. } // SpxBuildTdiAddress
  266. VOID
  267. SpxBuildTdiAddressFromIpxAddr(
  268. IN PVOID AddressBuffer,
  269. IN PBYTE pIpxAddr
  270. )
  271. {
  272. TA_IPX_ADDRESS UNALIGNED * SpxAddress;
  273. SpxAddress = (TA_IPX_ADDRESS UNALIGNED *)AddressBuffer;
  274. SpxAddress->TAAddressCount = 1;
  275. SpxAddress->Address[0].AddressLength = sizeof(TDI_ADDRESS_IPX);
  276. SpxAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IPX;
  277. SpxAddress->Address[0].Address[0].NetworkAddress = *(UNALIGNED LONG *)pIpxAddr;
  278. RtlCopyMemory(
  279. SpxAddress->Address[0].Address[0].NodeAddress,
  280. pIpxAddr+4,
  281. 6);
  282. GETSHORT2SHORT(
  283. &SpxAddress->Address[0].Address[0].Socket,
  284. pIpxAddr + 10);
  285. return;
  286. }
  287. VOID
  288. SpxCalculateNewT1(
  289. IN struct _SPX_CONN_FILE * pSpxConnFile,
  290. IN int NewT1
  291. )
  292. /*++
  293. Routine Description:
  294. Arguments:
  295. NewT1 - New value for the RTT in ms.
  296. Return Value:
  297. --*/
  298. {
  299. int baseT1, error;
  300. //
  301. // VAN JACOBSEN Algorithm. From Internetworking with Tcp/ip
  302. // (Comer) book.
  303. //
  304. error = NewT1 - (pSpxConnFile->scf_AveT1 >> 3);
  305. pSpxConnFile->scf_AveT1 += error;
  306. if (pSpxConnFile->scf_AveT1 <= 0) // Make sure not too small
  307. {
  308. pSpxConnFile->scf_AveT1 = SPX_T1_MIN;
  309. }
  310. if (error < 0)
  311. error = -error;
  312. error -= (pSpxConnFile->scf_DevT1 >> 2);
  313. pSpxConnFile->scf_DevT1 += error;
  314. if (pSpxConnFile->scf_DevT1 <= 0)
  315. pSpxConnFile->scf_DevT1 = 1;
  316. baseT1 = (((pSpxConnFile->scf_AveT1 >> 2) + pSpxConnFile->scf_DevT1) >> 1);
  317. // If less then min - set it
  318. if (baseT1 < SPX_T1_MIN)
  319. baseT1 = SPX_T1_MIN;
  320. // Set the new value
  321. DBGPRINT(TDI, DBG,
  322. ("SpxCalculateNewT1: Old value %lx New %lx\n",
  323. pSpxConnFile->scf_BaseT1, baseT1));
  324. pSpxConnFile->scf_BaseT1 = baseT1;
  325. // At the time of restarting the timer,we convert this to a tick value.
  326. return;
  327. }