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