Source code of Windows XP (NT5)
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.

396 lines
11 KiB

  1. /********************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1990-1993 **/
  4. /********************************************************************/
  5. /* :ts=4 */
  6. //** INIT.C - TCP/UDP init code.
  7. //
  8. // This file contain init code for the TCP/UDP driver. Some things
  9. // here are ifdef'ed for building a UDP only version.
  10. //
  11. #include "precomp.h"
  12. #include "tdint.h"
  13. #include "addr.h"
  14. #include "udp.h"
  15. #include "raw.h"
  16. #include "info.h"
  17. #include "tcp.h"
  18. #include "tcpsend.h"
  19. #include "tcprcv.h"
  20. #include "tcb.h"
  21. #include "tcpconn.h"
  22. #include "tcpdeliv.h"
  23. #include "tlcommon.h"
  24. #include "pplasl.h"
  25. extern int InitTCPRcv(void);
  26. extern void UnInitTCPRcv(void);
  27. #include "tcpcfg.h"
  28. #define MAX_CON_RESPONSE_REXMIT_CNT 3 //For UDP we need this!
  29. //* Definitions of global variables.
  30. IPInfo LocalNetInfo;
  31. HANDLE TcpRequestPool;
  32. uint DeadGWDetect;
  33. uint PMTUDiscovery;
  34. uint PMTUBHDetect;
  35. uint KeepAliveTime;
  36. uint KAInterval;
  37. uint DefaultRcvWin;
  38. uint MaxConnections;
  39. uint MaxConnectRexmitCount;
  40. uint MaxConnectResponseRexmitCount = MAX_CON_RESPONSE_REXMIT_CNT;
  41. uint MaxConnectResponseRexmitCountTmp;
  42. uint MaxDataRexmitCount;
  43. uint BSDUrgent;
  44. uint FinWait2TO;
  45. uint NTWMaxConnectCount;
  46. uint NTWMaxConnectTime;
  47. uint MaxUserPort;
  48. uint SecurityFilteringEnabled;
  49. uint GlobalMaxRcvWin = 0xFFFF; //max of 64K
  50. uint TcpHostOpts = TCP_FLAG_SACK | TCP_FLAG_WS | TCP_FLAG_TS;
  51. uint TcpHostSendOpts = 0;
  52. extern HANDLE AddressChangeHandle;
  53. uint StartTime;
  54. extern void *UDPProtInfo;
  55. extern void *RawProtInfo;
  56. extern int InitTCPConn(void);
  57. extern void UnInitTCPConn(void);
  58. extern IP_STATUS TLGetIPInfo(IPInfo * Buffer, int Size);
  59. extern NTSTATUS
  60. UDPPnPPowerRequest(void *ipContext, IPAddr ipAddr, NDIS_HANDLE handle, PNET_PNP_EVENT netPnPEvent);
  61. extern NTSTATUS
  62. RawPnPPowerRequest(void *ipContext, IPAddr ipAddr, NDIS_HANDLE handle, PNET_PNP_EVENT netPnPEvent);
  63. #if MILLEN
  64. extern BOOLEAN InitTcpIprPools(VOID);
  65. extern VOID UnInitTcpIprPools(VOID);
  66. #endif // MILLEN
  67. //
  68. // All of the init code can be discarded.
  69. //
  70. #ifdef ALLOC_PRAGMA
  71. int tlinit();
  72. #pragma alloc_text(INIT, tlinit)
  73. #endif
  74. //* Dummy routines for UDP only version. All of these routines return
  75. // 'Invalid Request'.
  76. //* TCPElistChangeHandler - Handles entity list change notification
  77. //
  78. // Called by IP when entity list needs to be reenumerated due to IP
  79. // Addr changes or bindings changes
  80. //
  81. // Input: Nothing
  82. // Returns: Nothing
  83. //
  84. void
  85. TCPElistChangeHandler()
  86. {
  87. TDIEntityID *Entity;
  88. uint i;
  89. CTELockHandle EntityHandle;
  90. uint NewEntityCount;
  91. struct TDIEntityID *NewEntityList;
  92. NewEntityList = CTEAllocMem(sizeof(TDIEntityID) * MAX_TDI_ENTITIES);
  93. if (!NewEntityList)
  94. return;
  95. // our entity list will always be the first.
  96. CTEGetLock(&EntityLock, &EntityHandle);
  97. if (EntityCount == 0) {
  98. NewEntityList[0].tei_entity = CO_TL_ENTITY;
  99. NewEntityList[0].tei_instance = 0;
  100. NewEntityList[1].tei_entity = CL_TL_ENTITY;
  101. NewEntityList[1].tei_instance = 0;
  102. NewEntityCount = 2;
  103. } else {
  104. NewEntityCount = EntityCount;
  105. RtlCopyMemory(NewEntityList, EntityList,
  106. EntityCount * sizeof(*EntityList));
  107. }
  108. CTEFreeLock(&EntityLock, EntityHandle);
  109. // When we have multiple networks under us, we'll want to loop through
  110. // here calling them all. For now just call the one we have.
  111. (*LocalNetInfo.ipi_getelist) (NewEntityList, &NewEntityCount);
  112. // Now walk the entire list, remove the entities that are going away,
  113. // and recompact the entity list. Usually entities dont go away as part of
  114. // the AddressArrival but we take care of this anyways in case there is
  115. // another that is just going away and we have not got a call for
  116. // AddressDeletion yet.
  117. for (i = 0, Entity = NewEntityList; i < NewEntityCount;) {
  118. if (Entity->tei_instance == INVALID_ENTITY_INSTANCE) {
  119. RtlMoveMemory(Entity, Entity + 1,
  120. sizeof(TDIEntityID) * (NewEntityCount - i - 1));
  121. NewEntityCount--;
  122. } else {
  123. Entity++;
  124. i++;
  125. }
  126. }
  127. // Transfer the newly-constructed list over the existing list.
  128. CTEGetLock(&EntityLock, &EntityHandle);
  129. NdisZeroMemory(EntityList, EntityCount * sizeof(*EntityList));
  130. RtlCopyMemory(EntityList, NewEntityList,
  131. NewEntityCount * sizeof(*NewEntityList));
  132. EntityCount = NewEntityCount;
  133. CTEFreeLock(&EntityLock, EntityHandle);
  134. CTEFreeMem(NewEntityList);
  135. }
  136. //* AddressArrival - Handle an IP address arriving
  137. //
  138. // Called by TDI when an address arrives. All we do is query the
  139. // EntityList.
  140. //
  141. // Input: Addr - IP address that's coming.
  142. // Context1 - PNP context1
  143. // Context2 - PNP context2
  144. //
  145. // Returns: Nothing.
  146. //
  147. void
  148. AddressArrival(PTA_ADDRESS Addr, PUNICODE_STRING DeviceName, PTDI_PNP_CONTEXT Context2)
  149. {
  150. if (Addr->AddressType == TDI_ADDRESS_TYPE_IP &&
  151. !IP_ADDR_EQUAL(((PTDI_ADDRESS_IP) Addr->Address)->in_addr,
  152. NULL_IP_ADDR)) {
  153. RevalidateAddrs(((PTDI_ADDRESS_IP) Addr->Address)->in_addr);
  154. }
  155. }
  156. //* AddressDeletion - Handle an IP address going away.
  157. //
  158. // Called by TDI when an address is deleted. If it's an address we
  159. // care about we'll clean up appropriately.
  160. //
  161. // Input: Addr - IP address that's going.
  162. // Context1 - PNP context1
  163. // Context2 - PNP context2
  164. //
  165. // Returns: Nothing.
  166. //
  167. void
  168. AddressDeletion(PTA_ADDRESS Addr, PUNICODE_STRING DeviceName, PTDI_PNP_CONTEXT Context2)
  169. {
  170. PTDI_ADDRESS_IP MyAddress;
  171. IPAddr LocalAddress;
  172. TDIEntityID *Entity;
  173. uint i, j;
  174. if (Addr->AddressType == TDI_ADDRESS_TYPE_IP) {
  175. // He's deleting an address.
  176. MyAddress = (PTDI_ADDRESS_IP) Addr->Address;
  177. LocalAddress = MyAddress->in_addr;
  178. if (!IP_ADDR_EQUAL(LocalAddress, NULL_IP_ADDR)) {
  179. TCBWalk(DeleteTCBWithSrc, &LocalAddress, NULL, NULL);
  180. InvalidateAddrs(LocalAddress);
  181. }
  182. }
  183. }
  184. #pragma BEGIN_INIT
  185. extern uchar TCPGetConfigInfo(void);
  186. extern uchar IPPresent(void);
  187. //** tlinit - Initialize the transport layer.
  188. //
  189. // The main transport layer initialize routine. We get whatever config
  190. // info we need, initialize some data structures, get information
  191. // from IP, do some more initialization, and finally register our
  192. // protocol values with IP.
  193. //
  194. // Input: Nothing
  195. //
  196. // Returns: True is we succeeded, False if we fail to initialize.
  197. //
  198. int
  199. tlinit()
  200. {
  201. TDI_CLIENT_INTERFACE_INFO tdiInterface;
  202. uint TCBInitialized = 0;
  203. if (!CTEInitialize())
  204. return FALSE;
  205. #if MILLEN
  206. if (!PplInit()) {
  207. return FALSE;
  208. }
  209. #endif // MILLEN
  210. if (!TCPGetConfigInfo())
  211. return FALSE;
  212. StartTime = CTESystemUpTime();
  213. KeepAliveTime = MS_TO_TICKS(KeepAliveTime);
  214. KAInterval = MS_TO_TICKS(KAInterval);
  215. // Get net information from IP.
  216. if (TLGetIPInfo(&LocalNetInfo, sizeof(IPInfo)) != IP_SUCCESS)
  217. goto failure;
  218. if (LocalNetInfo.ipi_version != IP_DRIVER_VERSION)
  219. goto failure; // Wrong version of IP.
  220. // Now query the lower layer entities, and save the information.
  221. CTEInitLock(&EntityLock);
  222. EntityList = CTEAllocMem(sizeof(TDIEntityID) * MAX_TDI_ENTITIES);
  223. if (EntityList == NULL)
  224. goto failure;
  225. RtlZeroMemory(&tdiInterface, sizeof(tdiInterface));
  226. tdiInterface.MajorTdiVersion = TDI_CURRENT_MAJOR_VERSION;
  227. tdiInterface.MinorTdiVersion = TDI_CURRENT_MINOR_VERSION;
  228. tdiInterface.AddAddressHandlerV2 = AddressArrival;
  229. tdiInterface.DelAddressHandlerV2 = AddressDeletion;
  230. (void)TdiRegisterPnPHandlers(
  231. &tdiInterface,
  232. sizeof(tdiInterface),
  233. &AddressChangeHandle
  234. );
  235. //* Initialize addr obj management code.
  236. if (!InitAddr())
  237. goto failure;
  238. if (!InitDG(sizeof(UDPHeader)))
  239. goto failure;
  240. MaxConnections = MIN(MaxConnections, INVALID_CONN_INDEX - 1);
  241. if (!InitTCPConn())
  242. goto failure;
  243. if (!InitTCB())
  244. goto failure;
  245. TCBInitialized = 1;
  246. TcpRequestPool = PplCreatePool(NULL, NULL, 0,
  247. MAX(sizeof(DGSendReq),
  248. MAX(sizeof(TCPConnReq),
  249. MAX(sizeof(TCPSendReq),
  250. MAX(sizeof(TCPRcvReq),
  251. sizeof(TWTCB))))),
  252. 'rPCT', 512);
  253. if (!TcpRequestPool)
  254. goto failure;
  255. #if MILLEN
  256. if (!InitTcpIprPools()) {
  257. goto failure;
  258. }
  259. #endif // MILLEN
  260. if (!InitTCPRcv())
  261. goto failure;
  262. if (!InitTCPSend())
  263. goto failure;
  264. NdisZeroMemory(&TStats, sizeof(TCPStats));
  265. TStats.ts_rtoalgorithm = TCP_RTO_VANJ;
  266. TStats.ts_rtomin = MIN_RETRAN_TICKS * MS_PER_TICK;
  267. TStats.ts_rtomax = MAX_REXMIT_TO * MS_PER_TICK;
  268. TStats.ts_maxconn = (ulong) TCP_MAXCONN_DYNAMIC;
  269. NdisZeroMemory(&UStats, sizeof(UDPStats));
  270. // Register our UDP protocol handler.
  271. UDPProtInfo = TLRegisterProtocol(PROTOCOL_UDP, UDPRcv, DGSendComplete,
  272. UDPStatus, NULL, UDPPnPPowerRequest, NULL);
  273. if (UDPProtInfo == NULL)
  274. goto failure; // Failed to register!
  275. // Register the Raw IP (wildcard) protocol handler.
  276. RawProtInfo = TLRegisterProtocol(PROTOCOL_ANY, RawRcv, DGSendComplete,
  277. RawStatus, NULL, RawPnPPowerRequest, NULL);
  278. if (RawProtInfo == NULL) {
  279. goto failure; // Failed to register!
  280. }
  281. EntityList[0].tei_entity = CO_TL_ENTITY;
  282. EntityList[0].tei_instance = 0;
  283. EntityList[1].tei_entity = CL_TL_ENTITY;
  284. EntityList[1].tei_instance = 0;
  285. EntityCount = 2;
  286. // When we have multiple networks under us, we'll want to loop through
  287. // here calling them all. For now just call the one we have.
  288. (*LocalNetInfo.ipi_getelist) (EntityList, &EntityCount);
  289. return TRUE;
  290. // Come here to handle all failure cases.
  291. failure:
  292. // If we've registered Raw IP, unregister it now.
  293. if (RawProtInfo != NULL)
  294. TLRegisterProtocol(PROTOCOL_ANY, NULL, NULL, NULL, NULL, NULL, NULL);
  295. // If we've registered UDP, unregister it now.
  296. if (UDPProtInfo != NULL)
  297. TLRegisterProtocol(PROTOCOL_UDP, NULL, NULL, NULL, NULL, NULL, NULL);
  298. #if MILLEN
  299. PplDeinit();
  300. UnInitTcpIprPools();
  301. #endif // MILLEN
  302. PplDestroyPool(TcpRequestPool);
  303. UnInitTCPSend();
  304. UnInitTCPRcv();
  305. if (TCBInitialized) {
  306. UnInitTCB();
  307. }
  308. UnInitTCPConn();
  309. return FALSE;
  310. }
  311. #pragma END_INIT