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