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