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