summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/isnp/spx/spxutils.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/tdi/isnp/spx/spxutils.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/tdi/isnp/spx/spxutils.c')
-rw-r--r--private/ntos/tdi/isnp/spx/spxutils.c484
1 files changed, 484 insertions, 0 deletions
diff --git a/private/ntos/tdi/isnp/spx/spxutils.c b/private/ntos/tdi/isnp/spx/spxutils.c
new file mode 100644
index 000000000..024a36988
--- /dev/null
+++ b/private/ntos/tdi/isnp/spx/spxutils.c
@@ -0,0 +1,484 @@
+/*++
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ spxutils.c
+
+Abstract:
+
+ This contains all utility routines for the ISN SPX module.
+
+Revision History:
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+// Define module number for event logging entries
+#define FILENUM SPXUTILS
+
+UINT
+SpxUtilWstrLength(
+ IN PWSTR Wstr
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ UINT length = 0;
+
+ while (*Wstr++)
+ {
+ length += sizeof(WCHAR);
+ }
+
+ return length;
+}
+
+
+
+
+LONG
+SpxRandomNumber(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ LARGE_INTEGER Li;
+ static LONG seed = 0;
+
+ // Return a positive pseudo-random number; simple linear congruential
+ // algorithm. ANSI C "rand()" function.
+
+ if (seed == 0)
+ {
+ KeQuerySystemTime(&Li);
+ seed = Li.LowPart;
+ }
+
+ seed *= (0x41C64E6D + 0x3039);
+
+ return (seed & 0x7FFFFFFF);
+}
+
+
+
+
+NTSTATUS
+SpxUtilGetSocketType(
+ PUNICODE_STRING RemainingFileName,
+ PBYTE SocketType
+ )
+/*++
+
+Routine Description:
+
+ For PROTO_SPX, i'd return a device name from the dll of the form
+ \Device\IsnSpx\SpxStream (for SOCK_STREAM) or
+ \Device\IsnSpx\Spx (for SOCK_SEQPKT)
+
+ and for PROTO_SPXII (the more common case we hope, even if
+ internally we degrade to SPX1 cause of the remote client's
+ limitations)
+ \Device\IsnSpx\Stream (for SOCK_STREAM) or
+ \Device\IsnSpx (for SOCK_SEQPKT)
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ UNICODE_STRING typeString;
+
+ *SocketType = SOCKET2_TYPE_SEQPKT;
+
+ // Check for the socket type
+ do
+ {
+ if (RemainingFileName->Length == 0)
+ {
+ break;
+ }
+
+ if ((UINT)RemainingFileName->Length ==
+ SpxUtilWstrLength(SOCKET1STREAM_SUFFIX))
+ {
+ RtlInitUnicodeString(&typeString, SOCKET1STREAM_SUFFIX);
+
+ // Case insensitive compare
+ if (RtlEqualUnicodeString(&typeString, RemainingFileName, TRUE))
+ {
+ *SocketType = SOCKET1_TYPE_STREAM;
+ break;
+ }
+ }
+
+ if ((UINT)RemainingFileName->Length ==
+ SpxUtilWstrLength(SOCKET1_SUFFIX))
+ {
+ RtlInitUnicodeString(&typeString, SOCKET1_SUFFIX);
+
+ // Case insensitive compare
+ if (RtlEqualUnicodeString(&typeString, RemainingFileName, TRUE))
+ {
+ *SocketType = SOCKET1_TYPE_SEQPKT;
+ break;
+ }
+ }
+
+ if ((UINT)RemainingFileName->Length ==
+ SpxUtilWstrLength(SOCKET2STREAM_SUFFIX))
+ {
+ RtlInitUnicodeString(&typeString, SOCKET2STREAM_SUFFIX);
+
+ // Case insensitive compare
+ if (RtlEqualUnicodeString(&typeString, RemainingFileName, TRUE))
+ {
+ *SocketType = SOCKET2_TYPE_STREAM;
+ break;
+ }
+ }
+
+ status = STATUS_NO_SUCH_DEVICE;
+
+ } while (FALSE);
+
+ return(status);
+}
+
+
+
+
+#define ONE_MS_IN_100ns -10000L // 1ms in 100ns units
+
+VOID
+SpxSleep(
+ IN ULONG TimeInMs
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ KTIMER SleepTimer;
+
+ ASSERT (KeGetCurrentIrql() == LOW_LEVEL);
+
+ KeInitializeTimer(&SleepTimer);
+
+ KeSetTimer(&SleepTimer,
+ RtlConvertLongToLargeInteger(TimeInMs * ONE_MS_IN_100ns),
+ NULL);
+
+ KeWaitForSingleObject(&SleepTimer, UserRequest, KernelMode, FALSE, NULL);
+ return;
+}
+
+
+
+
+TDI_ADDRESS_IPX UNALIGNED *
+SpxParseTdiAddress(
+ IN TRANSPORT_ADDRESS UNALIGNED * TransportAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine scans a TRANSPORT_ADDRESS, looking for an address
+ of type TDI_ADDRESS_TYPE_IPX.
+
+Arguments:
+
+ Transport - The generic TDI address.
+
+Return Value:
+
+ A pointer to the IPX address, or NULL if none is found.
+
+--*/
+
+{
+ TA_ADDRESS UNALIGNED * addressName;
+ INT i;
+
+ addressName = &TransportAddress->Address[0];
+
+ // The name can be passed with multiple entries; we'll take and use only
+ // the IPX one.
+ for (i=0;i<TransportAddress->TAAddressCount;i++)
+ {
+ if (addressName->AddressType == TDI_ADDRESS_TYPE_IPX)
+ {
+ if (addressName->AddressLength >= sizeof(TDI_ADDRESS_IPX))
+ {
+ return ((TDI_ADDRESS_IPX UNALIGNED *)(addressName->Address));
+ }
+ }
+ addressName = (TA_ADDRESS UNALIGNED *)(addressName->Address +
+ addressName->AddressLength);
+ }
+ return NULL;
+
+} // SpxParseTdiAddress
+
+
+
+BOOLEAN
+SpxValidateTdiAddress(
+ IN TRANSPORT_ADDRESS UNALIGNED * TransportAddress,
+ IN ULONG TransportAddressLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine scans a TRANSPORT_ADDRESS, verifying that the
+ components of the address do not extend past the specified
+ length.
+
+Arguments:
+
+ TransportAddress - The generic TDI address.
+
+ TransportAddressLength - The specific length of TransportAddress.
+
+Return Value:
+
+ TRUE if the address is valid, FALSE otherwise.
+
+--*/
+
+{
+ PUCHAR AddressEnd = ((PUCHAR)TransportAddress) + TransportAddressLength;
+ TA_ADDRESS UNALIGNED * addressName;
+ INT i;
+
+ if (TransportAddressLength < sizeof(TransportAddress->TAAddressCount))
+ {
+ DBGPRINT(TDI, ERR,
+ ("SpxValidateTdiAddress: runt address\n"));
+
+ return FALSE;
+ }
+
+ addressName = &TransportAddress->Address[0];
+
+ for (i=0;i<TransportAddress->TAAddressCount;i++)
+ {
+ if (addressName->Address > AddressEnd)
+ {
+ DBGPRINT(TDI, ERR,
+ ("SpxValidateTdiAddress: address too short\n"));
+
+ return FALSE;
+ }
+ addressName = (TA_ADDRESS UNALIGNED *)(addressName->Address +
+ addressName->AddressLength);
+ }
+
+ if ((PUCHAR)addressName > AddressEnd)
+ {
+ DBGPRINT(TDI, ERR,
+ ("SpxValidateTdiAddress: address too short\n"));
+
+ return FALSE;
+ }
+ return TRUE;
+
+} // SpxValidateTdiAddress
+
+
+
+
+ULONG
+SpxBuildTdiAddress(
+ IN PVOID AddressBuffer,
+ IN ULONG AddressBufferLength,
+ IN UCHAR Network[4],
+ IN UCHAR Node[6],
+ IN USHORT Socket
+ )
+
+/*++
+
+Routine Description:
+
+ This routine fills in a TRANSPORT_ADDRESS in the specified
+ buffer, given the socket, network and node. It will write
+ less than the full address if the buffer is too short.
+
+Arguments:
+
+ AddressBuffer - The buffer that will hold the address.
+
+ AddressBufferLength - The length of the buffer.
+
+ Network - The network number.
+
+ Node - The node address.
+
+ Socket - The socket.
+
+Return Value:
+
+ The number of bytes written into AddressBuffer.
+
+--*/
+
+{
+ TA_IPX_ADDRESS UNALIGNED * SpxAddress;
+ TA_IPX_ADDRESS TempAddress;
+
+ if (AddressBufferLength >= sizeof(TA_IPX_ADDRESS))
+ {
+ SpxAddress = (TA_IPX_ADDRESS UNALIGNED *)AddressBuffer;
+ }
+ else
+ {
+ SpxAddress = (TA_IPX_ADDRESS UNALIGNED *)&TempAddress;
+ }
+
+ SpxAddress->TAAddressCount = 1;
+ SpxAddress->Address[0].AddressLength = sizeof(TDI_ADDRESS_IPX);
+ SpxAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IPX;
+ SpxAddress->Address[0].Address[0].NetworkAddress = *(UNALIGNED LONG *)Network;
+ SpxAddress->Address[0].Address[0].Socket = Socket;
+ RtlCopyMemory(SpxAddress->Address[0].Address[0].NodeAddress, Node, 6);
+
+ if (AddressBufferLength >= sizeof(TA_IPX_ADDRESS))
+ {
+ return sizeof(TA_IPX_ADDRESS);
+ }
+ else
+ {
+ RtlCopyMemory(AddressBuffer, &TempAddress, AddressBufferLength);
+ return AddressBufferLength;
+ }
+
+} // SpxBuildTdiAddress
+
+
+
+VOID
+SpxBuildTdiAddressFromIpxAddr(
+ IN PVOID AddressBuffer,
+ IN PBYTE pIpxAddr
+ )
+{
+ TA_IPX_ADDRESS UNALIGNED * SpxAddress;
+
+ SpxAddress = (TA_IPX_ADDRESS UNALIGNED *)AddressBuffer;
+ SpxAddress->TAAddressCount = 1;
+ SpxAddress->Address[0].AddressLength = sizeof(TDI_ADDRESS_IPX);
+ SpxAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IPX;
+ SpxAddress->Address[0].Address[0].NetworkAddress = *(UNALIGNED LONG *)pIpxAddr;
+ RtlCopyMemory(
+ SpxAddress->Address[0].Address[0].NodeAddress,
+ pIpxAddr+4,
+ 6);
+
+ GETSHORT2SHORT(
+ &SpxAddress->Address[0].Address[0].Socket,
+ pIpxAddr + 10);
+
+ return;
+}
+
+
+
+VOID
+SpxCalculateNewT1(
+ IN struct _SPX_CONN_FILE * pSpxConnFile,
+ IN int NewT1
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ NewT1 - New value for the RTT in ms.
+
+Return Value:
+
+
+--*/
+{
+ int baseT1, error;
+
+ //
+ // VAN JACOBSEN Algorithm. From Internetworking with Tcp/ip
+ // (Comer) book.
+ //
+
+ error = NewT1 - (pSpxConnFile->scf_AveT1 >> 3);
+ pSpxConnFile->scf_AveT1 += error;
+ if (pSpxConnFile->scf_AveT1 <= 0) // Make sure not too small
+ {
+ pSpxConnFile->scf_AveT1 = SPX_T1_MIN;
+ }
+
+ if (error < 0)
+ error = -error;
+
+ error -= (pSpxConnFile->scf_DevT1 >> 2);
+ pSpxConnFile->scf_DevT1 += error;
+ if (pSpxConnFile->scf_DevT1 <= 0)
+ pSpxConnFile->scf_DevT1 = 1;
+
+ baseT1 = (((pSpxConnFile->scf_AveT1 >> 2) + pSpxConnFile->scf_DevT1) >> 1);
+
+ // If less then min - set it
+ if (baseT1 < SPX_T1_MIN)
+ baseT1 = SPX_T1_MIN;
+
+ // Set the new value
+ DBGPRINT(TDI, DBG,
+ ("SpxCalculateNewT1: Old value %lx New %lx\n",
+ pSpxConnFile->scf_BaseT1, baseT1));
+
+ pSpxConnFile->scf_BaseT1 = baseT1;
+
+ // At the time of restarting the timer,we convert this to a tick value.
+ return;
+}
+