Signed-off-by: lpleahy git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14123 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			302 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			302 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Implement the socket API.
 | |
| 
 | |
|   Copyright (c) 2011, Intel Corporation
 | |
|   All rights reserved. This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include <SocketInternals.h>
 | |
| 
 | |
| 
 | |
| /**
 | |
|   File system interface for the socket layer.
 | |
| 
 | |
|   This data structure defines the routines for the various
 | |
|   file system functions associated with the socket layer.
 | |
| **/
 | |
| const struct fileops SocketOperations = {
 | |
|   BslSocketClose,     //  close
 | |
|   BslSocketRead,      //  read
 | |
|   BslSocketWrite,     //  write
 | |
| 
 | |
|   //
 | |
|   //  Not supported
 | |
|   //
 | |
|   fnullop_fcntl,      //  fcntl
 | |
|   BslSocketPoll,      //  poll
 | |
|   fnullop_flush,      //  flush
 | |
| 
 | |
|   fbadop_stat,        //  stat
 | |
|   fbadop_ioctl,       //  ioctl
 | |
|   fbadop_delete,      //  delete
 | |
|   fbadop_rmdir,       //  rmdir
 | |
|   fbadop_mkdir,       //  mkdir
 | |
|   fbadop_rename,      //  rename
 | |
| 
 | |
|   NULL                //  lseek
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Translate from the socket file descriptor to the socket protocol.
 | |
| 
 | |
|   @param [in] s             Socket file descriptor returned from ::socket.
 | |
| 
 | |
|   @param [in] ppDescriptor  Address to receive the descriptor structure
 | |
|                             address for the file
 | |
|   @param [in] pErrno        Address of the errno variable
 | |
| 
 | |
|   @return   A pointer to the EFI_SOCKET_PROTOCOL structure or NULL if
 | |
|             an invalid file descriptor was passed in.
 | |
| 
 | |
|  **/
 | |
| EFI_SOCKET_PROTOCOL *
 | |
| BslFdToSocketProtocol (
 | |
|   int s,
 | |
|   struct __filedes ** ppDescriptor,
 | |
|   int * pErrno
 | |
|   )
 | |
| {
 | |
|   struct __filedes * pDescriptor;
 | |
|   EFI_SOCKET_PROTOCOL * pSocketProtocol;
 | |
| 
 | |
|   //
 | |
|   //  Assume failure
 | |
|   //
 | |
|   pSocketProtocol = NULL;
 | |
| 
 | |
|   //
 | |
|   //  Validate the file descriptor
 | |
|   //
 | |
|   if ( !ValidateFD ( s, TRUE )) {
 | |
|     //
 | |
|     //  Bad file descriptor
 | |
|     //
 | |
|     *pErrno = EBADF;
 | |
|   }
 | |
|   else {
 | |
|     //
 | |
|     //  Get the descriptor for the file
 | |
|     //
 | |
|     pDescriptor = &gMD->fdarray[ s ];
 | |
| 
 | |
|     //
 | |
|     //  Validate that the descriptor is associated with sockets
 | |
|     //
 | |
|     pSocketProtocol = BslValidateSocketFd ( pDescriptor, pErrno );
 | |
|     if (( NULL != ppDescriptor ) && ( NULL != pSocketProtocol )) {
 | |
|       *ppDescriptor = pDescriptor;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the socket protocol
 | |
|   //
 | |
|   return pSocketProtocol;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Build a file descriptor for a socket.
 | |
| 
 | |
|   @param [in] pSocketProtocol   Socket protocol structure address
 | |
| 
 | |
|   @param [in] pErrno            Address of the errno variable
 | |
| 
 | |
|   @return  The file descriptor for the socket or -1 if an error occurs.
 | |
| 
 | |
|  **/
 | |
| int
 | |
| BslSocketProtocolToFd (
 | |
|   IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
 | |
|   IN int * pErrno
 | |
|   )
 | |
| {
 | |
|   int FileDescriptor;
 | |
|   struct __filedes * pDescriptor;
 | |
| 
 | |
|   //
 | |
|   //  Assume failure
 | |
|   //
 | |
|   FileDescriptor = -1;
 | |
| 
 | |
|   //
 | |
|   //  Locate a file descriptor
 | |
|   //
 | |
|   FileDescriptor = FindFreeFD ( VALID_CLOSED );
 | |
|   if ( FileDescriptor < 0 ) {
 | |
|     //
 | |
|     // All available FDs are in use
 | |
|     //
 | |
|     errno = EMFILE;
 | |
|   }
 | |
|   else {
 | |
|     //
 | |
|     //  Initialize the file descriptor
 | |
|     //
 | |
|     pDescriptor = &gMD->fdarray[ FileDescriptor ];
 | |
|     pDescriptor->f_offset = 0;
 | |
|     pDescriptor->f_flag = 0;
 | |
|     pDescriptor->f_iflags = DTYPE_SOCKET;
 | |
|     pDescriptor->MyFD = (UINT16)FileDescriptor;
 | |
|     pDescriptor->Oflags = O_RDWR;
 | |
|     pDescriptor->Omode = S_ACC_READ | S_ACC_WRITE;
 | |
|     pDescriptor->RefCount = 1;
 | |
|     FILE_SET_MATURE ( pDescriptor );
 | |
| 
 | |
|     //
 | |
|     //  Socket specific file descriptor initialization
 | |
|     //
 | |
|     pDescriptor->devdata = pSocketProtocol;
 | |
|     pDescriptor->f_ops = &SocketOperations;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the socket's file descriptor
 | |
|   //
 | |
|   return FileDescriptor;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Creates an endpoint for network communication.
 | |
| 
 | |
|   The socket routine initializes the communication endpoint and returns a
 | |
|   file descriptor.
 | |
| 
 | |
|   The
 | |
|   <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html">POSIX</a>
 | |
|   documentation is available online.
 | |
| 
 | |
|   @param [in] domain    Select the family of protocols for the client or server
 | |
|                         application.  The supported values are:
 | |
|                         <ul>
 | |
|                           <li>AF_INET - Version 4 UEFI network stack</li>
 | |
|                         </ul>
 | |
| 
 | |
|   @param [in] type      Specifies how to make the network connection.  The following values
 | |
|                         are supported:
 | |
|                         <ul>
 | |
|                           <li>
 | |
|                             SOCK_DGRAM - Connect to UDP, provides a datagram service that is
 | |
|                             manipulated by recvfrom and sendto.
 | |
|                           </li>
 | |
|                           <li>
 | |
|                             SOCK_STREAM - Connect to TCP, provides a byte stream
 | |
|                             that is manipluated by read, recv, send and write.
 | |
|                           </li>
 | |
|                           <li>
 | |
|                             SOCK_RAW - Connect to IP, provides a datagram service that
 | |
|                             is manipulated by recvfrom and sendto.
 | |
|                           </li>
 | |
|                         </ul>
 | |
| 
 | |
|   @param [in] protocol  Specifies the lower layer protocol to use.  The following
 | |
|                         values are supported:
 | |
|                         <ul>
 | |
|                           <li>IPPROTO_TCP</li> - This value must be combined with SOCK_STREAM.</li>
 | |
|                           <li>IPPROTO_UDP</li> - This value must be combined with SOCK_DGRAM.</li>
 | |
|                           <li>0 - 254</li> - An assigned
 | |
|                             <a href="http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml">protocol number</a>
 | |
|                             is combined with SOCK_RAW.
 | |
|                           </li>
 | |
|                         </ul>
 | |
| 
 | |
|   @return  This routine returns a file descriptor for the socket.  If an error
 | |
|            occurs -1 is returned and ::errno contains more details.
 | |
| 
 | |
|  **/
 | |
| INT32
 | |
| socket (
 | |
|   IN INT32 domain,
 | |
|   IN INT32 type,
 | |
|   IN INT32 protocol
 | |
|   )
 | |
| {
 | |
|   INT32 FileDescriptor;
 | |
|   EFI_SOCKET_PROTOCOL * pSocketProtocol;
 | |
|   EFI_STATUS Status;
 | |
| 
 | |
|   //
 | |
|   //  Assume failure
 | |
|   //
 | |
|   FileDescriptor = -1;
 | |
| 
 | |
|   //
 | |
|   //  Locate the socket protocol
 | |
|   //
 | |
|   errno = EslServiceGetProtocol ( &pSocketProtocol );
 | |
|   if ( 0 == errno ) {
 | |
|     //
 | |
|     //  Initialize the socket
 | |
|     //
 | |
|     Status = pSocketProtocol->pfnSocket ( pSocketProtocol,
 | |
|                                           domain,
 | |
|                                           type,
 | |
|                                           protocol,
 | |
|                                           &errno );
 | |
|     if ( !EFI_ERROR ( Status )) {
 | |
|       //
 | |
|       //  Build the file descriptor for the socket
 | |
|       //
 | |
|       FileDescriptor = BslSocketProtocolToFd ( pSocketProtocol,
 | |
|                                                &errno );
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the socket's file descriptor
 | |
|   //
 | |
|   return FileDescriptor;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Validate the socket's file descriptor
 | |
| 
 | |
|   @param [in] pDescriptor Descriptor for the file
 | |
| 
 | |
|   @param [in] pErrno      Address of the errno variable
 | |
| 
 | |
|   @return   A pointer to the EFI_SOCKET_PROTOCOL structure or NULL if
 | |
|             an invalid file descriptor was passed in.
 | |
| 
 | |
|  **/
 | |
| EFI_SOCKET_PROTOCOL *
 | |
| BslValidateSocketFd (
 | |
|   struct __filedes * pDescriptor,
 | |
|   int * pErrno
 | |
|   )
 | |
| {
 | |
|   EFI_SOCKET_PROTOCOL * pSocketProtocol;
 | |
| 
 | |
|   //
 | |
|   //  Assume failure
 | |
|   //
 | |
|   *pErrno = ENOTSOCK;
 | |
|   pSocketProtocol = NULL;
 | |
| 
 | |
|   //
 | |
|   //  Validate that the descriptor is associated with sockets
 | |
|   //
 | |
|   if ( DTYPE_SOCKET == ( pDescriptor->f_iflags & DTYPE_MASK )) {
 | |
|     //
 | |
|     //  Locate the socket protocol
 | |
|     //
 | |
|     pSocketProtocol = pDescriptor->devdata;
 | |
|     *pErrno = 0;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the socket protocol
 | |
|   //
 | |
|   return pSocketProtocol;
 | |
| }
 |