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