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.
 
 
 
 
 
 

407 lines
11 KiB

/********************************************************************/
/** Microsoft LAN Manager **/
/** Copyright(c) Microsoft Corp., 1990-1993 **/
/********************************************************************/
/* :ts=4 */
//** INIT.C - TCP/UDP init code.
//
// This file contain init code for the TCP/UDP driver. Some things
// here are ifdef'ed for building a UDP only version.
//
#include "precomp.h"
#include "tdint.h"
#include "addr.h"
#include "udp.h"
#include "raw.h"
#include "info.h"
#include "tcp.h"
#include "tcpsend.h"
#include "tcprcv.h"
#include "tcb.h"
#include "tcpconn.h"
#include "pplasl.h"
#include "tcpdeliv.h"
#include "tlcommon.h"
#include "pplasl.h"
extern int InitTCPRcv(void);
extern void UnInitTCPRcv(void);
#include "tcpcfg.h"
#define MAX_CON_RESPONSE_REXMIT_CNT 3 //For UDP we need this!
//* Definitions of global variables.
IPInfo LocalNetInfo;
HANDLE TcpRequestPool;
uint DeadGWDetect;
uint PMTUDiscovery;
uint PMTUBHDetect;
uint KeepAliveTime;
uint KAInterval;
uint DefaultRcvWin;
uint MaxConnections;
uint MaxConnectRexmitCount;
uint MaxConnectResponseRexmitCount = MAX_CON_RESPONSE_REXMIT_CNT;
uint MaxConnectResponseRexmitCountTmp;
uint MaxDataRexmitCount;
uint BSDUrgent;
uint FinWait2TO;
uint NTWMaxConnectCount;
uint NTWMaxConnectTime;
uint MaxUserPort;
uint SecurityFilteringEnabled;
uint GlobalMaxRcvWin = 0xFFFF; //max of 64K
uint TcpHostOpts = TCP_FLAG_SACK | TCP_FLAG_WS | TCP_FLAG_TS;
uint TcpHostSendOpts = 0;
extern HANDLE AddressChangeHandle;
uint StartTime;
extern void *UDPProtInfo;
extern void *RawProtInfo;
extern int InitTCPConn(void);
extern void UnInitTCPConn(void);
extern IP_STATUS TLGetIPInfo(IPInfo * Buffer, int Size);
extern NTSTATUS
UDPPnPPowerRequest(void *ipContext, IPAddr ipAddr, NDIS_HANDLE handle, PNET_PNP_EVENT netPnPEvent);
extern NTSTATUS
RawPnPPowerRequest(void *ipContext, IPAddr ipAddr, NDIS_HANDLE handle, PNET_PNP_EVENT netPnPEvent);
#if MILLEN
extern BOOLEAN InitTcpIprPools(VOID);
extern VOID UnInitTcpIprPools(VOID);
#else
extern HANDLE TcprBufferPool;
extern struct TCPRcvBuf;
#endif // MILLEN
//
// All of the init code can be discarded.
//
#ifdef ALLOC_PRAGMA
int tlinit();
#pragma alloc_text(INIT, tlinit)
#endif
//* Dummy routines for UDP only version. All of these routines return
// 'Invalid Request'.
//* TCPElistChangeHandler - Handles entity list change notification
//
// Called by IP when entity list needs to be reenumerated due to IP
// Addr changes or bindings changes
//
// Input: Nothing
// Returns: Nothing
//
void
TCPElistChangeHandler()
{
TDIEntityID *Entity;
uint i;
CTELockHandle EntityHandle;
uint NewEntityCount;
struct TDIEntityID *NewEntityList;
NewEntityList = CTEAllocMem(sizeof(TDIEntityID) * MAX_TDI_ENTITIES);
if (!NewEntityList)
return;
// our entity list will always be the first.
CTEGetLock(&EntityLock, &EntityHandle);
if (EntityCount == 0) {
NewEntityList[0].tei_entity = CO_TL_ENTITY;
NewEntityList[0].tei_instance = 0;
NewEntityList[1].tei_entity = CL_TL_ENTITY;
NewEntityList[1].tei_instance = 0;
NewEntityCount = 2;
} else {
NewEntityCount = EntityCount;
RtlCopyMemory(NewEntityList, EntityList,
EntityCount * sizeof(*EntityList));
}
CTEFreeLock(&EntityLock, EntityHandle);
// When we have multiple networks under us, we'll want to loop through
// here calling them all. For now just call the one we have.
(*LocalNetInfo.ipi_getelist) (NewEntityList, &NewEntityCount);
// Now walk the entire list, remove the entities that are going away,
// and recompact the entity list. Usually entities dont go away as part of
// the AddressArrival but we take care of this anyways in case there is
// another that is just going away and we have not got a call for
// AddressDeletion yet.
for (i = 0, Entity = NewEntityList; i < NewEntityCount;) {
if (Entity->tei_instance == INVALID_ENTITY_INSTANCE) {
RtlMoveMemory(Entity, Entity + 1,
sizeof(TDIEntityID) * (NewEntityCount - i - 1));
NewEntityCount--;
} else {
Entity++;
i++;
}
}
// Transfer the newly-constructed list over the existing list.
CTEGetLock(&EntityLock, &EntityHandle);
NdisZeroMemory(EntityList, EntityCount * sizeof(*EntityList));
RtlCopyMemory(EntityList, NewEntityList,
NewEntityCount * sizeof(*NewEntityList));
EntityCount = NewEntityCount;
CTEFreeLock(&EntityLock, EntityHandle);
CTEFreeMem(NewEntityList);
}
//* AddressArrival - Handle an IP address arriving
//
// Called by TDI when an address arrives. All we do is query the
// EntityList.
//
// Input: Addr - IP address that's coming.
// Context1 - PNP context1
// Context2 - PNP context2
//
// Returns: Nothing.
//
void
AddressArrival(PTA_ADDRESS Addr, PUNICODE_STRING DeviceName, PTDI_PNP_CONTEXT Context2)
{
if (Addr->AddressType == TDI_ADDRESS_TYPE_IP &&
!IP_ADDR_EQUAL(((PTDI_ADDRESS_IP) Addr->Address)->in_addr,
NULL_IP_ADDR)) {
RevalidateAddrs(((PTDI_ADDRESS_IP) Addr->Address)->in_addr);
}
}
//* AddressDeletion - Handle an IP address going away.
//
// Called by TDI when an address is deleted. If it's an address we
// care about we'll clean up appropriately.
//
// Input: Addr - IP address that's going.
// Context1 - PNP context1
// Context2 - PNP context2
//
// Returns: Nothing.
//
void
AddressDeletion(PTA_ADDRESS Addr, PUNICODE_STRING DeviceName, PTDI_PNP_CONTEXT Context2)
{
PTDI_ADDRESS_IP MyAddress;
IPAddr LocalAddress;
if (Addr->AddressType == TDI_ADDRESS_TYPE_IP) {
// He's deleting an address.
MyAddress = (PTDI_ADDRESS_IP) Addr->Address;
LocalAddress = MyAddress->in_addr;
if (!IP_ADDR_EQUAL(LocalAddress, NULL_IP_ADDR)) {
TCBWalk(DeleteTCBWithSrc, &LocalAddress, NULL, NULL);
InvalidateAddrs(LocalAddress);
}
}
}
#pragma BEGIN_INIT
extern uchar TCPGetConfigInfo(void);
extern uchar IPPresent(void);
//** tlinit - Initialize the transport layer.
//
// The main transport layer initialize routine. We get whatever config
// info we need, initialize some data structures, get information
// from IP, do some more initialization, and finally register our
// protocol values with IP.
//
// Input: Nothing
//
// Returns: True is we succeeded, False if we fail to initialize.
//
int
tlinit()
{
TDI_CLIENT_INTERFACE_INFO tdiInterface;
uint TCBInitialized = 0;
if (!CTEInitialize())
return FALSE;
#if MILLEN
if (!PplInit()) {
return FALSE;
}
#endif // MILLEN
if (!TCPGetConfigInfo())
return FALSE;
StartTime = CTESystemUpTime();
KeepAliveTime = MS_TO_TICKS(KeepAliveTime);
KAInterval = MS_TO_TICKS(KAInterval);
// Get net information from IP.
if (TLGetIPInfo(&LocalNetInfo, sizeof(IPInfo)) != IP_SUCCESS)
goto failure;
if (LocalNetInfo.ipi_version != IP_DRIVER_VERSION)
goto failure; // Wrong version of IP.
// Now query the lower layer entities, and save the information.
CTEInitLock(&EntityLock);
EntityList = CTEAllocMem(sizeof(TDIEntityID) * MAX_TDI_ENTITIES);
if (EntityList == NULL)
goto failure;
EntityList[0].tei_entity = CO_TL_ENTITY;
EntityList[0].tei_instance = 0;
EntityList[1].tei_entity = CL_TL_ENTITY;
EntityList[1].tei_instance = 0;
EntityCount = 2;
RtlZeroMemory(&tdiInterface, sizeof(tdiInterface));
tdiInterface.MajorTdiVersion = TDI_CURRENT_MAJOR_VERSION;
tdiInterface.MinorTdiVersion = TDI_CURRENT_MINOR_VERSION;
tdiInterface.AddAddressHandlerV2 = AddressArrival;
tdiInterface.DelAddressHandlerV2 = AddressDeletion;
(void)TdiRegisterPnPHandlers(
&tdiInterface,
sizeof(tdiInterface),
&AddressChangeHandle
);
//* Initialize addr obj management code.
if (!InitAddr())
goto failure;
if (!InitDG(sizeof(UDPHeader)))
goto failure;
MaxConnections = MIN(MaxConnections, INVALID_CONN_INDEX - 1);
if (!InitTCPConn())
goto failure;
if (!InitTCB())
goto failure;
TCBInitialized = 1;
TcpRequestPool = PplCreatePool(NULL, NULL, 0,
MAX(sizeof(DGSendReq),
MAX(sizeof(TCPConnReq),
MAX(sizeof(TCPSendReq),
MAX(sizeof(TCPRcvReq),
sizeof(TWTCB))))),
'rPCT', 512);
if (!TcpRequestPool)
goto failure;
#if MILLEN
if (!InitTcpIprPools()) {
goto failure;
}
#else
TcprBufferPool =
PplCreatePool(NULL, NULL, 0, sizeof(TCPRcvBuf) + TCP_FIXED_SIZE_IPR_SIZE, 'BPCT', 512);
if (!TcprBufferPool) {
goto failure;
}
#endif // MILLEN
if (!InitTCPRcv())
goto failure;
if (!InitTCPSend())
goto failure;
NdisZeroMemory(&TStats, sizeof(TCPStats));
TStats.ts_rtoalgorithm = TCP_RTO_VANJ;
TStats.ts_rtomin = MIN_RETRAN_TICKS * MS_PER_TICK;
TStats.ts_rtomax = MAX_REXMIT_TO * MS_PER_TICK;
TStats.ts_maxconn = (ulong) TCP_MAXCONN_DYNAMIC;
NdisZeroMemory(&UStats, sizeof(UDPStats));
// Register our UDP protocol handler.
UDPProtInfo = TLRegisterProtocol(PROTOCOL_UDP, UDPRcv, DGSendComplete,
UDPStatus, NULL, UDPPnPPowerRequest, NULL);
if (UDPProtInfo == NULL)
goto failure; // Failed to register!
// Register the Raw IP (wildcard) protocol handler.
RawProtInfo = TLRegisterProtocol(PROTOCOL_ANY, RawRcv, DGSendComplete,
RawStatus, NULL, RawPnPPowerRequest, NULL);
if (RawProtInfo == NULL) {
goto failure; // Failed to register!
}
// When we have multiple networks under us, we'll want to loop through
// here calling them all. For now just call the one we have.
(*LocalNetInfo.ipi_getelist) (EntityList, &EntityCount);
return TRUE;
// Come here to handle all failure cases.
failure:
// If we've registered Raw IP, unregister it now.
if (RawProtInfo != NULL)
TLRegisterProtocol(PROTOCOL_ANY, NULL, NULL, NULL, NULL, NULL, NULL);
// If we've registered UDP, unregister it now.
if (UDPProtInfo != NULL)
TLRegisterProtocol(PROTOCOL_UDP, NULL, NULL, NULL, NULL, NULL, NULL);
#if MILLEN
PplDeinit();
UnInitTcpIprPools();
#endif // MILLEN
PplDestroyPool(TcpRequestPool);
UnInitTCPSend();
UnInitTCPRcv();
if (TCBInitialized) {
UnInitTCB();
}
UnInitTCPConn();
if (TcprBufferPool) {
PplDestroyPool(TcprBufferPool);
}
return FALSE;
}
#pragma END_INIT