]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c
f8b535cf6e7f0ad125a1647bf22e063daca7ff1e
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / SockInterface.c
1 /** @file
2 Interface function of the Socket.
3
4 Copyright (c) 2005 - 2017, 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 "SockImpl.h"
17
18
19 /**
20 Check whether the Event is in the List.
21
22 @param List Pointer to the token list to be searched.
23 @param Event The event to be checked.
24
25 @retval TRUE The specific Event exists in the List.
26 @retval FALSE The specific Event is not in the List.
27
28 **/
29 BOOLEAN
30 SockTokenExistedInList (
31 IN LIST_ENTRY *List,
32 IN EFI_EVENT Event
33 )
34 {
35 LIST_ENTRY *ListEntry;
36 SOCK_TOKEN *SockToken;
37
38 NET_LIST_FOR_EACH (ListEntry, List) {
39 SockToken = NET_LIST_USER_STRUCT (
40 ListEntry,
41 SOCK_TOKEN,
42 TokenList
43 );
44
45 if (Event == SockToken->Token->Event) {
46 return TRUE;
47 }
48 }
49
50 return FALSE;
51 }
52
53
54 /**
55 Call SockTokenExistedInList() to check whether the Event is
56 in the related socket's lists.
57
58 @param Sock Pointer to the instance's socket.
59 @param Event The event to be checked.
60
61 @retval TRUE The Event exists in related socket's lists.
62 @retval FALSE The Event is not in related socket's lists.
63
64 **/
65 BOOLEAN
66 SockTokenExisted (
67 IN SOCKET *Sock,
68 IN EFI_EVENT Event
69 )
70 {
71
72 if (SockTokenExistedInList (&Sock->SndTokenList, Event) ||
73 SockTokenExistedInList (&Sock->ProcessingSndTokenList, Event) ||
74 SockTokenExistedInList (&Sock->RcvTokenList, Event) ||
75 SockTokenExistedInList (&Sock->ListenTokenList, Event)) {
76
77 return TRUE;
78 }
79
80 if ((Sock->ConnectionToken != NULL) &&
81 (Sock->ConnectionToken->Event == Event)) {
82
83 return TRUE;
84 }
85
86 if ((Sock->CloseToken != NULL) && (Sock->CloseToken->Event == Event)) {
87 return TRUE;
88 }
89
90 return FALSE;
91 }
92
93
94 /**
95 Buffer a token into the specific list of socket Sock.
96
97 @param Sock Pointer to the instance's socket.
98 @param List Pointer to the list to store the token.
99 @param Token Pointer to the token to be buffered.
100 @param DataLen The data length of the buffer contained in Token.
101
102 @return Pointer to the token that wraps Token. If NULL, error condition occurred.
103
104 **/
105 SOCK_TOKEN *
106 SockBufferToken (
107 IN SOCKET *Sock,
108 IN LIST_ENTRY *List,
109 IN VOID *Token,
110 IN UINT32 DataLen
111 )
112 {
113 SOCK_TOKEN *SockToken;
114
115 SockToken = AllocatePool (sizeof (SOCK_TOKEN));
116 if (NULL == SockToken) {
117
118 DEBUG ((EFI_D_ERROR, "SockBufferIOToken: No Memory "
119 "to allocate SockToken\n"));
120
121 return NULL;
122 }
123
124 SockToken->Sock = Sock;
125 SockToken->Token = (SOCK_COMPLETION_TOKEN *) Token;
126 SockToken->RemainDataLen = DataLen;
127 InsertTailList (List, &SockToken->TokenList);
128
129 return SockToken;
130 }
131
132
133 /**
134 Destroy the socket Sock and its associated protocol control block.
135
136 @param Sock The socket to be destroyed.
137
138 @retval EFI_SUCCESS The socket Sock is destroyed successfully.
139 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
140
141 **/
142 EFI_STATUS
143 SockDestroyChild (
144 IN SOCKET *Sock
145 )
146 {
147 EFI_STATUS Status;
148 TCP4_PROTO_DATA *ProtoData;
149 TCP_CB *Tcb;
150 VOID *SockProtocol;
151
152 ASSERT ((Sock != NULL) && (Sock->ProtoHandler != NULL));
153
154 if (Sock->InDestroy) {
155 return EFI_SUCCESS;
156 }
157
158 Sock->InDestroy = TRUE;
159
160 ProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
161 Tcb = ProtoData->TcpPcb;
162
163 ASSERT (Tcb != NULL);
164
165 Status = EfiAcquireLockOrFail (&(Sock->Lock));
166 if (EFI_ERROR (Status)) {
167
168 DEBUG ((EFI_D_ERROR, "SockDestroyChild: Get the lock to "
169 "access socket failed with %r\n", Status));
170
171 return EFI_ACCESS_DENIED;
172 }
173
174 //
175 // Close the IP protocol.
176 //
177 gBS->CloseProtocol (
178 Tcb->IpInfo->ChildHandle,
179 &gEfiIp4ProtocolGuid,
180 ProtoData->TcpService->IpIo->Image,
181 Sock->SockHandle
182 );
183
184 if (Sock->DestroyCallback != NULL) {
185 Sock->DestroyCallback (Sock, Sock->Context);
186 }
187
188 //
189 // Retrieve the protocol installed on this sock
190 //
191 Status = gBS->OpenProtocol (
192 Sock->SockHandle,
193 &gEfiTcp4ProtocolGuid,
194 &SockProtocol,
195 Sock->DriverBinding,
196 Sock->SockHandle,
197 EFI_OPEN_PROTOCOL_GET_PROTOCOL
198 );
199
200 if (EFI_ERROR (Status)) {
201
202 DEBUG ((EFI_D_ERROR, "SockDestroyChild: Open protocol installed "
203 "on socket failed with %r\n", Status));
204 }
205
206 //
207 // Uninstall the protocol installed on this sock
208 // in the light of Sock->SockType
209 //
210 gBS->UninstallMultipleProtocolInterfaces (
211 Sock->SockHandle,
212 &gEfiTcp4ProtocolGuid,
213 SockProtocol,
214 NULL
215 );
216
217 //
218 // force protocol layer to detach the PCB
219 //
220 Status = Sock->ProtoHandler (Sock, SOCK_DETACH, NULL);
221
222 if (EFI_ERROR (Status)) {
223
224 DEBUG ((EFI_D_ERROR, "SockDestroyChild: Protocol detach socket"
225 " failed with %r\n", Status));
226
227 Sock->InDestroy = FALSE;
228 } else if (SOCK_IS_CONFIGURED (Sock)) {
229
230 SockConnFlush (Sock);
231 SockSetState (Sock, SO_CLOSED);
232
233 Sock->ConfigureState = SO_UNCONFIGURED;
234 }
235
236 EfiReleaseLock (&(Sock->Lock));
237
238 if (EFI_ERROR (Status)) {
239 return Status;
240 }
241
242 SockDestroy (Sock);
243 return EFI_SUCCESS;
244 }
245
246
247 /**
248 Create a socket and its associated protocol control block
249 with the intial data SockInitData and protocol specific
250 data ProtoData.
251
252 @param SockInitData Inital data to setting the socket.
253
254 @return Pointer to the newly created socket. If NULL, error condition occured.
255
256 **/
257 SOCKET *
258 SockCreateChild (
259 IN SOCK_INIT_DATA *SockInitData
260 )
261 {
262 SOCKET *Sock;
263 VOID *SockProtocol;
264 EFI_STATUS Status;
265
266 //
267 // create a new socket
268 //
269 Sock = SockCreate (SockInitData);
270 if (NULL == Sock) {
271
272 DEBUG ((EFI_D_ERROR, "SockCreateChild: No resource to "
273 "create a new socket\n"));
274
275 return NULL;
276 }
277
278 Status = EfiAcquireLockOrFail (&(Sock->Lock));
279 if (EFI_ERROR (Status)) {
280
281 DEBUG ((EFI_D_ERROR, "SockCreateChild: Get the lock to "
282 "access socket failed with %r\n", Status));
283
284 goto ERROR;
285 }
286 //
287 // inform the protocol layer to attach the socket
288 // with a new protocol control block
289 //
290 Status = Sock->ProtoHandler (Sock, SOCK_ATTACH, NULL);
291 EfiReleaseLock (&(Sock->Lock));
292 if (EFI_ERROR (Status)) {
293
294 DEBUG ((EFI_D_ERROR, "SockCreateChild: Protocol failed to"
295 " attach a socket with %r\n", Status));
296
297 goto ERROR;
298 }
299
300 return Sock;
301
302 ERROR:
303
304 if (Sock->DestroyCallback != NULL) {
305 Sock->DestroyCallback (Sock, Sock->Context);
306 }
307
308 gBS->OpenProtocol (
309 Sock->SockHandle,
310 &gEfiTcp4ProtocolGuid,
311 &SockProtocol,
312 Sock->DriverBinding,
313 Sock->SockHandle,
314 EFI_OPEN_PROTOCOL_GET_PROTOCOL
315 );
316 //
317 // Uninstall the protocol installed on this sock
318 //
319 gBS->UninstallMultipleProtocolInterfaces (
320 Sock->SockHandle,
321 &gEfiTcp4ProtocolGuid,
322 SockProtocol,
323 NULL
324 );
325 SockDestroy (Sock);
326 return NULL;
327 }
328
329
330 /**
331 Configure the specific socket Sock using configuration data ConfigData.
332
333 @param Sock Pointer to the socket to be configured.
334 @param ConfigData Pointer to the configuration data.
335
336 @retval EFI_SUCCESS The socket is configured successfully.
337 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the
338 socket is already configured.
339
340 **/
341 EFI_STATUS
342 SockConfigure (
343 IN SOCKET *Sock,
344 IN VOID *ConfigData
345 )
346 {
347 EFI_STATUS Status;
348
349 Status = EfiAcquireLockOrFail (&(Sock->Lock));
350 if (EFI_ERROR (Status)) {
351
352 DEBUG ((EFI_D_ERROR, "SockConfigure: Get the access for "
353 "socket failed with %r", Status));
354
355 return EFI_ACCESS_DENIED;
356 }
357
358 if (SOCK_IS_CONFIGURED (Sock)) {
359 Status = EFI_ACCESS_DENIED;
360 goto OnExit;
361 }
362
363 ASSERT (Sock->State == SO_CLOSED);
364
365 Status = Sock->ProtoHandler (Sock, SOCK_CONFIGURE, ConfigData);
366
367 OnExit:
368 EfiReleaseLock (&(Sock->Lock));
369
370 return Status;
371 }
372
373
374 /**
375 Initiate a connection establishment process.
376
377 @param Sock Pointer to the socket to initiate the initate the
378 connection.
379 @param Token Pointer to the token used for the connection
380 operation.
381
382 @retval EFI_SUCCESS The connection is initialized successfully.
383 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
384 socket is closed, or the socket is not configured to
385 be an active one, or the token is already in one of
386 this socket's lists.
387 @retval EFI_NO_MAPPING The IP address configuration operation is not
388 finished.
389 @retval EFI_NOT_STARTED The socket is not configured.
390
391 **/
392 EFI_STATUS
393 SockConnect (
394 IN SOCKET *Sock,
395 IN VOID *Token
396 )
397 {
398 EFI_STATUS Status;
399 EFI_EVENT Event;
400
401 Status = EfiAcquireLockOrFail (&(Sock->Lock));
402 if (EFI_ERROR (Status)) {
403
404 DEBUG ((EFI_D_ERROR, "SockConnect: Get the access for "
405 "socket failed with %r", Status));
406
407 return EFI_ACCESS_DENIED;
408 }
409
410 if (SOCK_IS_NO_MAPPING (Sock)) {
411 Status = EFI_NO_MAPPING;
412 goto OnExit;
413 }
414
415 if (SOCK_IS_UNCONFIGURED (Sock)) {
416
417 Status = EFI_NOT_STARTED;
418 goto OnExit;
419 }
420
421 if (!SOCK_IS_CLOSED (Sock) || !SOCK_IS_CONFIGURED_ACTIVE (Sock)) {
422
423 Status = EFI_ACCESS_DENIED;
424 goto OnExit;
425 }
426
427 Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
428
429 if (SockTokenExisted (Sock, Event)) {
430
431 Status = EFI_ACCESS_DENIED;
432 goto OnExit;
433 }
434
435 Sock->ConnectionToken = (SOCK_COMPLETION_TOKEN *) Token;
436 SockSetState (Sock, SO_CONNECTING);
437 Status = Sock->ProtoHandler (Sock, SOCK_CONNECT, NULL);
438
439 OnExit:
440 EfiReleaseLock (&(Sock->Lock));
441 return Status;
442 }
443
444
445 /**
446 Issue a listen token to get an existed connected network instance
447 or wait for a connection if there is none.
448
449 @param Sock Pointer to the socket to accept connections.
450 @param Token The token to accept a connection.
451
452 @retval EFI_SUCCESS Either a connection is accpeted or the Token is
453 buffered for further acception.
454 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
455 socket is closed, or the socket is not configured to
456 be a passive one, or the token is already in one of
457 this socket's lists.
458 @retval EFI_NO_MAPPING The IP address configuration operation is not
459 finished.
460 @retval EFI_NOT_STARTED The socket is not configured.
461 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
462
463 **/
464 EFI_STATUS
465 SockAccept (
466 IN SOCKET *Sock,
467 IN VOID *Token
468 )
469 {
470 EFI_TCP4_LISTEN_TOKEN *ListenToken;
471 LIST_ENTRY *ListEntry;
472 EFI_STATUS Status;
473 SOCKET *Socket;
474 EFI_EVENT Event;
475
476 ASSERT (SockStream == Sock->Type);
477
478 Status = EfiAcquireLockOrFail (&(Sock->Lock));
479 if (EFI_ERROR (Status)) {
480
481 DEBUG ((EFI_D_ERROR, "SockAccept: Get the access for socket"
482 " failed with %r", Status));
483
484 return EFI_ACCESS_DENIED;
485 }
486
487 if (SOCK_IS_NO_MAPPING (Sock)) {
488 Status = EFI_NO_MAPPING;
489 goto Exit;
490 }
491
492 if (SOCK_IS_UNCONFIGURED (Sock)) {
493
494 Status = EFI_NOT_STARTED;
495 goto Exit;
496 }
497
498 if (!SOCK_IS_LISTENING (Sock)) {
499
500 Status = EFI_ACCESS_DENIED;
501 goto Exit;
502 }
503
504 Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
505
506 if (SockTokenExisted (Sock, Event)) {
507
508 Status = EFI_ACCESS_DENIED;
509 goto Exit;
510 }
511
512 ListenToken = (EFI_TCP4_LISTEN_TOKEN *) Token;
513
514 //
515 // Check if a connection has already in this Sock->ConnectionList
516 //
517 NET_LIST_FOR_EACH (ListEntry, &Sock->ConnectionList) {
518
519 Socket = NET_LIST_USER_STRUCT (ListEntry, SOCKET, ConnectionList);
520
521 if (SOCK_IS_CONNECTED (Socket)) {
522 ListenToken->NewChildHandle = Socket->SockHandle;
523 SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);
524
525 RemoveEntryList (ListEntry);
526
527 ASSERT (Socket->Parent != NULL);
528
529 Socket->Parent->ConnCnt--;
530
531 DEBUG (
532 (EFI_D_NET,
533 "SockAccept: Accept a socket, now conncount is %d",
534 Socket->Parent->ConnCnt)
535 );
536 Socket->Parent = NULL;
537
538 goto Exit;
539 }
540 }
541
542 //
543 // Buffer this token for latter incoming connection request
544 //
545 if (NULL == SockBufferToken (Sock, &(Sock->ListenTokenList), Token, 0)) {
546
547 Status = EFI_OUT_OF_RESOURCES;
548 }
549
550 Exit:
551 EfiReleaseLock (&(Sock->Lock));
552
553 return Status;
554 }
555
556
557 /**
558 Issue a token with data to the socket to send out.
559
560 @param Sock Pointer to the socket to process the token with
561 data.
562 @param Token The token with data that needs to send out.
563
564 @retval EFI_SUCCESS The token is processed successfully.
565 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
566 socket is closed, or the socket is not in a
567 synchronized state , or the token is already in one
568 of this socket's lists.
569 @retval EFI_NO_MAPPING The IP address configuration operation is not
570 finished.
571 @retval EFI_NOT_STARTED The socket is not configured.
572 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
573
574 **/
575 EFI_STATUS
576 SockSend (
577 IN SOCKET *Sock,
578 IN VOID *Token
579 )
580 {
581 SOCK_IO_TOKEN *SndToken;
582 EFI_EVENT Event;
583 UINT32 FreeSpace;
584 EFI_TCP4_TRANSMIT_DATA *TxData;
585 EFI_STATUS Status;
586 SOCK_TOKEN *SockToken;
587 UINT32 DataLen;
588
589 ASSERT (SockStream == Sock->Type);
590
591 Status = EfiAcquireLockOrFail (&(Sock->Lock));
592 if (EFI_ERROR (Status)) {
593
594 DEBUG ((EFI_D_ERROR, "SockSend: Get the access for socket"
595 " failed with %r", Status));
596
597 return EFI_ACCESS_DENIED;
598 }
599
600 if (SOCK_IS_NO_MAPPING (Sock)) {
601 Status = EFI_NO_MAPPING;
602 goto Exit;
603 }
604
605 SndToken = (SOCK_IO_TOKEN *) Token;
606 TxData = (EFI_TCP4_TRANSMIT_DATA *) SndToken->Packet.TxData;
607
608 if (SOCK_IS_UNCONFIGURED (Sock)) {
609 Status = EFI_NOT_STARTED;
610 goto Exit;
611 }
612
613 if (!(SOCK_IS_CONNECTING (Sock) || SOCK_IS_CONNECTED (Sock))) {
614
615 Status = EFI_ACCESS_DENIED;
616 goto Exit;
617 }
618
619 //
620 // check if a token is already in the token buffer
621 //
622 Event = SndToken->Token.Event;
623
624 if (SockTokenExisted (Sock, Event)) {
625 Status = EFI_ACCESS_DENIED;
626 goto Exit;
627 }
628
629 DataLen = (UINT32) TxData->DataLength;
630
631 //
632 // process this sending token now or buffer it only?
633 //
634 FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);
635
636 if ((FreeSpace < Sock->SndBuffer.LowWater) || !SOCK_IS_CONNECTED (Sock)) {
637
638 SockToken = SockBufferToken (
639 Sock,
640 &Sock->SndTokenList,
641 SndToken,
642 DataLen
643 );
644
645 if (NULL == SockToken) {
646 Status = EFI_OUT_OF_RESOURCES;
647 }
648 } else {
649
650 SockToken = SockBufferToken (
651 Sock,
652 &Sock->ProcessingSndTokenList,
653 SndToken,
654 DataLen
655 );
656
657 if (NULL == SockToken) {
658 DEBUG ((EFI_D_ERROR, "SockSend: Failed to buffer IO token into"
659 " socket processing SndToken List\n", Status));
660
661 Status = EFI_OUT_OF_RESOURCES;
662 goto Exit;
663 }
664
665 Status = SockProcessTcpSndData (Sock, TxData);
666
667 if (EFI_ERROR (Status)) {
668 DEBUG ((EFI_D_ERROR, "SockSend: Failed to process "
669 "Snd Data\n", Status));
670
671 RemoveEntryList (&(SockToken->TokenList));
672 FreePool (SockToken);
673 }
674 }
675
676 Exit:
677 EfiReleaseLock (&(Sock->Lock));
678 return Status;
679 }
680
681
682 /**
683 Issue a token to get data from the socket.
684
685 @param Sock Pointer to the socket to get data from.
686 @param Token The token to store the received data from the
687 socket.
688
689 @retval EFI_SUCCESS The token is processed successfully.
690 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
691 socket is closed, or the socket is not in a
692 synchronized state , or the token is already in one
693 of this socket's lists.
694 @retval EFI_NO_MAPPING The IP address configuration operation is not
695 finished.
696 @retval EFI_NOT_STARTED The socket is not configured.
697 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
698 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
699
700 **/
701 EFI_STATUS
702 SockRcv (
703 IN SOCKET *Sock,
704 IN VOID *Token
705 )
706 {
707 SOCK_IO_TOKEN *RcvToken;
708 UINT32 RcvdBytes;
709 EFI_STATUS Status;
710 EFI_EVENT Event;
711
712 ASSERT (SockStream == Sock->Type);
713
714 Status = EfiAcquireLockOrFail (&(Sock->Lock));
715 if (EFI_ERROR (Status)) {
716
717 DEBUG ((EFI_D_ERROR, "SockRcv: Get the access for socket"
718 " failed with %r", Status));
719
720 return EFI_ACCESS_DENIED;
721 }
722
723 if (SOCK_IS_NO_MAPPING (Sock)) {
724
725 Status = EFI_NO_MAPPING;
726 goto Exit;
727 }
728
729 if (SOCK_IS_UNCONFIGURED (Sock)) {
730
731 Status = EFI_NOT_STARTED;
732 goto Exit;
733 }
734
735 if (!(SOCK_IS_CONNECTED (Sock) || SOCK_IS_CONNECTING (Sock))) {
736
737 Status = EFI_ACCESS_DENIED;
738 goto Exit;
739 }
740
741 RcvToken = (SOCK_IO_TOKEN *) Token;
742
743 //
744 // check if a token is already in the token buffer of this socket
745 //
746 Event = RcvToken->Token.Event;
747 if (SockTokenExisted (Sock, Event)) {
748 Status = EFI_ACCESS_DENIED;
749 goto Exit;
750 }
751
752 RcvToken = (SOCK_IO_TOKEN *) Token;
753 RcvdBytes = GET_RCV_DATASIZE (Sock);
754
755 //
756 // check whether an error has happened before
757 //
758 if (EFI_ABORTED != Sock->SockError) {
759
760 SIGNAL_TOKEN (&(RcvToken->Token), Sock->SockError);
761 Sock->SockError = EFI_ABORTED;
762 goto Exit;
763 }
764
765 //
766 // check whether can not receive and there is no any
767 // data buffered in Sock->RcvBuffer
768 //
769 if (SOCK_IS_NO_MORE_DATA (Sock) && (0 == RcvdBytes)) {
770
771 Status = EFI_CONNECTION_FIN;
772 goto Exit;
773 }
774
775 if (RcvdBytes != 0) {
776 SockProcessRcvToken (Sock, RcvToken);
777
778 Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);
779 } else {
780
781 if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {
782 Status = EFI_OUT_OF_RESOURCES;
783 }
784 }
785
786 Exit:
787 EfiReleaseLock (&(Sock->Lock));
788 return Status;
789 }
790
791
792 /**
793 Reset the socket and its associated protocol control block.
794
795 @param Sock Pointer to the socket to be flushed.
796
797 @retval EFI_SUCCESS The socket is flushed successfully.
798 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
799
800 **/
801 EFI_STATUS
802 SockFlush (
803 IN SOCKET *Sock
804 )
805 {
806 EFI_STATUS Status;
807
808 ASSERT (SockStream == Sock->Type);
809
810 Status = EfiAcquireLockOrFail (&(Sock->Lock));
811 if (EFI_ERROR (Status)) {
812
813 DEBUG ((EFI_D_ERROR, "SockFlush: Get the access for socket"
814 " failed with %r", Status));
815
816 return EFI_ACCESS_DENIED;
817 }
818
819 if (!SOCK_IS_CONFIGURED (Sock)) {
820 goto Exit;
821 }
822
823 Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);
824 if (EFI_ERROR (Status)) {
825
826 DEBUG ((EFI_D_ERROR, "SockFlush: Protocol failed handling"
827 " SOCK_FLUSH with %r", Status));
828
829 goto Exit;
830 }
831
832 SOCK_ERROR (Sock, EFI_ABORTED);
833 SockConnFlush (Sock);
834 SockSetState (Sock, SO_CLOSED);
835
836 Sock->ConfigureState = SO_UNCONFIGURED;
837
838 Exit:
839 EfiReleaseLock (&(Sock->Lock));
840 return Status;
841 }
842
843
844 /**
845 Close or abort the socket associated connection.
846
847 @param Sock Pointer to the socket of the connection to close or
848 abort.
849 @param Token The token for close operation.
850 @param OnAbort TRUE for aborting the connection, FALSE to close it.
851
852 @retval EFI_SUCCESS The close or abort operation is initialized
853 successfully.
854 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
855 socket is closed, or the socket is not in a
856 synchronized state , or the token is already in one
857 of this socket's lists.
858 @retval EFI_NO_MAPPING The IP address configuration operation is not
859 finished.
860 @retval EFI_NOT_STARTED The socket is not configured.
861
862 **/
863 EFI_STATUS
864 SockClose (
865 IN SOCKET *Sock,
866 IN VOID *Token,
867 IN BOOLEAN OnAbort
868 )
869 {
870 EFI_STATUS Status;
871 EFI_EVENT Event;
872
873 ASSERT (SockStream == Sock->Type);
874
875 Status = EfiAcquireLockOrFail (&(Sock->Lock));
876 if (EFI_ERROR (Status)) {
877 DEBUG ((EFI_D_ERROR, "SockClose: Get the access for socket"
878 " failed with %r", Status));
879
880 return EFI_ACCESS_DENIED;
881 }
882
883 if (SOCK_IS_NO_MAPPING (Sock)) {
884 Status = EFI_NO_MAPPING;
885 goto Exit;
886 }
887
888 if (SOCK_IS_UNCONFIGURED (Sock)) {
889 Status = EFI_NOT_STARTED;
890 goto Exit;
891 }
892
893 if (SOCK_IS_DISCONNECTING (Sock)) {
894 Status = EFI_ACCESS_DENIED;
895 goto Exit;
896 }
897
898 Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
899
900 if (SockTokenExisted (Sock, Event)) {
901 Status = EFI_ACCESS_DENIED;
902 goto Exit;
903 }
904
905 Sock->CloseToken = Token;
906 SockSetState (Sock, SO_DISCONNECTING);
907
908 if (OnAbort) {
909 Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);
910 } else {
911 Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);
912 }
913
914 Exit:
915 EfiReleaseLock (&(Sock->Lock));
916 return Status;
917 }
918
919
920 /**
921 Get the mode data of the low layer protocol.
922
923 @param Sock Pointer to the socket to get mode data from.
924 @param Mode Pointer to the data to store the low layer mode
925 information.
926
927 @retval EFI_SUCCESS The mode data is got successfully.
928 @retval EFI_NOT_STARTED The socket is not configured.
929
930 **/
931 EFI_STATUS
932 SockGetMode (
933 IN SOCKET *Sock,
934 IN OUT VOID *Mode
935 )
936 {
937 return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);
938 }
939
940
941 /**
942 Configure the low level protocol to join a multicast group for
943 this socket's connection.
944
945 @param Sock Pointer to the socket of the connection to join the
946 specific multicast group.
947 @param GroupInfo Pointer to the multicast group info.
948
949 @retval EFI_SUCCESS The configuration is done successfully.
950 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
951 @retval EFI_NOT_STARTED The socket is not configured.
952
953 **/
954 EFI_STATUS
955 SockGroup (
956 IN SOCKET *Sock,
957 IN VOID *GroupInfo
958 )
959 {
960 EFI_STATUS Status;
961
962 Status = EfiAcquireLockOrFail (&(Sock->Lock));
963
964 if (EFI_ERROR (Status)) {
965
966 DEBUG ((EFI_D_ERROR, "SockGroup: Get the access for socket"
967 " failed with %r", Status));
968
969 return EFI_ACCESS_DENIED;
970 }
971
972 if (SOCK_IS_UNCONFIGURED (Sock)) {
973 Status = EFI_NOT_STARTED;
974 goto Exit;
975 }
976
977 Status = Sock->ProtoHandler (Sock, SOCK_GROUP, GroupInfo);
978
979 Exit:
980 EfiReleaseLock (&(Sock->Lock));
981 return Status;
982 }
983
984
985 /**
986 Add or remove route information in IP route table associated
987 with this socket.
988
989 @param Sock Pointer to the socket associated with the IP route
990 table to operate on.
991 @param RouteInfo Pointer to the route information to be processed.
992
993 @retval EFI_SUCCESS The route table is updated successfully.
994 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
995 @retval EFI_NO_MAPPING The IP address configuration operation is not
996 finished.
997 @retval EFI_NOT_STARTED The socket is not configured.
998
999 **/
1000 EFI_STATUS
1001 SockRoute (
1002 IN SOCKET *Sock,
1003 IN VOID *RouteInfo
1004 )
1005 {
1006 EFI_STATUS Status;
1007
1008 Status = EfiAcquireLockOrFail (&(Sock->Lock));
1009 if (EFI_ERROR (Status)) {
1010 DEBUG ((EFI_D_ERROR, "SockRoute: Get the access for socket"
1011 " failed with %r", Status));
1012
1013 return EFI_ACCESS_DENIED;
1014 }
1015
1016 if (SOCK_IS_NO_MAPPING (Sock)) {
1017 Status = EFI_NO_MAPPING;
1018 goto Exit;
1019 }
1020
1021 if (SOCK_IS_UNCONFIGURED (Sock)) {
1022 Status = EFI_NOT_STARTED;
1023 goto Exit;
1024 }
1025
1026 Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);
1027
1028 Exit:
1029 EfiReleaseLock (&(Sock->Lock));
1030 return Status;
1031 }