/********************************************************************/ /** 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 "oscfg.h" #include "ndis.h" #include "cxport.h" #include "ip.h" #include "tdi.h" #ifdef NT #include #endif #ifdef VXD #include "tdivxd.h" #include "tdistat.h" #endif #ifdef NT #include "tdint.h" #include "tdistat.h" #endif #include "queue.h" #include "addr.h" #include "udp.h" #include "raw.h" #include "info.h" #ifndef UDP_ONLY #include "tcp.h" #include "tcpsend.h" #include "tcb.h" #include "tcpconn.h" #include "tcpdeliv.h" #include "tlcommon.h" extern int InitTCPRcv(void); extern void UnInitTCPRcv(void); #endif // UDP_ONLY #include "tdiinfo.h" #include "tcpcfg.h" //* Definitions of global variables. IPInfo LocalNetInfo; uint DeadGWDetect; uint PMTUDiscovery; uint PMTUBHDetect; uint KeepAliveTime; uint KAInterval; uint DefaultRcvWin; uint MaxConnections; uint MaxConnectRexmitCount; uint MaxConnectResponseRexmitCount; #ifdef SYN_ATTACK uint MaxConnectResponseRexmitCountTmp; #endif uint MaxDataRexmitCount; uint BSDUrgent; uint FinWait2TO; uint NTWMaxConnectCount; uint NTWMaxConnectTime; uint MaxUserPort; #ifdef SECFLTR uint SecurityFilteringEnabled; #endif // SECFLTR #ifdef VXD uint PreloadCount; #endif #ifdef _PNP_POWER HANDLE AddressChangeHandle; #endif #ifdef VXD TDIDispatchTable TLDispatch; #ifndef CHICAGO char TransportName[] = "MSTCP"; #else char TransportName[] = TCP_NAME; #endif #ifdef CHICAGO extern int RegisterAddrChangeHndlr(void *Handler, uint Add); #endif #endif uint StartTime; extern void *UDPProtInfo; extern void *RawProtInfo; extern int InitTCPConn(void); extern void UnInitTCPConn(void); extern IP_STATUS TLGetIPInfo(IPInfo *Buffer, int Size); // // All of the init code can be discarded. // #ifdef NT #ifdef ALLOC_PRAGMA int tlinit(); #pragma alloc_text(INIT, tlinit) #endif // ALLOC_PRAGMA #endif //* Dummy routines for UDP only version. All of these routines return // 'Invalid Request'. #ifdef UDP_ONLY TDI_STATUS TdiOpenConnection(PTDI_REQUEST Request, PVOID Context) { return TDI_INVALID_REQUEST; } TDI_STATUS TdiCloseConnection(PTDI_REQUEST Request) { return TDI_INVALID_REQUEST; } TDI_STATUS TdiAssociateAddress(PTDI_REQUEST Request, HANDLE AddrHandle) { return TDI_INVALID_REQUEST; } TDI_STATUS TdiDisAssociateAddress(PTDI_REQUEST Request) { return TDI_INVALID_REQUEST; } TDI_STATUS TdiConnect(PTDI_REQUEST Request, void *Timeout, PTDI_CONNECTION_INFORMATION RequestAddr, PTDI_CONNECTION_INFORMATION ReturnAddr) { return TDI_INVALID_REQUEST; } TDI_STATUS TdiListen(PTDI_REQUEST Request, ushort Flags, PTDI_CONNECTION_INFORMATION AcceptableAddr, PTDI_CONNECTION_INFORMATION ConnectedAddr) { return TDI_INVALID_REQUEST; } TDI_STATUS TdiAccept(PTDI_REQUEST Request, PTDI_CONNECTION_INFORMATION AcceptInfo, PTDI_CONNECTION_INFORMATION ConnectedInfo) { return TDI_INVALID_REQUEST; } TDI_STATUS TdiReceive(PTDI_REQUEST Request, ushort *Flags, uint *RcvLength, PNDIS_BUFFER Buffer) { return TDI_INVALID_REQUEST; } TDI_STATUS TdiSend(PTDI_REQUEST Request, ushort Flags, uint SendLength, PNDIS_BUFFER Buffer) { return TDI_INVALID_REQUEST; } TDI_STATUS TdiDisconnect(PTDI_REQUEST Request, PVOID Timeout, ushort Flags, PTDI_CONNECTION_INFORMATION DisconnectInfo, PTDI_CONNECTION_INFORMATION ReturnInfo) { return TDI_INVALID_REQUEST; } #endif #ifdef VXD extern void *ConvertPtr(void *Ptr); //** Routines to handle incoming QueryInformation requests, and dispatch //** them. struct ClientReq { ushort cr_opcode; void *cr_ID; void *cr_buffer; void *cr_length; void *cr_context; }; //* VxDQueryInfo - VxD thunk to query information. // // The VxD thunk to TdiQueryInformationEx. All we do it convert the pointers // and call in. // // Input: Req - A pointer to a ClientReq structure. // // Returns: Status of command. // TDI_STATUS VxDQueryInfo(struct ClientReq *Req) { NDIS_BUFFER Buffer; TDI_REQUEST Request; uint *Size; TDIObjectID *ID; void *Context; CTEAssert(Req->cr_opcode == 0); CTEMemSet(&Request, 0, sizeof(TDI_REQUEST)); ID = (TDIObjectID *)ConvertPtr(Req->cr_ID); Size = (uint *)ConvertPtr(Req->cr_length); #ifdef DEBUG Buffer.Signature = BUFFER_SIGN; #endif Buffer.VirtualAddress = ConvertPtr(Req->cr_buffer); Buffer.Length = *Size; Buffer.Next = NULL; return TdiQueryInformationEx(&Request, ID, &Buffer, Size, ConvertPtr(Req->cr_context)); } //* VxDSetInfo - VxD thunk to set information. // // The VxD thunk to TdiSetInformationEx. All we do it convert the pointers // and call in. // // Input: Req - A pointer to a ClientReq structure. // // Returns: Status of command. // TDI_STATUS VxDSetInfo(struct ClientReq *Req) { TDIObjectID *ID; uint *Size; void *Buffer; TDI_REQUEST Request; CTEAssert(Req->cr_opcode == 1); CTEMemSet(&Request, 0, sizeof(TDI_REQUEST)); ID = (TDIObjectID *)ConvertPtr(Req->cr_ID); Size = (uint *)ConvertPtr(Req->cr_length); Buffer = ConvertPtr(Req->cr_buffer); return TdiSetInformationEx(&Request, ID, Buffer, *Size); } #endif #ifdef CHICAGO //* AddrChange - Receive notification of an IP address change. // // Called by IP when an address comes or goes. We get the address // and mask, and depending on what's actually happened we may close address // and connections. // // Input: Addr - IP address that's coming or going. // Mask - Mask for Addr. // Context - PNP context (unused) // IPContext - IP context (unused) // Added - True if the address is coming, False if it's going. // // Returns: Nothing. // void AddrChange(IPAddr Addr, IPMask Mask, void *Context, ushort IPContext, uint Added) { if (Added) { // He's adding an address. Re-query the entity list now. 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; // 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); } else { // He's deleting an address. if (!IP_ADDR_EQUAL(Addr, NULL_IP_ADDR)) { #ifndef UDP_ONLY TCBWalk(DeleteTCBWithSrc, &Addr, NULL, NULL); #endif InvalidateAddrs(Addr); } } } #endif #ifdef NT #ifdef _PNP_POWER //* 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. // // Returns: Nothing. // void AddressArrival(PTA_ADDRESS Addr) { if (Addr->AddressType == TDI_ADDRESS_TYPE_IP) { // He's adding an address. Re-query the entity list now. 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; // 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); } } //* 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. // // Returns: Nothing. // void AddressDeletion(PTA_ADDRESS Addr) { 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)) { #ifndef UDP_ONLY TCBWalk(DeleteTCBWithSrc, &LocalAddress, NULL, NULL); #endif InvalidateAddrs(LocalAddress); } } } #endif // _PNP_POWER #endif // NT #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() { #ifdef VXD void *PreloadPtrs[MAX_PRELOAD_COUNT]; uint i; #endif uint TCBInitialized = 0; if (!CTEInitialize()) return FALSE; #ifdef VXD if (!IPPresent()) return FALSE; #endif if (!TCPGetConfigInfo()) return FALSE; StartTime = CTESystemUpTime(); #ifndef UDP_ONLY KeepAliveTime = MS_TO_TICKS(KeepAliveTime); KAInterval = MS_TO_TICKS(KAInterval); #endif CTERefillMem(); // 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. #ifdef CHICAGO if (!RegisterAddrChangeHndlr(AddrChange, TRUE)) goto failure; #endif #ifdef NT #ifdef _PNP_POWER (void)TdiRegisterAddressChangeHandler( AddressArrival, AddressDeletion, &AddressChangeHandle ); #endif // _PNP_POWER #endif // NT //* Initialize addr obj management code. if (!InitAddr()) goto failure; CTERefillMem(); if (!InitDG(sizeof(UDPHeader))) goto failure; #ifndef UDP_ONLY MaxConnections = MIN(MaxConnections, INVALID_CONN_INDEX - 1); CTERefillMem(); if (!InitTCPConn()) goto failure; CTERefillMem(); if (!InitTCB()) goto failure; TCBInitialized = 1; CTERefillMem(); if (!InitTCPRcv()) goto failure; CTERefillMem(); if (!InitTCPSend()) goto failure; CTEMemSet(&TStats, 0, 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; #endif CTEMemSet(&UStats,0, sizeof(UDPStats)); // Register our UDP protocol handler. UDPProtInfo = TLRegisterProtocol(PROTOCOL_UDP, UDPRcv, DGSendComplete, UDPStatus, NULL); if (UDPProtInfo == NULL) goto failure; // Failed to register! // Register the Raw IP (wildcard) protocol handler. RawProtInfo = TLRegisterProtocol(PROTOCOL_ANY, RawRcv, DGSendComplete, RawStatus, NULL); if (RawProtInfo == NULL) { CTEPrint(("failed to register raw prot with IP\n")); goto failure; // Failed to register! } #ifdef VXD TLDispatch.TdiOpenAddressEntry = TdiOpenAddress; TLDispatch.TdiCloseAddressEntry = TdiCloseAddress; TLDispatch.TdiSendDatagramEntry = TdiSendDatagram; TLDispatch.TdiReceiveDatagramEntry = TdiReceiveDatagram; TLDispatch.TdiSetEventEntry = TdiSetEvent; TLDispatch.TdiOpenConnectionEntry = TdiOpenConnection; TLDispatch.TdiCloseConnectionEntry = TdiCloseConnection; TLDispatch.TdiAssociateAddressEntry = TdiAssociateAddress; TLDispatch.TdiDisAssociateAddressEntry = TdiDisAssociateAddress; TLDispatch.TdiConnectEntry = TdiConnect; TLDispatch.TdiDisconnectEntry = TdiDisconnect; TLDispatch.TdiListenEntry = TdiListen; TLDispatch.TdiAcceptEntry = TdiAccept; TLDispatch.TdiReceiveEntry = TdiReceive; TLDispatch.TdiSendEntry = TdiSend; TLDispatch.TdiQueryInformationEntry = TdiQueryInformation; TLDispatch.TdiSetInformationEntry = TdiSetInformation; TLDispatch.TdiActionEntry = TdiAction; TLDispatch.TdiQueryInformationExEntry = TdiQueryInformationEx; TLDispatch.TdiSetInformationExEntry = TdiSetInformationEx; if (!TLRegisterDispatch(TransportName, &TLDispatch)) goto failure; #endif CTERefillMem(); // Now query the lower layer entities, and save the information. 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; // 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); CTERefillMem(); #ifdef VXD // Allocate memory as needed to satisfy the heap preload requirements. We'll // allocate a bunch of memory from the IFSMgr and then free it, so // hopefully it'll be there later when we need it. PreloadCount = MIN(PreloadCount, MAX_PRELOAD_COUNT); for (i = 0; i < PreloadCount; i++) { void *Temp; Temp = CTEAllocMem(PRELOAD_BLOCK_SIZE); if (Temp != NULL) PreloadPtrs[i] = Temp; else break; CTERefillMem(); } PreloadCount = i; for (i = 0; i < PreloadCount; i++) { CTEFreeMem(PreloadPtrs[i]); } #endif 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); // If we've registered UDP, unregister it now. if (UDPProtInfo != NULL) TLRegisterProtocol(PROTOCOL_UDP, NULL, NULL, NULL, NULL); #ifndef UDP_ONLY UnInitTCPSend(); UnInitTCPRcv(); if (TCBInitialized) { UnInitTCB(); } UnInitTCPConn(); #endif CTERefillMem(); return FALSE; } #pragma END_INIT