Home | History | Annotate | Download | only in BsdSocketLib
      1 /** @file
      2   Implement the socket API.
      3 
      4   Copyright (c) 2011, Intel Corporation
      5   All rights reserved. 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
      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 #include <SocketInternals.h>
     16 
     17 
     18 /**
     19   File system interface for the socket layer.
     20 
     21   This data structure defines the routines for the various
     22   file system functions associated with the socket layer.
     23 **/
     24 const struct fileops SocketOperations = {
     25   BslSocketClose,     //  close
     26   BslSocketRead,      //  read
     27   BslSocketWrite,     //  write
     28 
     29   //
     30   //  Not supported
     31   //
     32   fnullop_fcntl,      //  fcntl
     33   BslSocketPoll,      //  poll
     34   fnullop_flush,      //  flush
     35 
     36   fbadop_stat,        //  stat
     37   fbadop_ioctl,       //  ioctl
     38   fbadop_delete,      //  delete
     39   fbadop_rmdir,       //  rmdir
     40   fbadop_mkdir,       //  mkdir
     41   fbadop_rename,      //  rename
     42 
     43   NULL                //  lseek
     44 };
     45 
     46 
     47 /**
     48   Translate from the socket file descriptor to the socket protocol.
     49 
     50   @param [in] s             Socket file descriptor returned from ::socket.
     51 
     52   @param [in] ppDescriptor  Address to receive the descriptor structure
     53                             address for the file
     54   @param [in] pErrno        Address of the errno variable
     55 
     56   @return   A pointer to the EFI_SOCKET_PROTOCOL structure or NULL if
     57             an invalid file descriptor was passed in.
     58 
     59  **/
     60 EFI_SOCKET_PROTOCOL *
     61 BslFdToSocketProtocol (
     62   int s,
     63   struct __filedes ** ppDescriptor,
     64   int * pErrno
     65   )
     66 {
     67   struct __filedes * pDescriptor;
     68   EFI_SOCKET_PROTOCOL * pSocketProtocol;
     69 
     70   //
     71   //  Assume failure
     72   //
     73   pSocketProtocol = NULL;
     74 
     75   //
     76   //  Validate the file descriptor
     77   //
     78   if ( !ValidateFD ( s, TRUE )) {
     79     //
     80     //  Bad file descriptor
     81     //
     82     *pErrno = EBADF;
     83   }
     84   else {
     85     //
     86     //  Get the descriptor for the file
     87     //
     88     pDescriptor = &gMD->fdarray[ s ];
     89 
     90     //
     91     //  Validate that the descriptor is associated with sockets
     92     //
     93     pSocketProtocol = BslValidateSocketFd ( pDescriptor, pErrno );
     94     if (( NULL != ppDescriptor ) && ( NULL != pSocketProtocol )) {
     95       *ppDescriptor = pDescriptor;
     96     }
     97   }
     98 
     99   //
    100   //  Return the socket protocol
    101   //
    102   return pSocketProtocol;
    103 }
    104 
    105 
    106 /**
    107   Build a file descriptor for a socket.
    108 
    109   @param [in] pSocketProtocol   Socket protocol structure address
    110 
    111   @param [in] pErrno            Address of the errno variable
    112 
    113   @return  The file descriptor for the socket or -1 if an error occurs.
    114 
    115  **/
    116 int
    117 BslSocketProtocolToFd (
    118   IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
    119   IN int * pErrno
    120   )
    121 {
    122   int FileDescriptor;
    123   struct __filedes * pDescriptor;
    124 
    125   //
    126   //  Assume failure
    127   //
    128   FileDescriptor = -1;
    129 
    130   //
    131   //  Locate a file descriptor
    132   //
    133   FileDescriptor = FindFreeFD ( VALID_CLOSED );
    134   if ( FileDescriptor < 0 ) {
    135     //
    136     // All available FDs are in use
    137     //
    138     errno = EMFILE;
    139   }
    140   else {
    141     //
    142     //  Initialize the file descriptor
    143     //
    144     pDescriptor = &gMD->fdarray[ FileDescriptor ];
    145     pDescriptor->f_offset = 0;
    146     pDescriptor->f_flag = 0;
    147     pDescriptor->f_iflags = DTYPE_SOCKET;
    148     pDescriptor->MyFD = (UINT16)FileDescriptor;
    149     pDescriptor->Oflags = O_RDWR;
    150     pDescriptor->Omode = S_ACC_READ | S_ACC_WRITE;
    151     pDescriptor->RefCount = 1;
    152     FILE_SET_MATURE ( pDescriptor );
    153 
    154     //
    155     //  Socket specific file descriptor initialization
    156     //
    157     pDescriptor->devdata = pSocketProtocol;
    158     pDescriptor->f_ops = &SocketOperations;
    159   }
    160 
    161   //
    162   //  Return the socket's file descriptor
    163   //
    164   return FileDescriptor;
    165 }
    166 
    167 
    168 /**
    169   Creates an endpoint for network communication.
    170 
    171   The socket routine initializes the communication endpoint and returns a
    172   file descriptor.
    173 
    174   The
    175   <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html">POSIX</a>
    176   documentation is available online.
    177 
    178   @param [in] domain    Select the family of protocols for the client or server
    179                         application.  The supported values are:
    180                         <ul>
    181                           <li>AF_INET - Version 4 UEFI network stack</li>
    182                         </ul>
    183 
    184   @param [in] type      Specifies how to make the network connection.  The following values
    185                         are supported:
    186                         <ul>
    187                           <li>
    188                             SOCK_DGRAM - Connect to UDP, provides a datagram service that is
    189                             manipulated by recvfrom and sendto.
    190                           </li>
    191                           <li>
    192                             SOCK_STREAM - Connect to TCP, provides a byte stream
    193                             that is manipluated by read, recv, send and write.
    194                           </li>
    195                           <li>
    196                             SOCK_RAW - Connect to IP, provides a datagram service that
    197                             is manipulated by recvfrom and sendto.
    198                           </li>
    199                         </ul>
    200 
    201   @param [in] protocol  Specifies the lower layer protocol to use.  The following
    202                         values are supported:
    203                         <ul>
    204                           <li>IPPROTO_TCP</li> - This value must be combined with SOCK_STREAM.</li>
    205                           <li>IPPROTO_UDP</li> - This value must be combined with SOCK_DGRAM.</li>
    206                           <li>0 - 254</li> - An assigned
    207                             <a href="http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml">protocol number</a>
    208                             is combined with SOCK_RAW.
    209                           </li>
    210                         </ul>
    211 
    212   @return  This routine returns a file descriptor for the socket.  If an error
    213            occurs -1 is returned and ::errno contains more details.
    214 
    215  **/
    216 INT32
    217 socket (
    218   IN INT32 domain,
    219   IN INT32 type,
    220   IN INT32 protocol
    221   )
    222 {
    223   INT32 FileDescriptor;
    224   EFI_SOCKET_PROTOCOL * pSocketProtocol;
    225   EFI_STATUS Status;
    226 
    227   //
    228   //  Assume failure
    229   //
    230   FileDescriptor = -1;
    231 
    232   //
    233   //  Locate the socket protocol
    234   //
    235   errno = EslServiceGetProtocol ( &pSocketProtocol );
    236   if ( 0 == errno ) {
    237     //
    238     //  Initialize the socket
    239     //
    240     Status = pSocketProtocol->pfnSocket ( pSocketProtocol,
    241                                           domain,
    242                                           type,
    243                                           protocol,
    244                                           &errno );
    245     if ( !EFI_ERROR ( Status )) {
    246       //
    247       //  Build the file descriptor for the socket
    248       //
    249       FileDescriptor = BslSocketProtocolToFd ( pSocketProtocol,
    250                                                &errno );
    251     }
    252   }
    253 
    254   //
    255   //  Return the socket's file descriptor
    256   //
    257   return FileDescriptor;
    258 }
    259 
    260 
    261 /**
    262   Validate the socket's file descriptor
    263 
    264   @param [in] pDescriptor Descriptor for the file
    265 
    266   @param [in] pErrno      Address of the errno variable
    267 
    268   @return   A pointer to the EFI_SOCKET_PROTOCOL structure or NULL if
    269             an invalid file descriptor was passed in.
    270 
    271  **/
    272 EFI_SOCKET_PROTOCOL *
    273 BslValidateSocketFd (
    274   struct __filedes * pDescriptor,
    275   int * pErrno
    276   )
    277 {
    278   EFI_SOCKET_PROTOCOL * pSocketProtocol;
    279 
    280   //
    281   //  Assume failure
    282   //
    283   *pErrno = ENOTSOCK;
    284   pSocketProtocol = NULL;
    285 
    286   //
    287   //  Validate that the descriptor is associated with sockets
    288   //
    289   if ( DTYPE_SOCKET == ( pDescriptor->f_iflags & DTYPE_MASK )) {
    290     //
    291     //  Locate the socket protocol
    292     //
    293     pSocketProtocol = pDescriptor->devdata;
    294     *pErrno = 0;
    295   }
    296 
    297   //
    298   //  Return the socket protocol
    299   //
    300   return pSocketProtocol;
    301 }
    302