/********************************************************************/ /** 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