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