485 lines
8.7 KiB
C
485 lines
8.7 KiB
C
|
/*++
|
||
|
|
||
|
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 * 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 *)(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 * 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 *)(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;
|
||
|
}
|
||
|
|