TcpDispatcher.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. /** @file
  2. The implementation of a dispatch routine for processing TCP requests.
  3. (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
  4. Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "TcpMain.h"
  8. /**
  9. Add or remove a route entry in the IP route table associated with this TCP instance.
  10. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  11. @param[in] RouteInfo Pointer to the route information to be processed.
  12. @retval EFI_SUCCESS The operation completed successfully.
  13. @retval EFI_NOT_STARTED The driver instance has not been started.
  14. @retval EFI_NO_MAPPING When using the default address, configuration(DHCP,
  15. BOOTP, RARP, etc.) is not finished yet.
  16. @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.
  17. @retval EFI_NOT_FOUND This route is not in the routing table
  18. (when RouteInfo->DeleteRoute is TRUE).
  19. @retval EFI_ACCESS_DENIED The route is already defined in the routing table
  20. (when RouteInfo->DeleteRoute is FALSE).
  21. **/
  22. EFI_STATUS
  23. Tcp4Route (
  24. IN TCP_CB *Tcb,
  25. IN TCP4_ROUTE_INFO *RouteInfo
  26. )
  27. {
  28. IP_IO_IP_PROTOCOL Ip;
  29. Ip = Tcb->IpInfo->Ip;
  30. ASSERT (Ip.Ip4 != NULL);
  31. return Ip.Ip4->Routes (
  32. Ip.Ip4,
  33. RouteInfo->DeleteRoute,
  34. RouteInfo->SubnetAddress,
  35. RouteInfo->SubnetMask,
  36. RouteInfo->GatewayAddress
  37. );
  38. }
  39. /**
  40. Get the operational settings of this TCPv4 instance.
  41. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  42. @param[in, out] Mode Pointer to the buffer to store the operational
  43. settings.
  44. @retval EFI_SUCCESS The mode data was read.
  45. @retval EFI_NOT_STARTED No configuration data is available because this
  46. instance hasn't been started.
  47. **/
  48. EFI_STATUS
  49. Tcp4GetMode (
  50. IN TCP_CB *Tcb,
  51. IN OUT TCP4_MODE_DATA *Mode
  52. )
  53. {
  54. SOCKET *Sock;
  55. EFI_TCP4_CONFIG_DATA *ConfigData;
  56. EFI_TCP4_ACCESS_POINT *AccessPoint;
  57. EFI_TCP4_OPTION *Option;
  58. EFI_IP4_PROTOCOL *Ip;
  59. Sock = Tcb->Sk;
  60. if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp4ConfigData != NULL)) {
  61. return EFI_NOT_STARTED;
  62. }
  63. if (Mode->Tcp4State != NULL) {
  64. *(Mode->Tcp4State) = (EFI_TCP4_CONNECTION_STATE)Tcb->State;
  65. }
  66. if (Mode->Tcp4ConfigData != NULL) {
  67. ConfigData = Mode->Tcp4ConfigData;
  68. AccessPoint = &(ConfigData->AccessPoint);
  69. Option = ConfigData->ControlOption;
  70. ConfigData->TypeOfService = Tcb->Tos;
  71. ConfigData->TimeToLive = Tcb->Ttl;
  72. AccessPoint->UseDefaultAddress = Tcb->UseDefaultAddr;
  73. IP4_COPY_ADDRESS (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip);
  74. IP4_COPY_ADDRESS (&AccessPoint->SubnetMask, &Tcb->SubnetMask);
  75. AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port);
  76. IP4_COPY_ADDRESS (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip);
  77. AccessPoint->RemotePort = NTOHS (Tcb->RemoteEnd.Port);
  78. AccessPoint->ActiveFlag = (BOOLEAN)(Tcb->State != TCP_LISTEN);
  79. if (Option != NULL) {
  80. Option->ReceiveBufferSize = GET_RCV_BUFFSIZE (Tcb->Sk);
  81. Option->SendBufferSize = GET_SND_BUFFSIZE (Tcb->Sk);
  82. Option->MaxSynBackLog = GET_BACKLOG (Tcb->Sk);
  83. Option->ConnectionTimeout = Tcb->ConnectTimeout / TCP_TICK_HZ;
  84. Option->DataRetries = Tcb->MaxRexmit;
  85. Option->FinTimeout = Tcb->FinWait2Timeout / TCP_TICK_HZ;
  86. Option->TimeWaitTimeout = Tcb->TimeWaitTimeout / TCP_TICK_HZ;
  87. Option->KeepAliveProbes = Tcb->MaxKeepAlive;
  88. Option->KeepAliveTime = Tcb->KeepAliveIdle / TCP_TICK_HZ;
  89. Option->KeepAliveInterval = Tcb->KeepAlivePeriod / TCP_TICK_HZ;
  90. Option->EnableNagle = (BOOLEAN)(!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE));
  91. Option->EnableTimeStamp = (BOOLEAN)(!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS));
  92. Option->EnableWindowScaling = (BOOLEAN)(!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS));
  93. Option->EnableSelectiveAck = FALSE;
  94. Option->EnablePathMtuDiscovery = FALSE;
  95. }
  96. }
  97. Ip = Tcb->IpInfo->Ip.Ip4;
  98. ASSERT (Ip != NULL);
  99. return Ip->GetModeData (Ip, Mode->Ip4ModeData, Mode->MnpConfigData, Mode->SnpModeData);
  100. }
  101. /**
  102. Get the operational settings of this TCPv6 instance.
  103. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  104. @param[in, out] Mode Pointer to the buffer to store the operational
  105. settings.
  106. @retval EFI_SUCCESS The mode data was read.
  107. @retval EFI_NOT_STARTED No configuration data is available because this
  108. instance hasn't been started.
  109. **/
  110. EFI_STATUS
  111. Tcp6GetMode (
  112. IN TCP_CB *Tcb,
  113. IN OUT TCP6_MODE_DATA *Mode
  114. )
  115. {
  116. SOCKET *Sock;
  117. EFI_TCP6_CONFIG_DATA *ConfigData;
  118. EFI_TCP6_ACCESS_POINT *AccessPoint;
  119. EFI_TCP6_OPTION *Option;
  120. EFI_IP6_PROTOCOL *Ip;
  121. Sock = Tcb->Sk;
  122. if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp6ConfigData != NULL)) {
  123. return EFI_NOT_STARTED;
  124. }
  125. if (Mode->Tcp6State != NULL) {
  126. *(Mode->Tcp6State) = (EFI_TCP6_CONNECTION_STATE)(Tcb->State);
  127. }
  128. if (Mode->Tcp6ConfigData != NULL) {
  129. ConfigData = Mode->Tcp6ConfigData;
  130. AccessPoint = &(ConfigData->AccessPoint);
  131. Option = ConfigData->ControlOption;
  132. ConfigData->TrafficClass = Tcb->Tos;
  133. ConfigData->HopLimit = Tcb->Ttl;
  134. AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port);
  135. AccessPoint->RemotePort = NTOHS (Tcb->RemoteEnd.Port);
  136. AccessPoint->ActiveFlag = (BOOLEAN)(Tcb->State != TCP_LISTEN);
  137. IP6_COPY_ADDRESS (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip);
  138. IP6_COPY_ADDRESS (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip);
  139. if (Option != NULL) {
  140. Option->ReceiveBufferSize = GET_RCV_BUFFSIZE (Tcb->Sk);
  141. Option->SendBufferSize = GET_SND_BUFFSIZE (Tcb->Sk);
  142. Option->MaxSynBackLog = GET_BACKLOG (Tcb->Sk);
  143. Option->ConnectionTimeout = Tcb->ConnectTimeout / TCP_TICK_HZ;
  144. Option->DataRetries = Tcb->MaxRexmit;
  145. Option->FinTimeout = Tcb->FinWait2Timeout / TCP_TICK_HZ;
  146. Option->TimeWaitTimeout = Tcb->TimeWaitTimeout / TCP_TICK_HZ;
  147. Option->KeepAliveProbes = Tcb->MaxKeepAlive;
  148. Option->KeepAliveTime = Tcb->KeepAliveIdle / TCP_TICK_HZ;
  149. Option->KeepAliveInterval = Tcb->KeepAlivePeriod / TCP_TICK_HZ;
  150. Option->EnableNagle = (BOOLEAN)(!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE));
  151. Option->EnableTimeStamp = (BOOLEAN)(!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS));
  152. Option->EnableWindowScaling = (BOOLEAN)(!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS));
  153. Option->EnableSelectiveAck = FALSE;
  154. Option->EnablePathMtuDiscovery = FALSE;
  155. }
  156. }
  157. Ip = Tcb->IpInfo->Ip.Ip6;
  158. ASSERT (Ip != NULL);
  159. return Ip->GetModeData (Ip, Mode->Ip6ModeData, Mode->MnpConfigData, Mode->SnpModeData);
  160. }
  161. /**
  162. If TcpAp->StationPort isn't zero, check whether the access point
  163. is registered, else generate a random station port for this
  164. access point.
  165. @param[in] TcpAp Pointer to the access point.
  166. @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6
  167. @retval EFI_SUCCESS The check passed or the port is assigned.
  168. @retval EFI_INVALID_PARAMETER The non-zero station port is already used.
  169. @retval EFI_OUT_OF_RESOURCES No port can be allocated.
  170. **/
  171. EFI_STATUS
  172. TcpBind (
  173. IN TCP_ACCESS_POINT *TcpAp,
  174. IN UINT8 IpVersion
  175. )
  176. {
  177. BOOLEAN Cycle;
  178. EFI_IP_ADDRESS Local;
  179. UINT16 *Port;
  180. UINT16 *RandomPort;
  181. if (IpVersion == IP_VERSION_4) {
  182. IP4_COPY_ADDRESS (&Local, &TcpAp->Tcp4Ap.StationAddress);
  183. Port = &TcpAp->Tcp4Ap.StationPort;
  184. RandomPort = &mTcp4RandomPort;
  185. } else {
  186. IP6_COPY_ADDRESS (&Local, &TcpAp->Tcp6Ap.StationAddress);
  187. Port = &TcpAp->Tcp6Ap.StationPort;
  188. RandomPort = &mTcp6RandomPort;
  189. }
  190. if (0 != *Port) {
  191. //
  192. // Check if a same endpoing is bound.
  193. //
  194. if (TcpFindTcbByPeer (&Local, *Port, IpVersion)) {
  195. return EFI_INVALID_PARAMETER;
  196. }
  197. } else {
  198. //
  199. // generate a random port
  200. //
  201. Cycle = FALSE;
  202. if (TCP_PORT_USER_RESERVED == *RandomPort) {
  203. *RandomPort = TCP_PORT_KNOWN;
  204. }
  205. (*RandomPort)++;
  206. while (TcpFindTcbByPeer (&Local, *RandomPort, IpVersion)) {
  207. (*RandomPort)++;
  208. if (*RandomPort <= TCP_PORT_KNOWN) {
  209. if (Cycle) {
  210. DEBUG (
  211. (DEBUG_ERROR,
  212. "TcpBind: no port can be allocated for this pcb\n")
  213. );
  214. return EFI_OUT_OF_RESOURCES;
  215. }
  216. *RandomPort = TCP_PORT_KNOWN + 1;
  217. Cycle = TRUE;
  218. }
  219. }
  220. *Port = *RandomPort;
  221. }
  222. return EFI_SUCCESS;
  223. }
  224. /**
  225. Flush the Tcb add its associated protocols.
  226. @param[in, out] Tcb Pointer to the TCP_CB to be flushed.
  227. **/
  228. VOID
  229. TcpFlushPcb (
  230. IN OUT TCP_CB *Tcb
  231. )
  232. {
  233. SOCKET *Sock;
  234. IpIoConfigIp (Tcb->IpInfo, NULL);
  235. Sock = Tcb->Sk;
  236. if (SOCK_IS_CONFIGURED (Sock)) {
  237. RemoveEntryList (&Tcb->List);
  238. if (Sock->DevicePath != NULL) {
  239. //
  240. // Uninstall the device path protocol.
  241. //
  242. gBS->UninstallProtocolInterface (
  243. Sock->SockHandle,
  244. &gEfiDevicePathProtocolGuid,
  245. Sock->DevicePath
  246. );
  247. FreePool (Sock->DevicePath);
  248. Sock->DevicePath = NULL;
  249. }
  250. }
  251. NetbufFreeList (&Tcb->SndQue);
  252. NetbufFreeList (&Tcb->RcvQue);
  253. Tcb->State = TCP_CLOSED;
  254. Tcb->RemoteIpZero = FALSE;
  255. }
  256. /**
  257. Attach a Pcb to the socket.
  258. @param[in] Sk Pointer to the socket of this TCP instance.
  259. @retval EFI_SUCCESS The operation completed successfully.
  260. @retval EFI_OUT_OF_RESOURCES Failed due to resource limits.
  261. **/
  262. EFI_STATUS
  263. TcpAttachPcb (
  264. IN SOCKET *Sk
  265. )
  266. {
  267. TCP_CB *Tcb;
  268. TCP_PROTO_DATA *ProtoData;
  269. IP_IO *IpIo;
  270. EFI_STATUS Status;
  271. VOID *Ip;
  272. EFI_GUID *IpProtocolGuid;
  273. if (Sk->IpVersion == IP_VERSION_4) {
  274. IpProtocolGuid = &gEfiIp4ProtocolGuid;
  275. } else {
  276. IpProtocolGuid = &gEfiIp6ProtocolGuid;
  277. }
  278. Tcb = AllocateZeroPool (sizeof (TCP_CB));
  279. if (Tcb == NULL) {
  280. DEBUG ((DEBUG_ERROR, "TcpConfigurePcb: failed to allocate a TCB\n"));
  281. return EFI_OUT_OF_RESOURCES;
  282. }
  283. ProtoData = (TCP_PROTO_DATA *)Sk->ProtoReserved;
  284. IpIo = ProtoData->TcpService->IpIo;
  285. //
  286. // Create an IpInfo for this Tcb.
  287. //
  288. Tcb->IpInfo = IpIoAddIp (IpIo);
  289. if (Tcb->IpInfo == NULL) {
  290. FreePool (Tcb);
  291. return EFI_OUT_OF_RESOURCES;
  292. }
  293. //
  294. // Open the new created IP instance BY_CHILD.
  295. //
  296. Status = gBS->OpenProtocol (
  297. Tcb->IpInfo->ChildHandle,
  298. IpProtocolGuid,
  299. &Ip,
  300. IpIo->Image,
  301. Sk->SockHandle,
  302. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  303. );
  304. if (EFI_ERROR (Status)) {
  305. IpIoRemoveIp (IpIo, Tcb->IpInfo);
  306. FreePool (Tcb);
  307. return Status;
  308. }
  309. InitializeListHead (&Tcb->List);
  310. InitializeListHead (&Tcb->SndQue);
  311. InitializeListHead (&Tcb->RcvQue);
  312. Tcb->State = TCP_CLOSED;
  313. Tcb->Sk = Sk;
  314. ProtoData->TcpPcb = Tcb;
  315. return EFI_SUCCESS;
  316. }
  317. /**
  318. Detach the Pcb of the socket.
  319. @param[in, out] Sk Pointer to the socket of this TCP instance.
  320. **/
  321. VOID
  322. TcpDetachPcb (
  323. IN OUT SOCKET *Sk
  324. )
  325. {
  326. TCP_PROTO_DATA *ProtoData;
  327. TCP_CB *Tcb;
  328. ProtoData = (TCP_PROTO_DATA *)Sk->ProtoReserved;
  329. Tcb = ProtoData->TcpPcb;
  330. ASSERT (Tcb != NULL);
  331. TcpFlushPcb (Tcb);
  332. IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);
  333. FreePool (Tcb);
  334. ProtoData->TcpPcb = NULL;
  335. }
  336. /**
  337. Configure the Pcb using CfgData.
  338. @param[in] Sk Pointer to the socket of this TCP instance.
  339. @param[in] CfgData Pointer to the TCP configuration data.
  340. @retval EFI_SUCCESS The operation completed successfully.
  341. @retval EFI_INVALID_PARAMETER A same access point has been configured in
  342. another TCP instance.
  343. @retval EFI_OUT_OF_RESOURCES Failed due to resource limits.
  344. **/
  345. EFI_STATUS
  346. TcpConfigurePcb (
  347. IN SOCKET *Sk,
  348. IN TCP_CONFIG_DATA *CfgData
  349. )
  350. {
  351. IP_IO_IP_CONFIG_DATA IpCfgData;
  352. EFI_STATUS Status;
  353. EFI_TCP4_OPTION *Option;
  354. TCP_PROTO_DATA *TcpProto;
  355. TCP_CB *Tcb;
  356. TCP_ACCESS_POINT *TcpAp;
  357. ASSERT ((CfgData != NULL) && (Sk != NULL) && (Sk->SockHandle != NULL));
  358. TcpProto = (TCP_PROTO_DATA *)Sk->ProtoReserved;
  359. Tcb = TcpProto->TcpPcb;
  360. ASSERT (Tcb != NULL);
  361. if (Sk->IpVersion == IP_VERSION_4) {
  362. //
  363. // Add Ip for send pkt to the peer
  364. //
  365. CopyMem (&IpCfgData.Ip4CfgData, &mIp4IoDefaultIpConfigData, sizeof (EFI_IP4_CONFIG_DATA));
  366. IpCfgData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
  367. IpCfgData.Ip4CfgData.TypeOfService = CfgData->Tcp4CfgData.TypeOfService;
  368. IpCfgData.Ip4CfgData.TimeToLive = CfgData->Tcp4CfgData.TimeToLive;
  369. IpCfgData.Ip4CfgData.UseDefaultAddress = CfgData->Tcp4CfgData.AccessPoint.UseDefaultAddress;
  370. IP4_COPY_ADDRESS (
  371. &IpCfgData.Ip4CfgData.SubnetMask,
  372. &CfgData->Tcp4CfgData.AccessPoint.SubnetMask
  373. );
  374. IpCfgData.Ip4CfgData.ReceiveTimeout = (UINT32)(-1);
  375. IP4_COPY_ADDRESS (
  376. &IpCfgData.Ip4CfgData.StationAddress,
  377. &CfgData->Tcp4CfgData.AccessPoint.StationAddress
  378. );
  379. } else {
  380. ASSERT (Sk->IpVersion == IP_VERSION_6);
  381. CopyMem (&IpCfgData.Ip6CfgData, &mIp6IoDefaultIpConfigData, sizeof (EFI_IP6_CONFIG_DATA));
  382. IpCfgData.Ip6CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
  383. IpCfgData.Ip6CfgData.TrafficClass = CfgData->Tcp6CfgData.TrafficClass;
  384. IpCfgData.Ip6CfgData.HopLimit = CfgData->Tcp6CfgData.HopLimit;
  385. IpCfgData.Ip6CfgData.ReceiveTimeout = (UINT32)(-1);
  386. IP6_COPY_ADDRESS (
  387. &IpCfgData.Ip6CfgData.StationAddress,
  388. &CfgData->Tcp6CfgData.AccessPoint.StationAddress
  389. );
  390. IP6_COPY_ADDRESS (
  391. &IpCfgData.Ip6CfgData.DestinationAddress,
  392. &CfgData->Tcp6CfgData.AccessPoint.RemoteAddress
  393. );
  394. }
  395. //
  396. // Configure the IP instance this Tcb consumes.
  397. //
  398. Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData);
  399. if (EFI_ERROR (Status)) {
  400. goto OnExit;
  401. }
  402. if (Sk->IpVersion == IP_VERSION_4) {
  403. //
  404. // Get the default address information if the instance is configured to use default address.
  405. //
  406. IP4_COPY_ADDRESS (
  407. &CfgData->Tcp4CfgData.AccessPoint.StationAddress,
  408. &IpCfgData.Ip4CfgData.StationAddress
  409. );
  410. IP4_COPY_ADDRESS (
  411. &CfgData->Tcp4CfgData.AccessPoint.SubnetMask,
  412. &IpCfgData.Ip4CfgData.SubnetMask
  413. );
  414. TcpAp = (TCP_ACCESS_POINT *)&CfgData->Tcp4CfgData.AccessPoint;
  415. } else {
  416. IP6_COPY_ADDRESS (
  417. &CfgData->Tcp6CfgData.AccessPoint.StationAddress,
  418. &IpCfgData.Ip6CfgData.StationAddress
  419. );
  420. TcpAp = (TCP_ACCESS_POINT *)&CfgData->Tcp6CfgData.AccessPoint;
  421. }
  422. //
  423. // check if we can bind this endpoint in CfgData
  424. //
  425. Status = TcpBind (TcpAp, Sk->IpVersion);
  426. if (EFI_ERROR (Status)) {
  427. DEBUG (
  428. (DEBUG_ERROR,
  429. "TcpConfigurePcb: Bind endpoint failed with %r\n",
  430. Status)
  431. );
  432. goto OnExit;
  433. }
  434. //
  435. // Initialize the operating information in this Tcb
  436. //
  437. ASSERT (
  438. Tcb->State == TCP_CLOSED &&
  439. IsListEmpty (&Tcb->SndQue) &&
  440. IsListEmpty (&Tcb->RcvQue)
  441. );
  442. TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
  443. Tcb->State = TCP_CLOSED;
  444. Tcb->SndMss = 536;
  445. Tcb->RcvMss = TcpGetRcvMss (Sk);
  446. Tcb->SRtt = 0;
  447. Tcb->Rto = 3 * TCP_TICK_HZ;
  448. Tcb->CWnd = Tcb->SndMss;
  449. Tcb->Ssthresh = 0xffffffff;
  450. Tcb->CongestState = TCP_CONGEST_OPEN;
  451. Tcb->KeepAliveIdle = TCP_KEEPALIVE_IDLE_MIN;
  452. Tcb->KeepAlivePeriod = TCP_KEEPALIVE_PERIOD;
  453. Tcb->MaxKeepAlive = TCP_MAX_KEEPALIVE;
  454. Tcb->MaxRexmit = TCP_MAX_LOSS;
  455. Tcb->FinWait2Timeout = TCP_FIN_WAIT2_TIME;
  456. Tcb->TimeWaitTimeout = TCP_TIME_WAIT_TIME;
  457. Tcb->ConnectTimeout = TCP_CONNECT_TIME;
  458. if (Sk->IpVersion == IP_VERSION_4) {
  459. //
  460. // initialize Tcb in the light of CfgData
  461. //
  462. Tcb->Ttl = CfgData->Tcp4CfgData.TimeToLive;
  463. Tcb->Tos = CfgData->Tcp4CfgData.TypeOfService;
  464. Tcb->UseDefaultAddr = CfgData->Tcp4CfgData.AccessPoint.UseDefaultAddress;
  465. CopyMem (&Tcb->LocalEnd.Ip, &CfgData->Tcp4CfgData.AccessPoint.StationAddress, sizeof (IP4_ADDR));
  466. Tcb->LocalEnd.Port = HTONS (CfgData->Tcp4CfgData.AccessPoint.StationPort);
  467. IP4_COPY_ADDRESS (&Tcb->SubnetMask, &CfgData->Tcp4CfgData.AccessPoint.SubnetMask);
  468. CopyMem (&Tcb->RemoteEnd.Ip, &CfgData->Tcp4CfgData.AccessPoint.RemoteAddress, sizeof (IP4_ADDR));
  469. Tcb->RemoteEnd.Port = HTONS (CfgData->Tcp4CfgData.AccessPoint.RemotePort);
  470. Option = CfgData->Tcp4CfgData.ControlOption;
  471. } else {
  472. Tcb->Ttl = CfgData->Tcp6CfgData.HopLimit;
  473. Tcb->Tos = CfgData->Tcp6CfgData.TrafficClass;
  474. IP6_COPY_ADDRESS (&Tcb->LocalEnd.Ip, &CfgData->Tcp6CfgData.AccessPoint.StationAddress);
  475. Tcb->LocalEnd.Port = HTONS (CfgData->Tcp6CfgData.AccessPoint.StationPort);
  476. IP6_COPY_ADDRESS (&Tcb->RemoteEnd.Ip, &CfgData->Tcp6CfgData.AccessPoint.RemoteAddress);
  477. Tcb->RemoteEnd.Port = HTONS (CfgData->Tcp6CfgData.AccessPoint.RemotePort);
  478. //
  479. // Type EFI_TCP4_OPTION and EFI_TCP6_OPTION are the same.
  480. //
  481. Option = (EFI_TCP4_OPTION *)CfgData->Tcp6CfgData.ControlOption;
  482. }
  483. if (Option != NULL) {
  484. SET_RCV_BUFFSIZE (
  485. Sk,
  486. (UINT32)(TCP_COMP_VAL (
  487. TCP_RCV_BUF_SIZE_MIN,
  488. TCP_RCV_BUF_SIZE,
  489. TCP_RCV_BUF_SIZE,
  490. Option->ReceiveBufferSize
  491. )
  492. )
  493. );
  494. SET_SND_BUFFSIZE (
  495. Sk,
  496. (UINT32)(TCP_COMP_VAL (
  497. TCP_SND_BUF_SIZE_MIN,
  498. TCP_SND_BUF_SIZE,
  499. TCP_SND_BUF_SIZE,
  500. Option->SendBufferSize
  501. )
  502. )
  503. );
  504. SET_BACKLOG (
  505. Sk,
  506. (UINT32)(TCP_COMP_VAL (
  507. TCP_BACKLOG_MIN,
  508. TCP_BACKLOG,
  509. TCP_BACKLOG,
  510. Option->MaxSynBackLog
  511. )
  512. )
  513. );
  514. Tcb->MaxRexmit = (UINT16)TCP_COMP_VAL (
  515. TCP_MAX_LOSS_MIN,
  516. TCP_MAX_LOSS,
  517. TCP_MAX_LOSS,
  518. Option->DataRetries
  519. );
  520. Tcb->FinWait2Timeout = TCP_COMP_VAL (
  521. TCP_FIN_WAIT2_TIME,
  522. TCP_FIN_WAIT2_TIME_MAX,
  523. TCP_FIN_WAIT2_TIME,
  524. (UINT32)(Option->FinTimeout * TCP_TICK_HZ)
  525. );
  526. if (Option->TimeWaitTimeout != 0) {
  527. Tcb->TimeWaitTimeout = TCP_COMP_VAL (
  528. TCP_TIME_WAIT_TIME,
  529. TCP_TIME_WAIT_TIME_MAX,
  530. TCP_TIME_WAIT_TIME,
  531. (UINT32)(Option->TimeWaitTimeout * TCP_TICK_HZ)
  532. );
  533. } else {
  534. Tcb->TimeWaitTimeout = 0;
  535. }
  536. if (Option->KeepAliveProbes != 0) {
  537. TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
  538. Tcb->MaxKeepAlive = (UINT8)TCP_COMP_VAL (
  539. TCP_MAX_KEEPALIVE_MIN,
  540. TCP_MAX_KEEPALIVE,
  541. TCP_MAX_KEEPALIVE,
  542. Option->KeepAliveProbes
  543. );
  544. Tcb->KeepAliveIdle = TCP_COMP_VAL (
  545. TCP_KEEPALIVE_IDLE_MIN,
  546. TCP_KEEPALIVE_IDLE_MAX,
  547. TCP_KEEPALIVE_IDLE_MIN,
  548. (UINT32)(Option->KeepAliveTime * TCP_TICK_HZ)
  549. );
  550. Tcb->KeepAlivePeriod = TCP_COMP_VAL (
  551. TCP_KEEPALIVE_PERIOD_MIN,
  552. TCP_KEEPALIVE_PERIOD,
  553. TCP_KEEPALIVE_PERIOD,
  554. (UINT32)(Option->KeepAliveInterval * TCP_TICK_HZ)
  555. );
  556. }
  557. Tcb->ConnectTimeout = TCP_COMP_VAL (
  558. TCP_CONNECT_TIME_MIN,
  559. TCP_CONNECT_TIME,
  560. TCP_CONNECT_TIME,
  561. (UINT32)(Option->ConnectionTimeout * TCP_TICK_HZ)
  562. );
  563. if (!Option->EnableNagle) {
  564. TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);
  565. }
  566. if (!Option->EnableTimeStamp) {
  567. TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);
  568. }
  569. if (!Option->EnableWindowScaling) {
  570. TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS);
  571. }
  572. }
  573. //
  574. // The socket is bound, the <SrcIp, SrcPort, DstIp, DstPort> is
  575. // determined, construct the IP device path and install it.
  576. //
  577. Status = TcpInstallDevicePath (Sk);
  578. if (EFI_ERROR (Status)) {
  579. goto OnExit;
  580. }
  581. //
  582. // update state of Tcb and socket
  583. //
  584. if (((Sk->IpVersion == IP_VERSION_4) && !CfgData->Tcp4CfgData.AccessPoint.ActiveFlag) ||
  585. ((Sk->IpVersion == IP_VERSION_6) && !CfgData->Tcp6CfgData.AccessPoint.ActiveFlag)
  586. )
  587. {
  588. TcpSetState (Tcb, TCP_LISTEN);
  589. SockSetState (Sk, SO_LISTENING);
  590. Sk->ConfigureState = SO_CONFIGURED_PASSIVE;
  591. } else {
  592. Sk->ConfigureState = SO_CONFIGURED_ACTIVE;
  593. }
  594. if (Sk->IpVersion == IP_VERSION_6) {
  595. Tcb->Tick = TCP6_REFRESH_NEIGHBOR_TICK;
  596. if (NetIp6IsUnspecifiedAddr (&Tcb->RemoteEnd.Ip.v6)) {
  597. Tcb->RemoteIpZero = TRUE;
  598. }
  599. }
  600. TcpInsertTcb (Tcb);
  601. OnExit:
  602. return Status;
  603. }
  604. /**
  605. The protocol handler provided to the socket layer, which is used to
  606. dispatch the socket level requests by calling the corresponding
  607. TCP layer functions.
  608. @param[in] Sock Pointer to the socket of this TCP instance.
  609. @param[in] Request The code of this operation request.
  610. @param[in] Data Pointer to the operation specific data passed in
  611. together with the operation request. This is an
  612. optional parameter that may be NULL.
  613. @retval EFI_SUCCESS The socket request completed successfully.
  614. @retval other The error status returned by the corresponding TCP
  615. layer function.
  616. **/
  617. EFI_STATUS
  618. TcpDispatcher (
  619. IN SOCKET *Sock,
  620. IN UINT8 Request,
  621. IN VOID *Data OPTIONAL
  622. )
  623. {
  624. TCP_CB *Tcb;
  625. TCP_PROTO_DATA *ProtoData;
  626. ProtoData = (TCP_PROTO_DATA *)Sock->ProtoReserved;
  627. Tcb = ProtoData->TcpPcb;
  628. switch (Request) {
  629. case SOCK_POLL:
  630. if (Tcb->Sk->IpVersion == IP_VERSION_4) {
  631. ProtoData->TcpService->IpIo->Ip.Ip4->Poll (ProtoData->TcpService->IpIo->Ip.Ip4);
  632. } else {
  633. ProtoData->TcpService->IpIo->Ip.Ip6->Poll (ProtoData->TcpService->IpIo->Ip.Ip6);
  634. }
  635. break;
  636. case SOCK_CONSUMED:
  637. //
  638. // After user received data from socket buffer, socket will
  639. // notify TCP using this message to give it a chance to send out
  640. // window update information
  641. //
  642. ASSERT (Tcb != NULL);
  643. TcpOnAppConsume (Tcb);
  644. break;
  645. case SOCK_SND:
  646. ASSERT (Tcb != NULL);
  647. TcpOnAppSend (Tcb);
  648. break;
  649. case SOCK_CLOSE:
  650. TcpOnAppClose (Tcb);
  651. break;
  652. case SOCK_ABORT:
  653. TcpOnAppAbort (Tcb);
  654. break;
  655. case SOCK_SNDPUSH:
  656. Tcb->SndPsh = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk);
  657. TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);
  658. break;
  659. case SOCK_SNDURG:
  660. Tcb->SndUp = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk) - 1;
  661. TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);
  662. break;
  663. case SOCK_CONNECT:
  664. TcpOnAppConnect (Tcb);
  665. break;
  666. case SOCK_ATTACH:
  667. return TcpAttachPcb (Sock);
  668. break;
  669. case SOCK_FLUSH:
  670. TcpFlushPcb (Tcb);
  671. break;
  672. case SOCK_DETACH:
  673. TcpDetachPcb (Sock);
  674. break;
  675. case SOCK_CONFIGURE:
  676. return TcpConfigurePcb (
  677. Sock,
  678. (TCP_CONFIG_DATA *)Data
  679. );
  680. break;
  681. case SOCK_MODE:
  682. ASSERT ((Data != NULL) && (Tcb != NULL));
  683. if (Tcb->Sk->IpVersion == IP_VERSION_4) {
  684. return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *)Data);
  685. } else {
  686. return Tcp6GetMode (Tcb, (TCP6_MODE_DATA *)Data);
  687. }
  688. break;
  689. case SOCK_ROUTE:
  690. ASSERT ((Data != NULL) && (Tcb != NULL) && (Tcb->Sk->IpVersion == IP_VERSION_4));
  691. return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *)Data);
  692. default:
  693. return EFI_UNSUPPORTED;
  694. }
  695. return EFI_SUCCESS;
  696. }