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