TianoCore EDK2 master
Loading...
Searching...
No Matches
TcpMisc.c
Go to the documentation of this file.
1
11#include "TcpMain.h"
12
13LIST_ENTRY mTcpRunQue = {
14 &mTcpRunQue,
15 &mTcpRunQue
16};
17
18LIST_ENTRY mTcpListenQue = {
19 &mTcpListenQue,
20 &mTcpListenQue
21};
22
23//
24// The Session secret
25// This must be initialized to a random value at boot time
26//
27TCP_SEQNO mTcpGlobalSecret;
28
29//
30// Union to hold either an IPv4 or IPv6 address
31// This is used to simplify the ISN hash computation
32//
33typedef union {
34 UINT8 IPv4[4];
35 UINT8 IPv6[16];
37
38//
39// The ISN is computed by hashing this structure
40// It is initialized with the local and remote IP addresses and ports
41// and the secret
42//
43//
44typedef struct {
45 UINT16 LocalPort;
46 UINT16 RemotePort;
47 NETWORK_ADDRESS LocalAddress;
48 NETWORK_ADDRESS RemoteAddress;
49 TCP_SEQNO Secret;
51
52CHAR16 *mTcpStateName[] = {
53 L"TCP_CLOSED",
54 L"TCP_LISTEN",
55 L"TCP_SYN_SENT",
56 L"TCP_SYN_RCVD",
57 L"TCP_ESTABLISHED",
58 L"TCP_FIN_WAIT_1",
59 L"TCP_FIN_WAIT_2",
60 L"TCP_CLOSING",
61 L"TCP_TIME_WAIT",
62 L"TCP_CLOSE_WAIT",
63 L"TCP_LAST_ACK"
64};
65
77 IN OUT TCP_CB *Tcb
78 )
79{
80 TCP_SEQNO Isn;
81 EFI_STATUS Status;
82
83 //
84 // Compute the checksum of the fixed parts of pseudo header
85 //
86 if (Tcb->Sk->IpVersion == IP_VERSION_4) {
87 Tcb->HeadSum = NetPseudoHeadChecksum (
88 Tcb->LocalEnd.Ip.Addr[0],
89 Tcb->RemoteEnd.Ip.Addr[0],
90 0x06,
91 0
92 );
93
94 Status = TcpGetIsn (
95 Tcb->LocalEnd.Ip.v4.Addr,
96 sizeof (IPv4_ADDRESS),
97 Tcb->LocalEnd.Port,
98 Tcb->RemoteEnd.Ip.v4.Addr,
99 sizeof (IPv4_ADDRESS),
100 Tcb->RemoteEnd.Port,
101 &Isn
102 );
103 } else {
104 Tcb->HeadSum = NetIp6PseudoHeadChecksum (
105 &Tcb->LocalEnd.Ip.v6,
106 &Tcb->RemoteEnd.Ip.v6,
107 0x06,
108 0
109 );
110
111 Status = TcpGetIsn (
112 Tcb->LocalEnd.Ip.v6.Addr,
113 sizeof (IPv6_ADDRESS),
114 Tcb->LocalEnd.Port,
115 Tcb->RemoteEnd.Ip.v6.Addr,
116 sizeof (IPv6_ADDRESS),
117 Tcb->RemoteEnd.Port,
118 &Isn
119 );
120 }
121
122 if (EFI_ERROR (Status)) {
123 DEBUG ((DEBUG_ERROR, "TcpInitTcbLocal: failed to get isn\n"));
124 ASSERT (FALSE);
125 return Status;
126 }
127
128 Tcb->Iss = Isn;
129 Tcb->SndUna = Tcb->Iss;
130 Tcb->SndNxt = Tcb->Iss;
131
132 Tcb->SndWl2 = Tcb->Iss;
133 Tcb->SndWnd = 536;
134
135 Tcb->RcvWnd = GET_RCV_BUFFSIZE (Tcb->Sk);
136
137 //
138 // First window size is never scaled
139 //
140 Tcb->RcvWndScale = 0;
141 Tcb->RetxmitSeqMax = 0;
142
143 Tcb->ProbeTimerOn = FALSE;
144
145 return EFI_SUCCESS;
146}
147
156VOID
158 IN OUT TCP_CB *Tcb,
159 IN TCP_SEG *Seg,
160 IN TCP_OPTION *Opt
161 )
162{
163 UINT16 RcvMss;
164
165 ASSERT ((Tcb != NULL) && (Seg != NULL) && (Opt != NULL));
166 ASSERT (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN));
167
168 Tcb->SndWnd = Seg->Wnd;
169 Tcb->SndWndMax = Tcb->SndWnd;
170 Tcb->SndWl1 = Seg->Seq;
171
172 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
173 Tcb->SndWl2 = Seg->Ack;
174 } else {
175 Tcb->SndWl2 = Tcb->Iss + 1;
176 }
177
178 if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_MSS)) {
179 Tcb->SndMss = (UINT16)MAX (64, Opt->Mss);
180
181 RcvMss = TcpGetRcvMss (Tcb->Sk);
182 if (Tcb->SndMss > RcvMss) {
183 Tcb->SndMss = RcvMss;
184 }
185 } else {
186 //
187 // One end doesn't support MSS option, use default.
188 //
189 Tcb->RcvMss = 536;
190 }
191
192 Tcb->CWnd = Tcb->SndMss;
193
194 Tcb->Irs = Seg->Seq;
195 Tcb->RcvNxt = Tcb->Irs + 1;
196
197 Tcb->RcvWl2 = Tcb->RcvNxt;
198
199 if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_WS) && !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS)) {
200 Tcb->SndWndScale = Opt->WndScale;
201
202 Tcb->RcvWndScale = TcpComputeScale (Tcb);
203 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS);
204 } else {
205 //
206 // One end doesn't support window scale option. use zero.
207 //
208 Tcb->RcvWndScale = 0;
209 }
210
211 if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_TS) && !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS)) {
212 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_TS);
213 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS);
214
215 Tcb->TsRecent = Opt->TSVal;
216
217 //
218 // Compute the effective SndMss per RFC1122
219 // section 4.2.2.6. If timestamp option is
220 // enabled, it will always occupy 12 bytes.
221 //
222 Tcb->SndMss -= TCP_OPTION_TS_ALIGNED_LEN;
223 }
224}
225
238BOOLEAN
240 IN EFI_IP_ADDRESS *Ip1,
241 IN EFI_IP_ADDRESS *Ip2,
242 IN UINT8 Version
243 )
244{
245 ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6));
246
247 if (Version == IP_VERSION_4) {
248 return (BOOLEAN)(Ip1->Addr[0] == Ip2->Addr[0]);
249 } else {
250 return (BOOLEAN)EFI_IP6_EQUAL (&Ip1->v6, &Ip2->v6);
251 }
252}
253
265BOOLEAN
267 IN EFI_IP_ADDRESS *Ip,
268 IN UINT8 Version
269 )
270{
271 ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6));
272
273 if (Version == IP_VERSION_4) {
274 return (BOOLEAN)(Ip->Addr[0] == 0);
275 } else {
276 return (BOOLEAN)((Ip->Addr[0] == 0) && (Ip->Addr[1] == 0) &&
277 (Ip->Addr[2] == 0) && (Ip->Addr[3] == 0));
278 }
279}
280
293TCP_CB *
295 IN TCP_PEER *Local,
296 IN TCP_PEER *Remote,
297 IN UINT8 Version
298 )
299{
300 LIST_ENTRY *Entry;
301 TCP_CB *Node;
302 TCP_CB *Match;
303 INTN Last;
304 INTN Cur;
305
306 Last = 4;
307 Match = NULL;
308
309 NET_LIST_FOR_EACH (Entry, &mTcpListenQue) {
310 Node = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
311
312 if ((Version != Node->Sk->IpVersion) ||
313 (Local->Port != Node->LocalEnd.Port) ||
314 !TCP_PEER_MATCH (Remote, &Node->RemoteEnd, Version) ||
315 !TCP_PEER_MATCH (Local, &Node->LocalEnd, Version)
316 )
317 {
318 continue;
319 }
320
321 //
322 // Compute the number of wildcard
323 //
324 Cur = 0;
325 if (TcpIsIpZero (&Node->RemoteEnd.Ip, Version)) {
326 Cur++;
327 }
328
329 if (Node->RemoteEnd.Port == 0) {
330 Cur++;
331 }
332
333 if (TcpIsIpZero (&Node->LocalEnd.Ip, Version)) {
334 Cur++;
335 }
336
337 if (Cur < Last) {
338 if (Cur == 0) {
339 return Node;
340 }
341
342 Last = Cur;
343 Match = Node;
344 }
345 }
346
347 return Match;
348}
349
363BOOLEAN
365 IN EFI_IP_ADDRESS *Addr,
366 IN TCP_PORTNO Port,
367 IN UINT8 Version
368 )
369{
370 TCP_PORTNO LocalPort;
371 LIST_ENTRY *Entry;
372 TCP_CB *Tcb;
373
374 ASSERT ((Addr != NULL) && (Port != 0));
375
376 LocalPort = HTONS (Port);
377
378 NET_LIST_FOR_EACH (Entry, &mTcpListenQue) {
379 Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
380
381 if ((Version == Tcb->Sk->IpVersion) &&
382 TcpIsIpEqual (Addr, &Tcb->LocalEnd.Ip, Version) &&
383 (LocalPort == Tcb->LocalEnd.Port)
384 )
385 {
386 return TRUE;
387 }
388 }
389
390 NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {
391 Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
392
393 if ((Version == Tcb->Sk->IpVersion) &&
394 TcpIsIpEqual (Addr, &Tcb->LocalEnd.Ip, Version) &&
395 (LocalPort == Tcb->LocalEnd.Port)
396 )
397 {
398 return TRUE;
399 }
400 }
401
402 return FALSE;
403}
404
419TCP_CB *
421 IN TCP_PORTNO LocalPort,
422 IN EFI_IP_ADDRESS *LocalIp,
423 IN TCP_PORTNO RemotePort,
424 IN EFI_IP_ADDRESS *RemoteIp,
425 IN UINT8 Version,
426 IN BOOLEAN Syn
427 )
428{
429 TCP_PEER Local;
430 TCP_PEER Remote;
431 LIST_ENTRY *Entry;
432 TCP_CB *Tcb;
433
434 Local.Port = LocalPort;
435 Remote.Port = RemotePort;
436
437 CopyMem (&Local.Ip, LocalIp, sizeof (EFI_IP_ADDRESS));
438 CopyMem (&Remote.Ip, RemoteIp, sizeof (EFI_IP_ADDRESS));
439
440 //
441 // First check for exact match.
442 //
443 NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {
444 Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
445
446 if ((Version == Tcb->Sk->IpVersion) &&
447 TCP_PEER_EQUAL (&Remote, &Tcb->RemoteEnd, Version) &&
448 TCP_PEER_EQUAL (&Local, &Tcb->LocalEnd, Version)
449 )
450 {
451 RemoveEntryList (&Tcb->List);
452 InsertHeadList (&mTcpRunQue, &Tcb->List);
453
454 return Tcb;
455 }
456 }
457
458 //
459 // Only check the listen queue when the SYN flag is on.
460 //
461 if (Syn) {
462 return TcpLocateListenTcb (&Local, &Remote, Version);
463 }
464
465 return NULL;
466}
467
477INTN
479 IN TCP_CB *Tcb
480 )
481{
482 LIST_ENTRY *Entry;
483 LIST_ENTRY *Head;
484 TCP_CB *Node;
485
486 ASSERT (
487 (Tcb != NULL) &&
488 (
489 (Tcb->State == TCP_LISTEN) ||
490 (Tcb->State == TCP_SYN_SENT) ||
491 (Tcb->State == TCP_SYN_RCVD) ||
492 (Tcb->State == TCP_CLOSED)
493 )
494 );
495
496 if (Tcb->LocalEnd.Port == 0) {
497 return -1;
498 }
499
500 Head = &mTcpRunQue;
501
502 if (Tcb->State == TCP_LISTEN) {
503 Head = &mTcpListenQue;
504 }
505
506 //
507 // Check that the Tcb isn't already on the list.
508 //
509 NET_LIST_FOR_EACH (Entry, Head) {
510 Node = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
511
512 if (TCP_PEER_EQUAL (&Tcb->LocalEnd, &Node->LocalEnd, Tcb->Sk->IpVersion) &&
513 TCP_PEER_EQUAL (&Tcb->RemoteEnd, &Node->RemoteEnd, Tcb->Sk->IpVersion)
514 )
515 {
516 return -1;
517 }
518 }
519
520 InsertHeadList (Head, &Tcb->List);
521
522 return 0;
523}
524
533TCP_CB *
535 IN TCP_CB *Tcb
536 )
537{
538 TCP_CB *Clone;
539
540 Clone = AllocateZeroPool (sizeof (TCP_CB));
541
542 if (Clone == NULL) {
543 return NULL;
544 }
545
546 CopyMem (Clone, Tcb, sizeof (TCP_CB));
547
548 //
549 // Increase the reference count of the shared IpInfo.
550 //
551 NET_GET_REF (Tcb->IpInfo);
552
553 InitializeListHead (&Clone->List);
554 InitializeListHead (&Clone->SndQue);
555 InitializeListHead (&Clone->RcvQue);
556
557 Clone->Sk = SockClone (Tcb->Sk);
558 if (Clone->Sk == NULL) {
559 DEBUG ((DEBUG_ERROR, "TcpCloneTcb: failed to clone a sock\n"));
560 FreePool (Clone);
561 return NULL;
562 }
563
564 ((TCP_PROTO_DATA *)(Clone->Sk->ProtoReserved))->TcpPcb = Clone;
565
566 return Clone;
567}
568
606 IN UINT8 *LocalIp,
607 IN UINTN LocalIpSize,
608 IN UINT16 LocalPort,
609 IN UINT8 *RemoteIp,
610 IN UINTN RemoteIpSize,
611 IN UINT16 RemotePort,
612 OUT TCP_SEQNO *Isn
613 )
614{
615 EFI_STATUS Status;
616 EFI_HASH2_PROTOCOL *Hash2Protocol;
617 EFI_HASH2_OUTPUT HashResult;
618 ISN_HASH_CTX IsnHashCtx;
619 EFI_TIME TimeStamp;
620
621 //
622 // Check that the ISN pointer is valid
623 //
624 if (Isn == NULL) {
625 return EFI_INVALID_PARAMETER;
626 }
627
628 //
629 // The local ip may be a v4 or v6 address and may not be NULL
630 //
631 if ((LocalIp == NULL) || (LocalIpSize == 0) || (RemoteIp == NULL) || (RemoteIpSize == 0)) {
632 return EFI_INVALID_PARAMETER;
633 }
634
635 //
636 // the local ip may be a v4 or v6 address
637 //
638 if ((LocalIpSize != sizeof (EFI_IPv4_ADDRESS)) && (LocalIpSize != sizeof (EFI_IPv6_ADDRESS))) {
639 return EFI_INVALID_PARAMETER;
640 }
641
642 //
643 // Locate the Hash Protocol
644 //
645 Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2Protocol);
646 if (EFI_ERROR (Status)) {
647 DEBUG ((DEBUG_NET, "Failed to locate Hash Protocol: %r\n", Status));
648
649 //
650 // TcpCreateService(..) is expected to be called prior to this function
651 //
652 ASSERT_EFI_ERROR (Status);
653 return Status;
654 }
655
656 //
657 // Initialize the hash algorithm
658 //
659 Status = Hash2Protocol->HashInit (Hash2Protocol, &gEfiHashAlgorithmSha256Guid);
660 if (EFI_ERROR (Status)) {
661 DEBUG ((DEBUG_NET, "Failed to initialize sha256 hash algorithm: %r\n", Status));
662 return Status;
663 }
664
665 IsnHashCtx.LocalPort = LocalPort;
666 IsnHashCtx.RemotePort = RemotePort;
667 IsnHashCtx.Secret = mTcpGlobalSecret;
668
669 //
670 // Check the IP address family and copy accordingly
671 //
672 if (LocalIpSize == sizeof (EFI_IPv4_ADDRESS)) {
673 CopyMem (&IsnHashCtx.LocalAddress.IPv4, LocalIp, LocalIpSize);
674 } else if (LocalIpSize == sizeof (EFI_IPv6_ADDRESS)) {
675 CopyMem (&IsnHashCtx.LocalAddress.IPv6, LocalIp, LocalIpSize);
676 } else {
677 return EFI_INVALID_PARAMETER; // Unsupported address size
678 }
679
680 //
681 // Repeat the process for the remote IP address
682 //
683 if (RemoteIpSize == sizeof (EFI_IPv4_ADDRESS)) {
684 CopyMem (&IsnHashCtx.RemoteAddress.IPv4, RemoteIp, RemoteIpSize);
685 } else if (RemoteIpSize == sizeof (EFI_IPv6_ADDRESS)) {
686 CopyMem (&IsnHashCtx.RemoteAddress.IPv6, RemoteIp, RemoteIpSize);
687 } else {
688 return EFI_INVALID_PARAMETER; // Unsupported address size
689 }
690
691 //
692 // Compute the hash
693 // Update the hash with the data
694 //
695 Status = Hash2Protocol->HashUpdate (Hash2Protocol, (UINT8 *)&IsnHashCtx, sizeof (IsnHashCtx));
696 if (EFI_ERROR (Status)) {
697 DEBUG ((DEBUG_NET, "Failed to update hash: %r\n", Status));
698 return Status;
699 }
700
701 //
702 // Finalize the hash and retrieve the result
703 //
704 Status = Hash2Protocol->HashFinal (Hash2Protocol, &HashResult);
705 if (EFI_ERROR (Status)) {
706 DEBUG ((DEBUG_NET, "Failed to finalize hash: %r\n", Status));
707 return Status;
708 }
709
710 Status = gRT->GetTime (&TimeStamp, NULL);
711 if (EFI_ERROR (Status)) {
712 return Status;
713 }
714
715 //
716 // copy the first 4 bytes of the hash result into the ISN
717 //
718 CopyMem (Isn, HashResult.Md5Hash, sizeof (*Isn));
719
720 //
721 // now add the timestamp to the ISN as 4 microseconds units (1000 / 4 = 250)
722 //
723 *Isn += (TCP_SEQNO)TimeStamp.Nanosecond * 250;
724
725 return Status;
726}
727
736UINT16
738 IN SOCKET *Sock
739 )
740{
741 EFI_IP4_MODE_DATA Ip4Mode;
742 EFI_IP6_MODE_DATA Ip6Mode;
743 EFI_IP4_PROTOCOL *Ip4;
744 EFI_IP6_PROTOCOL *Ip6;
745 TCP_PROTO_DATA *TcpProto;
746
747 ASSERT (Sock != NULL);
748
749 ZeroMem (&Ip4Mode, sizeof (EFI_IP4_MODE_DATA));
750 ZeroMem (&Ip6Mode, sizeof (EFI_IP6_MODE_DATA));
751
752 TcpProto = (TCP_PROTO_DATA *)Sock->ProtoReserved;
753
754 if (Sock->IpVersion == IP_VERSION_4) {
755 Ip4 = TcpProto->TcpService->IpIo->Ip.Ip4;
756 ASSERT (Ip4 != NULL);
757 Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL);
758
759 return (UINT16)(Ip4Mode.MaxPacketSize - sizeof (TCP_HEAD));
760 } else {
761 Ip6 = TcpProto->TcpService->IpIo->Ip.Ip6;
762 ASSERT (Ip6 != NULL);
763 if (!EFI_ERROR (Ip6->GetModeData (Ip6, &Ip6Mode, NULL, NULL))) {
764 if (Ip6Mode.AddressList != NULL) {
765 FreePool (Ip6Mode.AddressList);
766 }
767
768 if (Ip6Mode.GroupTable != NULL) {
769 FreePool (Ip6Mode.GroupTable);
770 }
771
772 if (Ip6Mode.RouteTable != NULL) {
773 FreePool (Ip6Mode.RouteTable);
774 }
775
776 if (Ip6Mode.NeighborCache != NULL) {
777 FreePool (Ip6Mode.NeighborCache);
778 }
779
780 if (Ip6Mode.PrefixTable != NULL) {
781 FreePool (Ip6Mode.PrefixTable);
782 }
783
784 if (Ip6Mode.IcmpTypeList != NULL) {
785 FreePool (Ip6Mode.IcmpTypeList);
786 }
787 }
788
789 return (UINT16)(Ip6Mode.MaxPacketSize - sizeof (TCP_HEAD));
790 }
791}
792
800VOID
802 IN TCP_CB *Tcb,
803 IN UINT8 State
804 )
805{
806 ASSERT (Tcb->State < (sizeof (mTcpStateName) / sizeof (CHAR16 *)));
807 ASSERT (State < (sizeof (mTcpStateName) / sizeof (CHAR16 *)));
808
809 DEBUG (
810 (DEBUG_NET,
811 "Tcb (%p) state %s --> %s\n",
812 Tcb,
813 mTcpStateName[Tcb->State],
814 mTcpStateName[State])
815 );
816
817 Tcb->State = State;
818
819 switch (State) {
820 case TCP_ESTABLISHED:
821
822 SockConnEstablished (Tcb->Sk);
823
824 if (Tcb->Parent != NULL) {
825 //
826 // A new connection is accepted by a listening socket. Install
827 // the device path.
828 //
829 TcpInstallDevicePath (Tcb->Sk);
830 }
831
832 break;
833
834 case TCP_CLOSED:
835
836 SockConnClosed (Tcb->Sk);
837
838 break;
839 default:
840 break;
841 }
842}
843
853UINT16
855 IN NET_BUF *Nbuf,
856 IN UINT16 HeadSum
857 )
858{
859 UINT16 Checksum;
860
861 Checksum = NetbufChecksum (Nbuf);
862 Checksum = NetAddChecksum (Checksum, HeadSum);
863
864 Checksum = NetAddChecksum (
865 Checksum,
866 HTONS ((UINT16)Nbuf->TotalSize)
867 );
868
869 return (UINT16)(~Checksum);
870}
871
882TCP_SEG *
884 IN TCP_CB *Tcb,
885 IN OUT NET_BUF *Nbuf
886 )
887{
888 TCP_SEG *Seg;
889 TCP_HEAD *Head;
890
891 Seg = TCPSEG_NETBUF (Nbuf);
892 Head = (TCP_HEAD *)NetbufGetByte (Nbuf, 0, NULL);
893 ASSERT (Head != NULL);
894
895 Nbuf->Tcp = Head;
896
897 Seg->Seq = NTOHL (Head->Seq);
898 Seg->Ack = NTOHL (Head->Ack);
899 Seg->End = Seg->Seq + (Nbuf->TotalSize - (Head->HeadLen << 2));
900
901 Seg->Urg = NTOHS (Head->Urg);
902 Seg->Wnd = (NTOHS (Head->Wnd) << Tcb->SndWndScale);
903 Seg->Flag = Head->Flag;
904
905 //
906 // SYN and FIN flag occupy one sequence space each.
907 //
908 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
909 //
910 // RFC requires that the initial window not be scaled.
911 //
912 Seg->Wnd = NTOHS (Head->Wnd);
913 Seg->End++;
914 }
915
916 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
917 Seg->End++;
918 }
919
920 return Seg;
921}
922
935 IN OUT TCP_CB *Tcb
936 )
937{
938 EFI_STATUS Status;
939
940 Status = TcpInitTcbLocal (Tcb);
941 if (EFI_ERROR (Status)) {
942 return Status;
943 }
944
945 TcpSetState (Tcb, TCP_SYN_SENT);
946
947 TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);
948 TcpToSendData (Tcb, 1);
949
950 return EFI_SUCCESS;
951}
952
960VOID
962 IN OUT TCP_CB *Tcb
963 )
964{
965 ASSERT (Tcb != NULL);
966
967 if (!IsListEmpty (&Tcb->RcvQue) || (GET_RCV_DATASIZE (Tcb->Sk) != 0)) {
968 DEBUG (
969 (DEBUG_WARN,
970 "TcpOnAppClose: connection reset because data is lost for TCB %p\n",
971 Tcb)
972 );
973
974 TcpResetConnection (Tcb);
975 TcpClose (Tcb);
976 return;
977 }
978
979 switch (Tcb->State) {
980 case TCP_CLOSED:
981 case TCP_LISTEN:
982 case TCP_SYN_SENT:
983 TcpSetState (Tcb, TCP_CLOSED);
984 break;
985
986 case TCP_SYN_RCVD:
987 case TCP_ESTABLISHED:
988 TcpSetState (Tcb, TCP_FIN_WAIT_1);
989 break;
990
991 case TCP_CLOSE_WAIT:
992 TcpSetState (Tcb, TCP_LAST_ACK);
993 break;
994 default:
995 break;
996 }
997
998 TcpToSendData (Tcb, 1);
999}
1000
1011INTN
1013 IN OUT TCP_CB *Tcb
1014 )
1015{
1016 switch (Tcb->State) {
1017 case TCP_CLOSED:
1018 return -1;
1019
1020 case TCP_LISTEN:
1021 return -1;
1022
1023 case TCP_SYN_SENT:
1024 case TCP_SYN_RCVD:
1025 return 0;
1026
1027 case TCP_ESTABLISHED:
1028 case TCP_CLOSE_WAIT:
1029 TcpToSendData (Tcb, 0);
1030 return 0;
1031
1032 case TCP_FIN_WAIT_1:
1033 case TCP_FIN_WAIT_2:
1034 case TCP_CLOSING:
1035 case TCP_LAST_ACK:
1036 case TCP_TIME_WAIT:
1037 return -1;
1038
1039 default:
1040 break;
1041 }
1042
1043 return 0;
1044}
1045
1053VOID
1055 IN TCP_CB *Tcb
1056 )
1057{
1058 UINT32 TcpOld;
1059
1060 switch (Tcb->State) {
1061 case TCP_ESTABLISHED:
1062 TcpOld = TcpRcvWinOld (Tcb);
1063 if (TcpRcvWinNow (Tcb) > TcpOld) {
1064 if (TcpOld < Tcb->RcvMss) {
1065 DEBUG (
1066 (DEBUG_NET,
1067 "TcpOnAppConsume: send a window update for a window closed Tcb %p\n",
1068 Tcb)
1069 );
1070
1071 TcpSendAck (Tcb);
1072 } else if (Tcb->DelayedAck == 0) {
1073 DEBUG (
1074 (DEBUG_NET,
1075 "TcpOnAppConsume: scheduled a delayed ACK to update window for Tcb %p\n",
1076 Tcb)
1077 );
1078
1079 Tcb->DelayedAck = 1;
1080 }
1081 }
1082
1083 break;
1084
1085 default:
1086 break;
1087 }
1088}
1089
1097VOID
1099 IN TCP_CB *Tcb
1100 )
1101{
1102 DEBUG (
1103 (DEBUG_WARN,
1104 "TcpOnAppAbort: connection reset issued by application for TCB %p\n",
1105 Tcb)
1106 );
1107
1108 switch (Tcb->State) {
1109 case TCP_SYN_RCVD:
1110 case TCP_ESTABLISHED:
1111 case TCP_FIN_WAIT_1:
1112 case TCP_FIN_WAIT_2:
1113 case TCP_CLOSE_WAIT:
1114 TcpResetConnection (Tcb);
1115 break;
1116 default:
1117 break;
1118 }
1119
1120 TcpSetState (Tcb, TCP_CLOSED);
1121}
1122
1129VOID
1131 IN TCP_CB *Tcb
1132 )
1133{
1134 NET_BUF *Nbuf;
1135 TCP_HEAD *Nhead;
1136
1137 Nbuf = NetbufAlloc (TCP_MAX_HEAD);
1138
1139 if (Nbuf == NULL) {
1140 return;
1141 }
1142
1143 Nhead = (TCP_HEAD *)NetbufAllocSpace (
1144 Nbuf,
1145 sizeof (TCP_HEAD),
1146 NET_BUF_TAIL
1147 );
1148
1149 ASSERT (Nhead != NULL);
1150
1151 Nbuf->Tcp = Nhead;
1152
1153 Nhead->Flag = TCP_FLG_RST;
1154 Nhead->Seq = HTONL (Tcb->SndNxt);
1155 Nhead->Ack = HTONL (Tcb->RcvNxt);
1156 Nhead->SrcPort = Tcb->LocalEnd.Port;
1157 Nhead->DstPort = Tcb->RemoteEnd.Port;
1158 Nhead->HeadLen = (UINT8)(sizeof (TCP_HEAD) >> 2);
1159 Nhead->Res = 0;
1160 Nhead->Wnd = HTONS (0xFFFF);
1161 Nhead->Checksum = 0;
1162 Nhead->Urg = 0;
1163 Nhead->Checksum = TcpChecksum (Nbuf, Tcb->HeadSum);
1164
1165 TcpSendIpPacket (Tcb, Nbuf, &Tcb->LocalEnd.Ip, &Tcb->RemoteEnd.Ip, Tcb->Sk->IpVersion);
1166
1167 NetbufFree (Nbuf);
1168}
1169
1181 IN SOCKET *Sock
1182 )
1183{
1184 TCP_PROTO_DATA *TcpProto;
1185 TCP_SERVICE_DATA *TcpService;
1186 TCP_CB *Tcb;
1187 IPv4_DEVICE_PATH Ip4DPathNode;
1188 IPv6_DEVICE_PATH Ip6DPathNode;
1189 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
1190 EFI_STATUS Status;
1191 TCP_PORTNO LocalPort;
1192 TCP_PORTNO RemotePort;
1193
1194 TcpProto = (TCP_PROTO_DATA *)Sock->ProtoReserved;
1195 TcpService = TcpProto->TcpService;
1196 Tcb = TcpProto->TcpPcb;
1197
1198 LocalPort = NTOHS (Tcb->LocalEnd.Port);
1199 RemotePort = NTOHS (Tcb->RemoteEnd.Port);
1200 if (Sock->IpVersion == IP_VERSION_4) {
1202 &Ip4DPathNode,
1203 TcpService->ControllerHandle,
1204 Tcb->LocalEnd.Ip.Addr[0],
1205 LocalPort,
1206 Tcb->RemoteEnd.Ip.Addr[0],
1207 RemotePort,
1208 EFI_IP_PROTO_TCP,
1209 Tcb->UseDefaultAddr
1210 );
1211
1212 IP4_COPY_ADDRESS (&Ip4DPathNode.SubnetMask, &Tcb->SubnetMask);
1213
1214 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&Ip4DPathNode;
1215 } else {
1217 &Ip6DPathNode,
1218 TcpService->ControllerHandle,
1219 &Tcb->LocalEnd.Ip.v6,
1220 LocalPort,
1221 &Tcb->RemoteEnd.Ip.v6,
1222 RemotePort,
1223 EFI_IP_PROTO_TCP
1224 );
1225
1226 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&Ip6DPathNode;
1227 }
1228
1229 Sock->DevicePath = AppendDevicePathNode (Sock->ParentDevicePath, DevicePath);
1230 if (Sock->DevicePath == NULL) {
1231 return EFI_OUT_OF_RESOURCES;
1232 }
1233
1234 Status = gBS->InstallProtocolInterface (
1235 &Sock->SockHandle,
1236 &gEfiDevicePathProtocolGuid,
1238 Sock->DevicePath
1239 );
1240 if (EFI_ERROR (Status)) {
1241 FreePool (Sock->DevicePath);
1242 Sock->DevicePath = NULL;
1243 }
1244
1245 return Status;
1246}
UINT64 UINTN
INT64 INTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI AppendDevicePathNode(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define MAX(a, b)
Definition: Base.h:992
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID EFIAPI NetbufFree(IN NET_BUF *Nbuf)
Definition: NetBuffer.c:195
UINT16 EFIAPI NetIp6PseudoHeadChecksum(IN EFI_IPv6_ADDRESS *Src, IN EFI_IPv6_ADDRESS *Dst, IN UINT8 NextHeader, IN UINT32 Len)
Definition: NetBuffer.c:1777
UINT16 EFIAPI NetbufChecksum(IN NET_BUF *Nbuf)
Definition: NetBuffer.c:1687
VOID EFIAPI NetLibCreateIPv6DPathNode(IN OUT IPv6_DEVICE_PATH *Node, IN EFI_HANDLE Controller, IN EFI_IPv6_ADDRESS *LocalIp, IN UINT16 LocalPort, IN EFI_IPv6_ADDRESS *RemoteIp, IN UINT16 RemotePort, IN UINT16 Protocol)
Definition: DxeNetLib.c:2965
UINT16 EFIAPI NetAddChecksum(IN UINT16 Checksum1, IN UINT16 Checksum2)
Definition: NetBuffer.c:1658
NET_BUF *EFIAPI NetbufAlloc(IN UINT32 Len)
Definition: NetBuffer.c:89
VOID EFIAPI NetLibCreateIPv4DPathNode(IN OUT IPv4_DEVICE_PATH *Node, IN EFI_HANDLE Controller, IN IP4_ADDR LocalIp, IN UINT16 LocalPort, IN IP4_ADDR RemoteIp, IN UINT16 RemotePort, IN UINT16 Protocol, IN BOOLEAN UseDefaultAddress)
Definition: DxeNetLib.c:2903
UINT8 *EFIAPI NetbufAllocSpace(IN OUT NET_BUF *Nbuf, IN UINT32 Len, IN BOOLEAN FromHead)
Definition: NetBuffer.c:1015
UINT16 EFIAPI NetPseudoHeadChecksum(IN IP4_ADDR Src, IN IP4_ADDR Dst, IN UINT8 Proto, IN UINT16 Len)
Definition: NetBuffer.c:1740
UINT8 *EFIAPI NetbufGetByte(IN NET_BUF *Nbuf, IN UINT32 Offset, OUT UINT32 *Index OPTIONAL)
Definition: NetBuffer.c:359
#define GET_RCV_DATASIZE(Sock)
Definition: Socket.h:255
SOCKET * SockClone(IN SOCKET *Sock)
Definition: SockImpl.c:937
#define GET_RCV_BUFFSIZE(Sock)
Definition: Socket.h:245
VOID SockConnClosed(IN OUT SOCKET *Sock)
Definition: SockImpl.c:1011
VOID SockConnEstablished(IN OUT SOCKET *Sock)
Definition: SockImpl.c:985
STATIC BOOLEAN Match(IN CONST CHAR16 *Translated, IN UINTN TranslatedLength, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
VOID TcpClose(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:96
INTN TcpToSendData(IN OUT TCP_CB *Tcb, IN INTN Force)
Definition: TcpOutput.c:776
UINT32 TcpRcvWinNow(IN TCP_CB *Tcb)
Definition: TcpOutput.c:62
VOID TcpSetTimer(IN OUT TCP_CB *Tcb, IN UINT16 Timer, IN UINT32 TimeOut)
Definition: TcpTimer.c:364
UINT32 TcpRcvWinOld(IN TCP_CB *Tcb)
Definition: TcpOutput.c:35
INTN TcpSendIpPacket(IN TCP_CB *Tcb, IN NET_BUF *Nbuf, IN EFI_IP_ADDRESS *Src, IN EFI_IP_ADDRESS *Dest, IN UINT8 Version)
Definition: TcpIo.c:62
VOID TcpSendAck(IN OUT TCP_CB *Tcb)
Definition: TcpOutput.c:967
BOOLEAN TcpIsIpEqual(IN EFI_IP_ADDRESS *Ip1, IN EFI_IP_ADDRESS *Ip2, IN UINT8 Version)
Definition: TcpMisc.c:239
INTN TcpOnAppSend(IN OUT TCP_CB *Tcb)
Definition: TcpMisc.c:1012
EFI_STATUS TcpInitTcbLocal(IN OUT TCP_CB *Tcb)
Definition: TcpMisc.c:76
INTN TcpInsertTcb(IN TCP_CB *Tcb)
Definition: TcpMisc.c:478
VOID TcpOnAppConsume(IN TCP_CB *Tcb)
Definition: TcpMisc.c:1054
EFI_STATUS TcpOnAppConnect(IN OUT TCP_CB *Tcb)
Definition: TcpMisc.c:934
VOID TcpOnAppClose(IN OUT TCP_CB *Tcb)
Definition: TcpMisc.c:961
BOOLEAN TcpFindTcbByPeer(IN EFI_IP_ADDRESS *Addr, IN TCP_PORTNO Port, IN UINT8 Version)
Definition: TcpMisc.c:364
VOID TcpSetState(IN TCP_CB *Tcb, IN UINT8 State)
Definition: TcpMisc.c:801
EFI_STATUS TcpGetIsn(IN UINT8 *LocalIp, IN UINTN LocalIpSize, IN UINT16 LocalPort, IN UINT8 *RemoteIp, IN UINTN RemoteIpSize, IN UINT16 RemotePort, OUT TCP_SEQNO *Isn)
Definition: TcpMisc.c:605
TCP_CB * TcpLocateTcb(IN TCP_PORTNO LocalPort, IN EFI_IP_ADDRESS *LocalIp, IN TCP_PORTNO RemotePort, IN EFI_IP_ADDRESS *RemoteIp, IN UINT8 Version, IN BOOLEAN Syn)
Definition: TcpMisc.c:420
VOID TcpOnAppAbort(IN TCP_CB *Tcb)
Definition: TcpMisc.c:1098
TCP_CB * TcpLocateListenTcb(IN TCP_PEER *Local, IN TCP_PEER *Remote, IN UINT8 Version)
Definition: TcpMisc.c:294
VOID TcpResetConnection(IN TCP_CB *Tcb)
Definition: TcpMisc.c:1130
EFI_STATUS TcpInstallDevicePath(IN SOCKET *Sock)
Definition: TcpMisc.c:1180
TCP_CB * TcpCloneTcb(IN TCP_CB *Tcb)
Definition: TcpMisc.c:534
TCP_SEG * TcpFormatNetbuf(IN TCP_CB *Tcb, IN OUT NET_BUF *Nbuf)
Definition: TcpMisc.c:883
VOID TcpInitTcbPeer(IN OUT TCP_CB *Tcb, IN TCP_SEG *Seg, IN TCP_OPTION *Opt)
Definition: TcpMisc.c:157
UINT16 TcpGetRcvMss(IN SOCKET *Sock)
Definition: TcpMisc.c:737
BOOLEAN TcpIsIpZero(IN EFI_IP_ADDRESS *Ip, IN UINT8 Version)
Definition: TcpMisc.c:266
UINT16 TcpChecksum(IN NET_BUF *Nbuf, IN UINT16 HeadSum)
Definition: TcpMisc.c:854
UINT8 TcpComputeScale(IN TCP_CB *Tcb)
Definition: TcpOption.c:76
#define TCP_OPTION_TS_ALIGNED_LEN
Length of timestamp option, aligned.
Definition: TcpOption.h:25
#define TCP_TIMER_CONNECT
Connection establishment timer.
Definition: TcpProto.h:77
#define TCP_CTRL_RCVD_WS
Received a wnd scale option in syn.
Definition: TcpProto.h:61
#define TCP_CTRL_SND_TS
Send Timestamp option to remote.
Definition: TcpProto.h:64
#define TCP_CTRL_RCVD_TS
Received a Timestamp option in syn.
Definition: TcpProto.h:63
#define TCP_CLOSED
Definition: TcpProto.h:17
#define TCP_CTRL_NO_WS
Disable window scale option.
Definition: TcpProto.h:60
#define TCP_FLG_FIN
Definition: TcpProto.h:32
#define TCP_CTRL_NO_TS
Disable Timestamp option.
Definition: TcpProto.h:62
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ EFI_NATIVE_INTERFACE
Definition: UefiSpec.h:1193
TCP_PEER RemoteEnd
Remote endpoint.
Definition: TcpProto.h:238
LIST_ENTRY RcvQue
Reassemble queue.
Definition: TcpProto.h:241
SOCKET * Sk
The socket it controlled.
Definition: TcpProto.h:236
TCP_PEER LocalEnd
Local endpoint.
Definition: TcpProto.h:237
LIST_ENTRY List
Back and forward link entry.
Definition: TcpProto.h:233
LIST_ENTRY SndQue
Retxmission queue.
Definition: TcpProto.h:240
EFI_IP_ADDRESS Ip
IP address, in network byte order.
Definition: TcpProto.h:223
TCP_PORTNO Port
Port number, in network byte order.
Definition: TcpProto.h:224
TCP_SEQNO Seq
Starting sequence number.
Definition: TcpProto.h:211
TCP_SEQNO End
The sequence of the last byte + 1, include SYN/FIN. End-Seq = SEG.LEN.
Definition: TcpProto.h:212
UINT8 Flag
TCP header flags.
Definition: TcpProto.h:214
UINT16 Urg
Valid if URG flag is set.
Definition: TcpProto.h:215
TCP_SEQNO Ack
ACK field in the segment.
Definition: TcpProto.h:213
UINT32 Wnd
TCP window size field.
Definition: TcpProto.h:216
UINT8 ProtoReserved[PROTO_RESERVED_LEN]
Data fields reserved for protocol.
Definition: Socket.h:497
UINT32 MaxPacketSize
Definition: Ip4.h:149
UINT32 MaxPacketSize
Definition: Ip6.h:315
EFI_IP6_NEIGHBOR_CACHE * NeighborCache
Definition: Ip6.h:366
EFI_IP6_ICMP_TYPE * IcmpTypeList
Definition: Ip6.h:386
EFI_IP6_ADDRESS_INFO * AddressList
Definition: Ip6.h:336
EFI_IP6_ROUTE_TABLE * RouteTable
Definition: Ip6.h:356
EFI_IPv6_ADDRESS * GroupTable
Definition: Ip6.h:347
EFI_IP6_ADDRESS_INFO * PrefixTable
Definition: Ip6.h:376
EFI_IPv4_ADDRESS SubnetMask
Definition: DevicePath.h:601