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