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 *
BslFdToSocketProtocol(int s,struct __filedes ** ppDescriptor,int * pErrno)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
BslSocketProtocolToFd(IN EFI_SOCKET_PROTOCOL * pSocketProtocol,IN int * pErrno)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
socket(IN INT32 domain,IN INT32 type,IN INT32 protocol)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 *
BslValidateSocketFd(struct __filedes * pDescriptor,int * pErrno)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