/** @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; | |
} |