TcpMisc.c 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. /** @file
  2. Misc support routines for TCP driver.
  3. (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
  4. Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "TcpMain.h"
  8. LIST_ENTRY mTcpRunQue = {
  9. &mTcpRunQue,
  10. &mTcpRunQue
  11. };
  12. LIST_ENTRY mTcpListenQue = {
  13. &mTcpListenQue,
  14. &mTcpListenQue
  15. };
  16. TCP_SEQNO mTcpGlobalIss = TCP_BASE_ISS;
  17. CHAR16 *mTcpStateName[] = {
  18. L"TCP_CLOSED",
  19. L"TCP_LISTEN",
  20. L"TCP_SYN_SENT",
  21. L"TCP_SYN_RCVD",
  22. L"TCP_ESTABLISHED",
  23. L"TCP_FIN_WAIT_1",
  24. L"TCP_FIN_WAIT_2",
  25. L"TCP_CLOSING",
  26. L"TCP_TIME_WAIT",
  27. L"TCP_CLOSE_WAIT",
  28. L"TCP_LAST_ACK"
  29. };
  30. /**
  31. Initialize the Tcb local related members.
  32. @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
  33. **/
  34. VOID
  35. TcpInitTcbLocal (
  36. IN OUT TCP_CB *Tcb
  37. )
  38. {
  39. //
  40. // Compute the checksum of the fixed parts of pseudo header
  41. //
  42. if (Tcb->Sk->IpVersion == IP_VERSION_4) {
  43. Tcb->HeadSum = NetPseudoHeadChecksum (
  44. Tcb->LocalEnd.Ip.Addr[0],
  45. Tcb->RemoteEnd.Ip.Addr[0],
  46. 0x06,
  47. 0
  48. );
  49. } else {
  50. Tcb->HeadSum = NetIp6PseudoHeadChecksum (
  51. &Tcb->LocalEnd.Ip.v6,
  52. &Tcb->RemoteEnd.Ip.v6,
  53. 0x06,
  54. 0
  55. );
  56. }
  57. Tcb->Iss = TcpGetIss ();
  58. Tcb->SndUna = Tcb->Iss;
  59. Tcb->SndNxt = Tcb->Iss;
  60. Tcb->SndWl2 = Tcb->Iss;
  61. Tcb->SndWnd = 536;
  62. Tcb->RcvWnd = GET_RCV_BUFFSIZE (Tcb->Sk);
  63. //
  64. // First window size is never scaled
  65. //
  66. Tcb->RcvWndScale = 0;
  67. Tcb->RetxmitSeqMax = 0;
  68. Tcb->ProbeTimerOn = FALSE;
  69. }
  70. /**
  71. Initialize the peer related members.
  72. @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
  73. @param[in] Seg Pointer to the segment that contains the peer's initial info.
  74. @param[in] Opt Pointer to the options announced by the peer.
  75. **/
  76. VOID
  77. TcpInitTcbPeer (
  78. IN OUT TCP_CB *Tcb,
  79. IN TCP_SEG *Seg,
  80. IN TCP_OPTION *Opt
  81. )
  82. {
  83. UINT16 RcvMss;
  84. ASSERT ((Tcb != NULL) && (Seg != NULL) && (Opt != NULL));
  85. ASSERT (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN));
  86. Tcb->SndWnd = Seg->Wnd;
  87. Tcb->SndWndMax = Tcb->SndWnd;
  88. Tcb->SndWl1 = Seg->Seq;
  89. if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
  90. Tcb->SndWl2 = Seg->Ack;
  91. } else {
  92. Tcb->SndWl2 = Tcb->Iss + 1;
  93. }
  94. if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_MSS)) {
  95. Tcb->SndMss = (UINT16)MAX (64, Opt->Mss);
  96. RcvMss = TcpGetRcvMss (Tcb->Sk);
  97. if (Tcb->SndMss > RcvMss) {
  98. Tcb->SndMss = RcvMss;
  99. }
  100. } else {
  101. //
  102. // One end doesn't support MSS option, use default.
  103. //
  104. Tcb->RcvMss = 536;
  105. }
  106. Tcb->CWnd = Tcb->SndMss;
  107. Tcb->Irs = Seg->Seq;
  108. Tcb->RcvNxt = Tcb->Irs + 1;
  109. Tcb->RcvWl2 = Tcb->RcvNxt;
  110. if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_WS) && !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS)) {
  111. Tcb->SndWndScale = Opt->WndScale;
  112. Tcb->RcvWndScale = TcpComputeScale (Tcb);
  113. TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS);
  114. } else {
  115. //
  116. // One end doesn't support window scale option. use zero.
  117. //
  118. Tcb->RcvWndScale = 0;
  119. }
  120. if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_TS) && !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS)) {
  121. TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_TS);
  122. TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS);
  123. Tcb->TsRecent = Opt->TSVal;
  124. //
  125. // Compute the effective SndMss per RFC1122
  126. // section 4.2.2.6. If timestamp option is
  127. // enabled, it will always occupy 12 bytes.
  128. //
  129. Tcb->SndMss -= TCP_OPTION_TS_ALIGNED_LEN;
  130. }
  131. }
  132. /**
  133. Check whether one IP address equals the other.
  134. @param[in] Ip1 Pointer to IP address to be checked.
  135. @param[in] Ip2 Pointer to IP address to be checked.
  136. @param[in] Version IP_VERSION_4 indicates the IP address is an IPv4 address,
  137. IP_VERSION_6 indicates the IP address is an IPv6 address.
  138. @retval TRUE Ip1 equals Ip2.
  139. @retval FALSE Ip1 does not equal Ip2.
  140. **/
  141. BOOLEAN
  142. TcpIsIpEqual (
  143. IN EFI_IP_ADDRESS *Ip1,
  144. IN EFI_IP_ADDRESS *Ip2,
  145. IN UINT8 Version
  146. )
  147. {
  148. ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6));
  149. if (Version == IP_VERSION_4) {
  150. return (BOOLEAN)(Ip1->Addr[0] == Ip2->Addr[0]);
  151. } else {
  152. return (BOOLEAN)EFI_IP6_EQUAL (&Ip1->v6, &Ip2->v6);
  153. }
  154. }
  155. /**
  156. Check whether one IP address is filled with ZERO.
  157. @param[in] Ip Pointer to the IP address to be checked.
  158. @param[in] Version IP_VERSION_4 indicates the IP address is an IPv4 address,
  159. IP_VERSION_6 indicates the IP address is an IPv6 address.
  160. @retval TRUE Ip is all zero address.
  161. @retval FALSE Ip is not all zero address.
  162. **/
  163. BOOLEAN
  164. TcpIsIpZero (
  165. IN EFI_IP_ADDRESS *Ip,
  166. IN UINT8 Version
  167. )
  168. {
  169. ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6));
  170. if (Version == IP_VERSION_4) {
  171. return (BOOLEAN)(Ip->Addr[0] == 0);
  172. } else {
  173. return (BOOLEAN)((Ip->Addr[0] == 0) && (Ip->Addr[1] == 0) &&
  174. (Ip->Addr[2] == 0) && (Ip->Addr[3] == 0));
  175. }
  176. }
  177. /**
  178. Locate a listen TCB that matchs the Local and Remote.
  179. @param[in] Local Pointer to the local (IP, Port).
  180. @param[in] Remote Pointer to the remote (IP, Port).
  181. @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
  182. IP_VERSION_6 indicates TCP is running on IP6 stack.
  183. @return Pointer to the TCP_CB with the least number of wildcards,
  184. if NULL no match is found.
  185. **/
  186. TCP_CB *
  187. TcpLocateListenTcb (
  188. IN TCP_PEER *Local,
  189. IN TCP_PEER *Remote,
  190. IN UINT8 Version
  191. )
  192. {
  193. LIST_ENTRY *Entry;
  194. TCP_CB *Node;
  195. TCP_CB *Match;
  196. INTN Last;
  197. INTN Cur;
  198. Last = 4;
  199. Match = NULL;
  200. NET_LIST_FOR_EACH (Entry, &mTcpListenQue) {
  201. Node = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
  202. if ((Version != Node->Sk->IpVersion) ||
  203. (Local->Port != Node->LocalEnd.Port) ||
  204. !TCP_PEER_MATCH (Remote, &Node->RemoteEnd, Version) ||
  205. !TCP_PEER_MATCH (Local, &Node->LocalEnd, Version)
  206. )
  207. {
  208. continue;
  209. }
  210. //
  211. // Compute the number of wildcard
  212. //
  213. Cur = 0;
  214. if (TcpIsIpZero (&Node->RemoteEnd.Ip, Version)) {
  215. Cur++;
  216. }
  217. if (Node->RemoteEnd.Port == 0) {
  218. Cur++;
  219. }
  220. if (TcpIsIpZero (&Node->LocalEnd.Ip, Version)) {
  221. Cur++;
  222. }
  223. if (Cur < Last) {
  224. if (Cur == 0) {
  225. return Node;
  226. }
  227. Last = Cur;
  228. Match = Node;
  229. }
  230. }
  231. return Match;
  232. }
  233. /**
  234. Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
  235. @param[in] Addr Pointer to the IP address needs to match.
  236. @param[in] Port The port number needs to match.
  237. @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
  238. IP_VERSION_6 indicates TCP is running on IP6 stack.
  239. @retval TRUE The Tcb which matches the <Addr Port> pair exists.
  240. @retval FALSE Otherwise
  241. **/
  242. BOOLEAN
  243. TcpFindTcbByPeer (
  244. IN EFI_IP_ADDRESS *Addr,
  245. IN TCP_PORTNO Port,
  246. IN UINT8 Version
  247. )
  248. {
  249. TCP_PORTNO LocalPort;
  250. LIST_ENTRY *Entry;
  251. TCP_CB *Tcb;
  252. ASSERT ((Addr != NULL) && (Port != 0));
  253. LocalPort = HTONS (Port);
  254. NET_LIST_FOR_EACH (Entry, &mTcpListenQue) {
  255. Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
  256. if ((Version == Tcb->Sk->IpVersion) &&
  257. TcpIsIpEqual (Addr, &Tcb->LocalEnd.Ip, Version) &&
  258. (LocalPort == Tcb->LocalEnd.Port)
  259. )
  260. {
  261. return TRUE;
  262. }
  263. }
  264. NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {
  265. Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
  266. if ((Version == Tcb->Sk->IpVersion) &&
  267. TcpIsIpEqual (Addr, &Tcb->LocalEnd.Ip, Version) &&
  268. (LocalPort == Tcb->LocalEnd.Port)
  269. )
  270. {
  271. return TRUE;
  272. }
  273. }
  274. return FALSE;
  275. }
  276. /**
  277. Locate the TCP_CB related to the socket pair.
  278. @param[in] LocalPort The local port number.
  279. @param[in] LocalIp The local IP address.
  280. @param[in] RemotePort The remote port number.
  281. @param[in] RemoteIp The remote IP address.
  282. @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
  283. IP_VERSION_6 indicates TCP is running on IP6 stack.
  284. @param[in] Syn If TRUE, the listen sockets are searched.
  285. @return Pointer to the related TCP_CB. If NULL, no match is found.
  286. **/
  287. TCP_CB *
  288. TcpLocateTcb (
  289. IN TCP_PORTNO LocalPort,
  290. IN EFI_IP_ADDRESS *LocalIp,
  291. IN TCP_PORTNO RemotePort,
  292. IN EFI_IP_ADDRESS *RemoteIp,
  293. IN UINT8 Version,
  294. IN BOOLEAN Syn
  295. )
  296. {
  297. TCP_PEER Local;
  298. TCP_PEER Remote;
  299. LIST_ENTRY *Entry;
  300. TCP_CB *Tcb;
  301. Local.Port = LocalPort;
  302. Remote.Port = RemotePort;
  303. CopyMem (&Local.Ip, LocalIp, sizeof (EFI_IP_ADDRESS));
  304. CopyMem (&Remote.Ip, RemoteIp, sizeof (EFI_IP_ADDRESS));
  305. //
  306. // First check for exact match.
  307. //
  308. NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {
  309. Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
  310. if ((Version == Tcb->Sk->IpVersion) &&
  311. TCP_PEER_EQUAL (&Remote, &Tcb->RemoteEnd, Version) &&
  312. TCP_PEER_EQUAL (&Local, &Tcb->LocalEnd, Version)
  313. )
  314. {
  315. RemoveEntryList (&Tcb->List);
  316. InsertHeadList (&mTcpRunQue, &Tcb->List);
  317. return Tcb;
  318. }
  319. }
  320. //
  321. // Only check the listen queue when the SYN flag is on.
  322. //
  323. if (Syn) {
  324. return TcpLocateListenTcb (&Local, &Remote, Version);
  325. }
  326. return NULL;
  327. }
  328. /**
  329. Insert a Tcb into the proper queue.
  330. @param[in] Tcb Pointer to the TCP_CB to be inserted.
  331. @retval 0 The Tcb was inserted successfully.
  332. @retval -1 Error condition occurred.
  333. **/
  334. INTN
  335. TcpInsertTcb (
  336. IN TCP_CB *Tcb
  337. )
  338. {
  339. LIST_ENTRY *Entry;
  340. LIST_ENTRY *Head;
  341. TCP_CB *Node;
  342. ASSERT (
  343. (Tcb != NULL) &&
  344. (
  345. (Tcb->State == TCP_LISTEN) ||
  346. (Tcb->State == TCP_SYN_SENT) ||
  347. (Tcb->State == TCP_SYN_RCVD) ||
  348. (Tcb->State == TCP_CLOSED)
  349. )
  350. );
  351. if (Tcb->LocalEnd.Port == 0) {
  352. return -1;
  353. }
  354. Head = &mTcpRunQue;
  355. if (Tcb->State == TCP_LISTEN) {
  356. Head = &mTcpListenQue;
  357. }
  358. //
  359. // Check that the Tcb isn't already on the list.
  360. //
  361. NET_LIST_FOR_EACH (Entry, Head) {
  362. Node = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
  363. if (TCP_PEER_EQUAL (&Tcb->LocalEnd, &Node->LocalEnd, Tcb->Sk->IpVersion) &&
  364. TCP_PEER_EQUAL (&Tcb->RemoteEnd, &Node->RemoteEnd, Tcb->Sk->IpVersion)
  365. )
  366. {
  367. return -1;
  368. }
  369. }
  370. InsertHeadList (Head, &Tcb->List);
  371. return 0;
  372. }
  373. /**
  374. Clone a TCP_CB from Tcb.
  375. @param[in] Tcb Pointer to the TCP_CB to be cloned.
  376. @return Pointer to the new cloned TCP_CB; if NULL, error condition occurred.
  377. **/
  378. TCP_CB *
  379. TcpCloneTcb (
  380. IN TCP_CB *Tcb
  381. )
  382. {
  383. TCP_CB *Clone;
  384. Clone = AllocateZeroPool (sizeof (TCP_CB));
  385. if (Clone == NULL) {
  386. return NULL;
  387. }
  388. CopyMem (Clone, Tcb, sizeof (TCP_CB));
  389. //
  390. // Increase the reference count of the shared IpInfo.
  391. //
  392. NET_GET_REF (Tcb->IpInfo);
  393. InitializeListHead (&Clone->List);
  394. InitializeListHead (&Clone->SndQue);
  395. InitializeListHead (&Clone->RcvQue);
  396. Clone->Sk = SockClone (Tcb->Sk);
  397. if (Clone->Sk == NULL) {
  398. DEBUG ((DEBUG_ERROR, "TcpCloneTcb: failed to clone a sock\n"));
  399. FreePool (Clone);
  400. return NULL;
  401. }
  402. ((TCP_PROTO_DATA *)(Clone->Sk->ProtoReserved))->TcpPcb = Clone;
  403. return Clone;
  404. }
  405. /**
  406. Compute an ISS to be used by a new connection.
  407. @return The resulting ISS.
  408. **/
  409. TCP_SEQNO
  410. TcpGetIss (
  411. VOID
  412. )
  413. {
  414. mTcpGlobalIss += TCP_ISS_INCREMENT_1;
  415. return mTcpGlobalIss;
  416. }
  417. /**
  418. Get the local mss.
  419. @param[in] Sock Pointer to the socket to get mss.
  420. @return The mss size.
  421. **/
  422. UINT16
  423. TcpGetRcvMss (
  424. IN SOCKET *Sock
  425. )
  426. {
  427. EFI_IP4_MODE_DATA Ip4Mode;
  428. EFI_IP6_MODE_DATA Ip6Mode;
  429. EFI_IP4_PROTOCOL *Ip4;
  430. EFI_IP6_PROTOCOL *Ip6;
  431. TCP_PROTO_DATA *TcpProto;
  432. ASSERT (Sock != NULL);
  433. ZeroMem (&Ip4Mode, sizeof (EFI_IP4_MODE_DATA));
  434. ZeroMem (&Ip6Mode, sizeof (EFI_IP6_MODE_DATA));
  435. TcpProto = (TCP_PROTO_DATA *)Sock->ProtoReserved;
  436. if (Sock->IpVersion == IP_VERSION_4) {
  437. Ip4 = TcpProto->TcpService->IpIo->Ip.Ip4;
  438. ASSERT (Ip4 != NULL);
  439. Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL);
  440. return (UINT16)(Ip4Mode.MaxPacketSize - sizeof (TCP_HEAD));
  441. } else {
  442. Ip6 = TcpProto->TcpService->IpIo->Ip.Ip6;
  443. ASSERT (Ip6 != NULL);
  444. if (!EFI_ERROR (Ip6->GetModeData (Ip6, &Ip6Mode, NULL, NULL))) {
  445. if (Ip6Mode.AddressList != NULL) {
  446. FreePool (Ip6Mode.AddressList);
  447. }
  448. if (Ip6Mode.GroupTable != NULL) {
  449. FreePool (Ip6Mode.GroupTable);
  450. }
  451. if (Ip6Mode.RouteTable != NULL) {
  452. FreePool (Ip6Mode.RouteTable);
  453. }
  454. if (Ip6Mode.NeighborCache != NULL) {
  455. FreePool (Ip6Mode.NeighborCache);
  456. }
  457. if (Ip6Mode.PrefixTable != NULL) {
  458. FreePool (Ip6Mode.PrefixTable);
  459. }
  460. if (Ip6Mode.IcmpTypeList != NULL) {
  461. FreePool (Ip6Mode.IcmpTypeList);
  462. }
  463. }
  464. return (UINT16)(Ip6Mode.MaxPacketSize - sizeof (TCP_HEAD));
  465. }
  466. }
  467. /**
  468. Set the Tcb's state.
  469. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  470. @param[in] State The state to be set.
  471. **/
  472. VOID
  473. TcpSetState (
  474. IN TCP_CB *Tcb,
  475. IN UINT8 State
  476. )
  477. {
  478. ASSERT (Tcb->State < (sizeof (mTcpStateName) / sizeof (CHAR16 *)));
  479. ASSERT (State < (sizeof (mTcpStateName) / sizeof (CHAR16 *)));
  480. DEBUG (
  481. (DEBUG_NET,
  482. "Tcb (%p) state %s --> %s\n",
  483. Tcb,
  484. mTcpStateName[Tcb->State],
  485. mTcpStateName[State])
  486. );
  487. Tcb->State = State;
  488. switch (State) {
  489. case TCP_ESTABLISHED:
  490. SockConnEstablished (Tcb->Sk);
  491. if (Tcb->Parent != NULL) {
  492. //
  493. // A new connection is accepted by a listening socket. Install
  494. // the device path.
  495. //
  496. TcpInstallDevicePath (Tcb->Sk);
  497. }
  498. break;
  499. case TCP_CLOSED:
  500. SockConnClosed (Tcb->Sk);
  501. break;
  502. default:
  503. break;
  504. }
  505. }
  506. /**
  507. Compute the TCP segment's checksum.
  508. @param[in] Nbuf Pointer to the buffer that contains the TCP segment.
  509. @param[in] HeadSum The checksum value of the fixed part of pseudo header.
  510. @return The checksum value.
  511. **/
  512. UINT16
  513. TcpChecksum (
  514. IN NET_BUF *Nbuf,
  515. IN UINT16 HeadSum
  516. )
  517. {
  518. UINT16 Checksum;
  519. Checksum = NetbufChecksum (Nbuf);
  520. Checksum = NetAddChecksum (Checksum, HeadSum);
  521. Checksum = NetAddChecksum (
  522. Checksum,
  523. HTONS ((UINT16)Nbuf->TotalSize)
  524. );
  525. return (UINT16)(~Checksum);
  526. }
  527. /**
  528. Translate the information from the head of the received TCP
  529. segment Nbuf contents and fill it into a TCP_SEG structure.
  530. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  531. @param[in, out] Nbuf Pointer to the buffer contains the TCP segment.
  532. @return Pointer to the TCP_SEG that contains the translated TCP head information.
  533. **/
  534. TCP_SEG *
  535. TcpFormatNetbuf (
  536. IN TCP_CB *Tcb,
  537. IN OUT NET_BUF *Nbuf
  538. )
  539. {
  540. TCP_SEG *Seg;
  541. TCP_HEAD *Head;
  542. Seg = TCPSEG_NETBUF (Nbuf);
  543. Head = (TCP_HEAD *)NetbufGetByte (Nbuf, 0, NULL);
  544. ASSERT (Head != NULL);
  545. Nbuf->Tcp = Head;
  546. Seg->Seq = NTOHL (Head->Seq);
  547. Seg->Ack = NTOHL (Head->Ack);
  548. Seg->End = Seg->Seq + (Nbuf->TotalSize - (Head->HeadLen << 2));
  549. Seg->Urg = NTOHS (Head->Urg);
  550. Seg->Wnd = (NTOHS (Head->Wnd) << Tcb->SndWndScale);
  551. Seg->Flag = Head->Flag;
  552. //
  553. // SYN and FIN flag occupy one sequence space each.
  554. //
  555. if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
  556. //
  557. // RFC requires that the initial window not be scaled.
  558. //
  559. Seg->Wnd = NTOHS (Head->Wnd);
  560. Seg->End++;
  561. }
  562. if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
  563. Seg->End++;
  564. }
  565. return Seg;
  566. }
  567. /**
  568. Initialize an active connection.
  569. @param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
  570. connection.
  571. **/
  572. VOID
  573. TcpOnAppConnect (
  574. IN OUT TCP_CB *Tcb
  575. )
  576. {
  577. TcpInitTcbLocal (Tcb);
  578. TcpSetState (Tcb, TCP_SYN_SENT);
  579. TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);
  580. TcpToSendData (Tcb, 1);
  581. }
  582. /**
  583. Initiate the connection close procedure, called when
  584. applications want to close the connection.
  585. @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
  586. **/
  587. VOID
  588. TcpOnAppClose (
  589. IN OUT TCP_CB *Tcb
  590. )
  591. {
  592. ASSERT (Tcb != NULL);
  593. if (!IsListEmpty (&Tcb->RcvQue) || (GET_RCV_DATASIZE (Tcb->Sk) != 0)) {
  594. DEBUG (
  595. (DEBUG_WARN,
  596. "TcpOnAppClose: connection reset because data is lost for TCB %p\n",
  597. Tcb)
  598. );
  599. TcpResetConnection (Tcb);
  600. TcpClose (Tcb);
  601. return;
  602. }
  603. switch (Tcb->State) {
  604. case TCP_CLOSED:
  605. case TCP_LISTEN:
  606. case TCP_SYN_SENT:
  607. TcpSetState (Tcb, TCP_CLOSED);
  608. break;
  609. case TCP_SYN_RCVD:
  610. case TCP_ESTABLISHED:
  611. TcpSetState (Tcb, TCP_FIN_WAIT_1);
  612. break;
  613. case TCP_CLOSE_WAIT:
  614. TcpSetState (Tcb, TCP_LAST_ACK);
  615. break;
  616. default:
  617. break;
  618. }
  619. TcpToSendData (Tcb, 1);
  620. }
  621. /**
  622. Check whether the application's newly delivered data can be sent out.
  623. @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
  624. @retval 0 The data has been sent out successfully.
  625. @retval -1 The Tcb is not in a state that data is permitted to
  626. be sent out.
  627. **/
  628. INTN
  629. TcpOnAppSend (
  630. IN OUT TCP_CB *Tcb
  631. )
  632. {
  633. switch (Tcb->State) {
  634. case TCP_CLOSED:
  635. return -1;
  636. case TCP_LISTEN:
  637. return -1;
  638. case TCP_SYN_SENT:
  639. case TCP_SYN_RCVD:
  640. return 0;
  641. case TCP_ESTABLISHED:
  642. case TCP_CLOSE_WAIT:
  643. TcpToSendData (Tcb, 0);
  644. return 0;
  645. case TCP_FIN_WAIT_1:
  646. case TCP_FIN_WAIT_2:
  647. case TCP_CLOSING:
  648. case TCP_LAST_ACK:
  649. case TCP_TIME_WAIT:
  650. return -1;
  651. default:
  652. break;
  653. }
  654. return 0;
  655. }
  656. /**
  657. Application has consumed some data. Check whether
  658. to send a window update ack or a delayed ack.
  659. @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
  660. **/
  661. VOID
  662. TcpOnAppConsume (
  663. IN TCP_CB *Tcb
  664. )
  665. {
  666. UINT32 TcpOld;
  667. switch (Tcb->State) {
  668. case TCP_ESTABLISHED:
  669. TcpOld = TcpRcvWinOld (Tcb);
  670. if (TcpRcvWinNow (Tcb) > TcpOld) {
  671. if (TcpOld < Tcb->RcvMss) {
  672. DEBUG (
  673. (DEBUG_NET,
  674. "TcpOnAppConsume: send a window update for a window closed Tcb %p\n",
  675. Tcb)
  676. );
  677. TcpSendAck (Tcb);
  678. } else if (Tcb->DelayedAck == 0) {
  679. DEBUG (
  680. (DEBUG_NET,
  681. "TcpOnAppConsume: scheduled a delayed ACK to update window for Tcb %p\n",
  682. Tcb)
  683. );
  684. Tcb->DelayedAck = 1;
  685. }
  686. }
  687. break;
  688. default:
  689. break;
  690. }
  691. }
  692. /**
  693. Abort the connection by sending a reset segment. Called
  694. when the application wants to abort the connection.
  695. @param[in] Tcb Pointer to the TCP_CB of the TCP instance.
  696. **/
  697. VOID
  698. TcpOnAppAbort (
  699. IN TCP_CB *Tcb
  700. )
  701. {
  702. DEBUG (
  703. (DEBUG_WARN,
  704. "TcpOnAppAbort: connection reset issued by application for TCB %p\n",
  705. Tcb)
  706. );
  707. switch (Tcb->State) {
  708. case TCP_SYN_RCVD:
  709. case TCP_ESTABLISHED:
  710. case TCP_FIN_WAIT_1:
  711. case TCP_FIN_WAIT_2:
  712. case TCP_CLOSE_WAIT:
  713. TcpResetConnection (Tcb);
  714. break;
  715. default:
  716. break;
  717. }
  718. TcpSetState (Tcb, TCP_CLOSED);
  719. }
  720. /**
  721. Reset the connection related with Tcb.
  722. @param[in] Tcb Pointer to the TCP_CB of the connection to be reset.
  723. **/
  724. VOID
  725. TcpResetConnection (
  726. IN TCP_CB *Tcb
  727. )
  728. {
  729. NET_BUF *Nbuf;
  730. TCP_HEAD *Nhead;
  731. Nbuf = NetbufAlloc (TCP_MAX_HEAD);
  732. if (Nbuf == NULL) {
  733. return;
  734. }
  735. Nhead = (TCP_HEAD *)NetbufAllocSpace (
  736. Nbuf,
  737. sizeof (TCP_HEAD),
  738. NET_BUF_TAIL
  739. );
  740. ASSERT (Nhead != NULL);
  741. Nbuf->Tcp = Nhead;
  742. Nhead->Flag = TCP_FLG_RST;
  743. Nhead->Seq = HTONL (Tcb->SndNxt);
  744. Nhead->Ack = HTONL (Tcb->RcvNxt);
  745. Nhead->SrcPort = Tcb->LocalEnd.Port;
  746. Nhead->DstPort = Tcb->RemoteEnd.Port;
  747. Nhead->HeadLen = (UINT8)(sizeof (TCP_HEAD) >> 2);
  748. Nhead->Res = 0;
  749. Nhead->Wnd = HTONS (0xFFFF);
  750. Nhead->Checksum = 0;
  751. Nhead->Urg = 0;
  752. Nhead->Checksum = TcpChecksum (Nbuf, Tcb->HeadSum);
  753. TcpSendIpPacket (Tcb, Nbuf, &Tcb->LocalEnd.Ip, &Tcb->RemoteEnd.Ip, Tcb->Sk->IpVersion);
  754. NetbufFree (Nbuf);
  755. }
  756. /**
  757. Install the device path protocol on the TCP instance.
  758. @param[in] Sock Pointer to the socket representing the TCP instance.
  759. @retval EFI_SUCCESS The device path protocol was installed.
  760. @retval other Failed to install the device path protocol.
  761. **/
  762. EFI_STATUS
  763. TcpInstallDevicePath (
  764. IN SOCKET *Sock
  765. )
  766. {
  767. TCP_PROTO_DATA *TcpProto;
  768. TCP_SERVICE_DATA *TcpService;
  769. TCP_CB *Tcb;
  770. IPv4_DEVICE_PATH Ip4DPathNode;
  771. IPv6_DEVICE_PATH Ip6DPathNode;
  772. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  773. EFI_STATUS Status;
  774. TCP_PORTNO LocalPort;
  775. TCP_PORTNO RemotePort;
  776. TcpProto = (TCP_PROTO_DATA *)Sock->ProtoReserved;
  777. TcpService = TcpProto->TcpService;
  778. Tcb = TcpProto->TcpPcb;
  779. LocalPort = NTOHS (Tcb->LocalEnd.Port);
  780. RemotePort = NTOHS (Tcb->RemoteEnd.Port);
  781. if (Sock->IpVersion == IP_VERSION_4) {
  782. NetLibCreateIPv4DPathNode (
  783. &Ip4DPathNode,
  784. TcpService->ControllerHandle,
  785. Tcb->LocalEnd.Ip.Addr[0],
  786. LocalPort,
  787. Tcb->RemoteEnd.Ip.Addr[0],
  788. RemotePort,
  789. EFI_IP_PROTO_TCP,
  790. Tcb->UseDefaultAddr
  791. );
  792. IP4_COPY_ADDRESS (&Ip4DPathNode.SubnetMask, &Tcb->SubnetMask);
  793. DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&Ip4DPathNode;
  794. } else {
  795. NetLibCreateIPv6DPathNode (
  796. &Ip6DPathNode,
  797. TcpService->ControllerHandle,
  798. &Tcb->LocalEnd.Ip.v6,
  799. LocalPort,
  800. &Tcb->RemoteEnd.Ip.v6,
  801. RemotePort,
  802. EFI_IP_PROTO_TCP
  803. );
  804. DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&Ip6DPathNode;
  805. }
  806. Sock->DevicePath = AppendDevicePathNode (Sock->ParentDevicePath, DevicePath);
  807. if (Sock->DevicePath == NULL) {
  808. return EFI_OUT_OF_RESOURCES;
  809. }
  810. Status = gBS->InstallProtocolInterface (
  811. &Sock->SockHandle,
  812. &gEfiDevicePathProtocolGuid,
  813. EFI_NATIVE_INTERFACE,
  814. Sock->DevicePath
  815. );
  816. if (EFI_ERROR (Status)) {
  817. FreePool (Sock->DevicePath);
  818. Sock->DevicePath = NULL;
  819. }
  820. return Status;
  821. }