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