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

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