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