1 /** @file 2 Interface function of the Socket. 3 4 Copyright (c) 2009 - 2012, 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 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 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 * 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 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 * 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 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 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 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_INFO, 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 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 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 Status = SockProcessRcvToken (Sock, RcvToken); 728 729 if (EFI_ERROR (Status)) { 730 goto Exit; 731 } 732 733 Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL); 734 } else { 735 736 if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) { 737 Status = EFI_OUT_OF_RESOURCES; 738 } 739 } 740 741 Exit: 742 EfiReleaseLock (&(Sock->Lock)); 743 return Status; 744 } 745 746 /** 747 Reset the socket and its associated protocol control block. 748 749 @param[in, out] Sock Pointer to the socket to be flushed. 750 751 @retval EFI_SUCCESS The socket is flushed successfully. 752 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket. 753 754 **/ 755 EFI_STATUS 756 SockFlush ( 757 IN OUT SOCKET *Sock 758 ) 759 { 760 EFI_STATUS Status; 761 762 ASSERT (SockStream == Sock->Type); 763 764 Status = EfiAcquireLockOrFail (&(Sock->Lock)); 765 if (EFI_ERROR (Status)) { 766 767 DEBUG ( 768 (EFI_D_ERROR, 769 "SockFlush: Get the access for socket failed with %r", 770 Status) 771 ); 772 773 return EFI_ACCESS_DENIED; 774 } 775 776 if (!SOCK_IS_CONFIGURED (Sock)) { 777 778 Status = EFI_ACCESS_DENIED; 779 goto Exit; 780 } 781 782 Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL); 783 if (EFI_ERROR (Status)) { 784 785 DEBUG ( 786 (EFI_D_ERROR, 787 "SockFlush: Protocol failed handling SOCK_FLUSH with %r", 788 Status) 789 ); 790 791 goto Exit; 792 } 793 794 SOCK_ERROR (Sock, EFI_ABORTED); 795 SockConnFlush (Sock); 796 SockSetState (Sock, SO_CLOSED); 797 798 Sock->ConfigureState = SO_UNCONFIGURED; 799 800 Exit: 801 EfiReleaseLock (&(Sock->Lock)); 802 return Status; 803 } 804 805 /** 806 Close or abort the socket associated connection. 807 808 @param[in, out] Sock Pointer to the socket of the connection to close 809 or abort. 810 @param[in] Token The token for a close operation. 811 @param[in] OnAbort TRUE for aborting the connection; FALSE to close it. 812 813 @retval EFI_SUCCESS The close or abort operation initialized 814 successfully. 815 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the 816 socket is closed, or the socket is not in a 817 synchronized state , or the token is already in one 818 of this socket's lists. 819 @retval EFI_NO_MAPPING The IP address configuration operation is not 820 finished. 821 @retval EFI_NOT_STARTED The socket is not configured. 822 823 **/ 824 EFI_STATUS 825 SockClose ( 826 IN OUT SOCKET *Sock, 827 IN VOID *Token, 828 IN BOOLEAN OnAbort 829 ) 830 { 831 EFI_STATUS Status; 832 EFI_EVENT Event; 833 834 ASSERT (SockStream == Sock->Type); 835 836 Status = EfiAcquireLockOrFail (&(Sock->Lock)); 837 if (EFI_ERROR (Status)) { 838 DEBUG ( 839 (EFI_D_ERROR, 840 "SockClose: Get the access for socket failed with %r", 841 Status) 842 ); 843 844 return EFI_ACCESS_DENIED; 845 } 846 847 if (SOCK_IS_NO_MAPPING (Sock)) { 848 Status = EFI_NO_MAPPING; 849 goto Exit; 850 } 851 852 if (SOCK_IS_UNCONFIGURED (Sock)) { 853 Status = EFI_NOT_STARTED; 854 goto Exit; 855 } 856 857 if (SOCK_IS_DISCONNECTING (Sock)) { 858 Status = EFI_ACCESS_DENIED; 859 goto Exit; 860 } 861 862 Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event; 863 864 if (SockTokenExisted (Sock, Event)) { 865 Status = EFI_ACCESS_DENIED; 866 goto Exit; 867 } 868 869 Sock->CloseToken = Token; 870 SockSetState (Sock, SO_DISCONNECTING); 871 872 if (OnAbort) { 873 Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL); 874 } else { 875 Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL); 876 } 877 878 Exit: 879 EfiReleaseLock (&(Sock->Lock)); 880 return Status; 881 } 882 883 /** 884 Get the mode data of the low layer protocol. 885 886 @param[in] Sock Pointer to the socket to get mode data from. 887 @param[in, out] Mode Pointer to the data to store the low layer mode 888 information. 889 890 @retval EFI_SUCCESS The mode data was obtained successfully. 891 @retval EFI_NOT_STARTED The socket is not configured. 892 893 **/ 894 EFI_STATUS 895 SockGetMode ( 896 IN SOCKET *Sock, 897 IN OUT VOID *Mode 898 ) 899 { 900 return Sock->ProtoHandler (Sock, SOCK_MODE, Mode); 901 } 902 903 /** 904 Configure the low level protocol to join a multicast group for 905 this socket's connection. 906 907 @param[in] Sock Pointer to the socket of the connection to join the 908 specific multicast group. 909 @param[in] GroupInfo Pointer to the multicast group info. 910 911 @retval EFI_SUCCESS The configuration completed successfully. 912 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket. 913 @retval EFI_NOT_STARTED The socket is not configured. 914 915 **/ 916 EFI_STATUS 917 SockGroup ( 918 IN SOCKET *Sock, 919 IN VOID *GroupInfo 920 ) 921 { 922 EFI_STATUS Status; 923 924 Status = EfiAcquireLockOrFail (&(Sock->Lock)); 925 926 if (EFI_ERROR (Status)) { 927 928 DEBUG ( 929 (EFI_D_ERROR, 930 "SockGroup: Get the access for socket failed with %r", 931 Status) 932 ); 933 934 return EFI_ACCESS_DENIED; 935 } 936 937 if (SOCK_IS_UNCONFIGURED (Sock)) { 938 Status = EFI_NOT_STARTED; 939 goto Exit; 940 } 941 942 Status = Sock->ProtoHandler (Sock, SOCK_GROUP, GroupInfo); 943 944 Exit: 945 EfiReleaseLock (&(Sock->Lock)); 946 return Status; 947 } 948 949 /** 950 Add or remove route information in IP route table associated 951 with this socket. 952 953 @param[in] Sock Pointer to the socket associated with the IP route 954 table to operate on. 955 @param[in] RouteInfo Pointer to the route information to be processed. 956 957 @retval EFI_SUCCESS The route table updated successfully. 958 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket. 959 @retval EFI_NO_MAPPING The IP address configuration operation is not 960 finished. 961 @retval EFI_NOT_STARTED The socket is not configured. 962 963 **/ 964 EFI_STATUS 965 SockRoute ( 966 IN SOCKET *Sock, 967 IN VOID *RouteInfo 968 ) 969 { 970 EFI_STATUS Status; 971 972 Status = EfiAcquireLockOrFail (&(Sock->Lock)); 973 if (EFI_ERROR (Status)) { 974 DEBUG ( 975 (EFI_D_ERROR, 976 "SockRoute: Get the access for socket failed with %r", 977 Status) 978 ); 979 980 return EFI_ACCESS_DENIED; 981 } 982 983 if (SOCK_IS_NO_MAPPING (Sock)) { 984 Status = EFI_NO_MAPPING; 985 goto Exit; 986 } 987 988 if (SOCK_IS_UNCONFIGURED (Sock)) { 989 Status = EFI_NOT_STARTED; 990 goto Exit; 991 } 992 993 Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo); 994 995 Exit: 996 EfiReleaseLock (&(Sock->Lock)); 997 return Status; 998 } 999 1000