]>
Commit | Line | Data |
---|---|---|
d7ce7006 | 1 | /** @file\r |
2 | Implement the socket support for the socket layer.\r | |
3 | \r | |
4 | Socket States:\r | |
5 | * Bound - pSocket->PortList is not NULL\r | |
6 | * Listen - AcceptWait event is not NULL\r | |
7 | \r | |
8 | Copyright (c) 2011, Intel Corporation\r | |
9 | All rights reserved. This program and the accompanying materials\r | |
10 | are licensed and made available under the terms and conditions of the BSD License\r | |
11 | which accompanies this distribution. The full text of the license may be found at\r | |
12 | http://opensource.org/licenses/bsd-license.php\r | |
13 | \r | |
14 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
15 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
16 | \r | |
17 | **/\r | |
18 | \r | |
19 | #include "Socket.h"\r | |
20 | \r | |
21 | \r | |
22 | /**\r | |
23 | Socket driver connection points\r | |
24 | \r | |
25 | List the network stack connection points for the socket driver.\r | |
26 | **/\r | |
27 | CONST DT_SOCKET_BINDING cEslSocketBinding [] = {\r | |
28 | { L"Tcp4",\r | |
29 | &gEfiTcp4ServiceBindingProtocolGuid,\r | |
30 | &mEslTcp4ServiceGuid,\r | |
31 | EslTcpInitialize4,\r | |
32 | EslTcpShutdown4 },\r | |
33 | { L"Udp4",\r | |
34 | &gEfiUdp4ServiceBindingProtocolGuid,\r | |
35 | &mEslUdp4ServiceGuid,\r | |
36 | EslUdpInitialize4,\r | |
37 | EslUdpShutdown4 }\r | |
38 | };\r | |
39 | \r | |
40 | CONST UINTN cEslSocketBindingEntries = DIM ( cEslSocketBinding );\r | |
41 | \r | |
42 | DT_LAYER mEslLayer;\r | |
43 | \r | |
44 | \r | |
45 | /**\r | |
46 | Initialize an endpoint for network communication.\r | |
47 | \r | |
48 | The ::Socket routine initializes the communication endpoint by providing\r | |
49 | the support for the socket library function ::socket. The\r | |
50 | <a href="http://www.linuxhowtos.org/manpages/2/socket.htm">Linux</a>,\r | |
51 | <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html">POSIX</a>\r | |
52 | and <a href="http://msdn.microsoft.com/en-us/library/ms740506(v=VS.85).aspx">Windows</a>\r | |
53 | documentation for the socket routine are available online for reference.\r | |
54 | \r | |
55 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
56 | @param [in] domain Select the family of protocols for the client or server\r | |
57 | application.\r | |
58 | \r | |
59 | @param [in] type Specifies how to make the network connection. The following values\r | |
60 | are supported:\r | |
61 | <ul>\r | |
62 | <li>\r | |
63 | SOCK_STREAM - Connect to TCP, provides a byte stream\r | |
64 | that is manipluated by read, recv, send and write.\r | |
65 | </li>\r | |
66 | <li>\r | |
67 | SOCK_SEQPACKET - Connect to TCP, provides sequenced packet stream\r | |
68 | that is manipulated by read, recv, send and write.\r | |
69 | </li>\r | |
70 | <li>\r | |
71 | SOCK_DGRAM - Connect to UDP, provides a datagram service that is\r | |
72 | manipulated by recvfrom and sendto.\r | |
73 | </li>\r | |
74 | </ul>\r | |
75 | \r | |
76 | @param [in] protocol Specifies the lower layer protocol to use. The following\r | |
77 | values are supported:\r | |
78 | <ul>\r | |
79 | <li>IPPROTO_TCP</li> - This value must be combined with SOCK_STREAM.</li>\r | |
80 | <li>IPPROTO_UDP</li> - This value must be combined with SOCK_DGRAM.</li>\r | |
81 | </ul>\r | |
82 | \r | |
83 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
84 | \r | |
85 | @retval EFI_SUCCESS - Socket successfully created\r | |
86 | @retval EFI_INVALID_PARAMETER - Invalid domain value, errno = EAFNOSUPPORT\r | |
87 | @retval EFI_INVALID_PARAMETER - Invalid type value, errno = EINVAL\r | |
88 | @retval EFI_INVALID_PARAMETER - Invalid protocol value, errno = EINVAL\r | |
89 | \r | |
90 | **/\r | |
91 | EFI_STATUS\r | |
92 | EslSocket (\r | |
93 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
94 | IN int domain,\r | |
95 | IN int type,\r | |
96 | IN int protocol,\r | |
97 | IN int * pErrno\r | |
98 | )\r | |
99 | {\r | |
100 | DT_SOCKET * pSocket;\r | |
101 | EFI_STATUS Status;\r | |
102 | int errno;\r | |
103 | \r | |
104 | DBG_ENTER ( );\r | |
105 | \r | |
106 | //\r | |
107 | // Locate the socket\r | |
108 | //\r | |
109 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
110 | \r | |
111 | //\r | |
112 | // Set the default domain if necessary\r | |
113 | //\r | |
114 | if ( AF_UNSPEC == domain ) {\r | |
115 | domain = AF_INET;\r | |
116 | }\r | |
117 | \r | |
118 | //\r | |
119 | // Assume success\r | |
120 | //\r | |
121 | errno = 0;\r | |
122 | Status = EFI_SUCCESS;\r | |
123 | \r | |
124 | //\r | |
125 | // Use break instead of goto\r | |
126 | //\r | |
127 | for ( ; ; ) {\r | |
128 | //\r | |
129 | // Validate the domain value\r | |
130 | //\r | |
131 | if (( AF_INET != domain )\r | |
132 | && ( AF_LOCAL != domain ))\r | |
133 | {\r | |
134 | DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r | |
135 | "ERROR - Invalid domain value" ));\r | |
136 | Status = EFI_INVALID_PARAMETER;\r | |
137 | errno = EAFNOSUPPORT;\r | |
138 | break;\r | |
139 | }\r | |
140 | \r | |
141 | //\r | |
142 | // Set the default type if necessary\r | |
143 | //\r | |
144 | if ( 0 == type ) {\r | |
145 | type = SOCK_STREAM;\r | |
146 | }\r | |
147 | \r | |
148 | //\r | |
149 | // Validate the type value\r | |
150 | //\r | |
151 | if (( SOCK_STREAM == type )\r | |
152 | || ( SOCK_SEQPACKET == type )) {\r | |
153 | //\r | |
154 | // Set the default protocol if necessary\r | |
155 | //\r | |
156 | if ( 0 == protocol ) {\r | |
157 | protocol = IPPROTO_TCP;\r | |
158 | }\r | |
159 | }\r | |
160 | else if ( SOCK_DGRAM == type ) {\r | |
161 | //\r | |
162 | // Set the default protocol if necessary\r | |
163 | //\r | |
164 | if ( 0 == protocol ) {\r | |
165 | protocol = IPPROTO_UDP;\r | |
166 | }\r | |
167 | }\r | |
168 | else {\r | |
169 | DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r | |
170 | "ERROR - Invalid type value" ));\r | |
171 | Status = EFI_INVALID_PARAMETER;\r | |
172 | errno = EINVAL;\r | |
173 | break;\r | |
174 | }\r | |
175 | \r | |
176 | //\r | |
177 | // Validate the protocol value\r | |
178 | //\r | |
179 | if (( IPPROTO_TCP != protocol )\r | |
180 | && ( IPPROTO_UDP != protocol )) {\r | |
181 | DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r | |
182 | "ERROR - Invalid protocol value" ));\r | |
183 | Status = EFI_INVALID_PARAMETER;\r | |
184 | errno = EINVAL;\r | |
185 | break;\r | |
186 | }\r | |
187 | \r | |
188 | //\r | |
189 | // Save the socket attributes\r | |
190 | //\r | |
191 | pSocket->Domain = domain;\r | |
192 | pSocket->Type = type;\r | |
193 | pSocket->Protocol = protocol;\r | |
194 | \r | |
195 | //\r | |
196 | // Done\r | |
197 | //\r | |
198 | break;\r | |
199 | }\r | |
200 | \r | |
201 | //\r | |
202 | // Return the operation status\r | |
203 | //\r | |
204 | if ( NULL != pErrno ) {\r | |
205 | *pErrno = errno;\r | |
206 | }\r | |
207 | DBG_EXIT_STATUS ( Status );\r | |
208 | return Status;\r | |
209 | }\r | |
210 | \r | |
211 | \r | |
212 | /**\r | |
213 | Accept a network connection.\r | |
214 | \r | |
215 | The SocketAccept routine waits for a network connection to the socket.\r | |
216 | It is able to return the remote network address to the caller if\r | |
217 | requested.\r | |
218 | \r | |
219 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
220 | \r | |
221 | @param [in] pSockAddr Address of a buffer to receive the remote\r | |
222 | network address.\r | |
223 | \r | |
224 | @param [in, out] pSockAddrLength Length in bytes of the address buffer.\r | |
225 | On output specifies the length of the\r | |
226 | remote network address.\r | |
227 | \r | |
228 | @param [out] ppSocketProtocol Address of a buffer to receive the socket protocol\r | |
229 | instance associated with the new socket.\r | |
230 | \r | |
231 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
232 | \r | |
233 | @retval EFI_SUCCESS New connection successfully created\r | |
234 | @retval EFI_NOT_READY No connection is available\r | |
235 | \r | |
236 | **/\r | |
237 | EFI_STATUS\r | |
238 | EslSocketAccept (\r | |
239 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
240 | IN struct sockaddr * pSockAddr,\r | |
241 | IN OUT socklen_t * pSockAddrLength,\r | |
242 | IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol,\r | |
243 | IN int * pErrno\r | |
244 | )\r | |
245 | {\r | |
246 | DT_SOCKET * pNewSocket;\r | |
247 | DT_SOCKET * pSocket;\r | |
248 | EFI_STATUS Status;\r | |
249 | EFI_TPL TplPrevious;\r | |
250 | \r | |
251 | DBG_ENTER ( );\r | |
252 | \r | |
253 | //\r | |
254 | // Assume success\r | |
255 | //\r | |
256 | Status = EFI_SUCCESS;\r | |
257 | \r | |
258 | //\r | |
259 | // Validate the socket\r | |
260 | //\r | |
261 | pSocket = NULL;\r | |
262 | pNewSocket = NULL;\r | |
263 | if ( NULL != pSocketProtocol ) {\r | |
264 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
265 | \r | |
266 | //\r | |
267 | // Validate the sockaddr\r | |
268 | //\r | |
269 | if (( NULL != pSockAddr )\r | |
270 | && ( NULL == pSockAddrLength )) {\r | |
271 | DEBUG (( DEBUG_ACCEPT,\r | |
272 | "ERROR - pSockAddr is NULL!\r\n" ));\r | |
273 | Status = EFI_INVALID_PARAMETER;\r | |
274 | pSocket->errno = EFAULT;\r | |
275 | }\r | |
276 | else {\r | |
277 | //\r | |
278 | // Synchronize with the socket layer\r | |
279 | //\r | |
280 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
281 | \r | |
282 | //\r | |
283 | // Verify that the socket is in the listen state\r | |
284 | //\r | |
285 | if ( SOCKET_STATE_LISTENING != pSocket->State ) {\r | |
286 | DEBUG (( DEBUG_ACCEPT,\r | |
287 | "ERROR - Socket is not listening!\r\n" ));\r | |
288 | Status = EFI_NOT_STARTED;\r | |
289 | pSocket->errno = EOPNOTSUPP;\r | |
290 | }\r | |
291 | else {\r | |
292 | //\r | |
293 | // Determine if a socket is available\r | |
294 | //\r | |
295 | if ( 0 == pSocket->FifoDepth ) {\r | |
296 | //\r | |
297 | // No connections available\r | |
298 | // Determine if any ports are available\r | |
299 | //\r | |
300 | if ( NULL == pSocket->pPortList ) {\r | |
301 | //\r | |
302 | // No ports available\r | |
303 | //\r | |
304 | Status = EFI_DEVICE_ERROR;\r | |
305 | pSocket->errno = EINVAL;\r | |
306 | \r | |
307 | //\r | |
308 | // Update the socket state\r | |
309 | //\r | |
310 | pSocket->State = SOCKET_STATE_NO_PORTS;\r | |
311 | }\r | |
312 | else {\r | |
313 | //\r | |
314 | // Ports are available\r | |
315 | // No connection requests at this time\r | |
316 | //\r | |
317 | Status = EFI_NOT_READY;\r | |
318 | pSocket->errno = EAGAIN;\r | |
319 | }\r | |
320 | }\r | |
321 | else {\r | |
322 | \r | |
323 | //\r | |
324 | // Get the remote network address\r | |
325 | //\r | |
326 | pNewSocket = pSocket->pFifoHead;\r | |
327 | ASSERT ( NULL != pNewSocket );\r | |
328 | switch ( pSocket->Domain ) {\r | |
329 | default:\r | |
330 | DEBUG (( DEBUG_ACCEPT,\r | |
331 | "ERROR - Invalid socket address family: %d\r\n",\r | |
332 | pSocket->Domain ));\r | |
333 | Status = EFI_INVALID_PARAMETER;\r | |
334 | pSocket->errno = EADDRNOTAVAIL;\r | |
335 | break;\r | |
336 | \r | |
337 | case AF_INET:\r | |
338 | //\r | |
339 | // Determine the connection point within the network stack\r | |
340 | //\r | |
341 | switch ( pSocket->Type ) {\r | |
342 | default:\r | |
343 | DEBUG (( DEBUG_ACCEPT,\r | |
344 | "ERROR - Invalid socket type: %d\r\n",\r | |
345 | pSocket->Type));\r | |
346 | Status = EFI_INVALID_PARAMETER;\r | |
347 | pSocket->errno = EADDRNOTAVAIL;\r | |
348 | break;\r | |
349 | \r | |
350 | case SOCK_STREAM:\r | |
351 | case SOCK_SEQPACKET:\r | |
352 | Status = EslTcpAccept4 ( pNewSocket,\r | |
353 | pSockAddr,\r | |
354 | pSockAddrLength );\r | |
355 | break;\r | |
356 | \r | |
357 | /*\r | |
358 | case SOCK_DGRAM:\r | |
359 | Status = UdpAccept4 ( pSocket );\r | |
360 | break;\r | |
361 | */\r | |
362 | }\r | |
363 | break;\r | |
364 | }\r | |
365 | if ( !EFI_ERROR ( Status )) {\r | |
366 | //\r | |
367 | // Remove the new socket from the list\r | |
368 | //\r | |
369 | pSocket->pFifoHead = pNewSocket->pNextConnection;\r | |
370 | if ( NULL == pSocket->pFifoHead ) {\r | |
371 | pSocket->pFifoTail = NULL;\r | |
372 | }\r | |
373 | \r | |
374 | //\r | |
375 | // Account for this socket\r | |
376 | //\r | |
377 | pSocket->FifoDepth -= 1;\r | |
378 | \r | |
379 | //\r | |
380 | // Update the new socket's state\r | |
381 | //\r | |
382 | pNewSocket->State = SOCKET_STATE_CONNECTED;\r | |
383 | pNewSocket->bConfigured = TRUE;\r | |
384 | DEBUG (( DEBUG_ACCEPT,\r | |
385 | "0x%08x: Socket connected\r\n",\r | |
386 | pNewSocket ));\r | |
387 | }\r | |
388 | }\r | |
389 | }\r | |
390 | \r | |
391 | //\r | |
392 | // Release the socket layer synchronization\r | |
393 | //\r | |
394 | RESTORE_TPL ( TplPrevious );\r | |
395 | }\r | |
396 | }\r | |
397 | \r | |
398 | //\r | |
399 | // Return the new socket\r | |
400 | //\r | |
401 | if (( NULL != ppSocketProtocol )\r | |
402 | && ( NULL != pNewSocket )) {\r | |
403 | *ppSocketProtocol = &pNewSocket->SocketProtocol;\r | |
404 | }\r | |
405 | \r | |
406 | //\r | |
407 | // Return the operation status\r | |
408 | //\r | |
409 | if ( NULL != pErrno ) {\r | |
410 | if ( NULL != pSocket ) {\r | |
411 | *pErrno = pSocket->errno;\r | |
412 | }\r | |
413 | else\r | |
414 | {\r | |
415 | Status = EFI_INVALID_PARAMETER;\r | |
416 | *pErrno = EBADF;\r | |
417 | }\r | |
418 | }\r | |
419 | DBG_EXIT_STATUS ( Status );\r | |
420 | return Status;\r | |
421 | }\r | |
422 | \r | |
423 | \r | |
424 | /**\r | |
425 | Allocate and initialize a DT_SOCKET structure.\r | |
426 | \r | |
427 | The ::SocketAllocate() function allocates a DT_SOCKET structure\r | |
428 | and installs a protocol on ChildHandle. If pChildHandle is a\r | |
429 | pointer to NULL, then a new handle is created and returned in\r | |
430 | pChildHandle. If pChildHandle is not a pointer to NULL, then\r | |
431 | the protocol installs on the existing pChildHandle.\r | |
432 | \r | |
433 | @param [in, out] pChildHandle Pointer to the handle of the child to create.\r | |
434 | If it is NULL, then a new handle is created.\r | |
435 | If it is a pointer to an existing UEFI handle, \r | |
436 | then the protocol is added to the existing UEFI\r | |
437 | handle.\r | |
438 | @param [in] DebugFlags Flags for debug messages\r | |
439 | @param [in, out] ppSocket The buffer to receive the DT_SOCKET structure address.\r | |
440 | \r | |
441 | @retval EFI_SUCCESS The protocol was added to ChildHandle.\r | |
442 | @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r | |
443 | @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r | |
444 | the child\r | |
445 | @retval other The child handle was not created\r | |
446 | \r | |
447 | **/\r | |
448 | EFI_STATUS\r | |
449 | EFIAPI\r | |
450 | EslSocketAllocate (\r | |
451 | IN OUT EFI_HANDLE * pChildHandle,\r | |
452 | IN UINTN DebugFlags,\r | |
453 | IN OUT DT_SOCKET ** ppSocket\r | |
454 | )\r | |
455 | {\r | |
456 | UINTN LengthInBytes;\r | |
457 | DT_LAYER * pLayer;\r | |
458 | DT_SOCKET * pSocket;\r | |
459 | EFI_STATUS Status;\r | |
460 | EFI_TPL TplPrevious;\r | |
461 | \r | |
462 | DBG_ENTER ( );\r | |
463 | \r | |
464 | //\r | |
465 | // Create a socket structure\r | |
466 | //\r | |
467 | LengthInBytes = sizeof ( *pSocket );\r | |
468 | Status = gBS->AllocatePool (\r | |
469 | EfiRuntimeServicesData,\r | |
470 | LengthInBytes,\r | |
471 | (VOID **) &pSocket\r | |
472 | );\r | |
473 | if ( !EFI_ERROR ( Status )) {\r | |
474 | DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,\r | |
475 | "0x%08x: Allocate pSocket, %d bytes\r\n",\r | |
476 | pSocket,\r | |
477 | LengthInBytes ));\r | |
478 | \r | |
479 | //\r | |
480 | // Initialize the socket protocol\r | |
481 | //\r | |
482 | ZeroMem ( pSocket, LengthInBytes );\r | |
483 | \r | |
484 | pSocket->Signature = SOCKET_SIGNATURE;\r | |
485 | pSocket->SocketProtocol.pfnAccept = EslSocketAccept;\r | |
486 | pSocket->SocketProtocol.pfnBind = EslSocketBind;\r | |
487 | pSocket->SocketProtocol.pfnClosePoll = EslSocketClosePoll;\r | |
488 | pSocket->SocketProtocol.pfnCloseStart = EslSocketCloseStart;\r | |
489 | pSocket->SocketProtocol.pfnConnect = EslSocketConnect;\r | |
490 | pSocket->SocketProtocol.pfnGetLocal = EslSocketGetLocalAddress;\r | |
491 | pSocket->SocketProtocol.pfnGetPeer = EslSocketGetPeerAddress;\r | |
492 | pSocket->SocketProtocol.pfnListen = EslSocketListen;\r | |
493 | pSocket->SocketProtocol.pfnOptionGet = EslSocketOptionGet;\r | |
494 | pSocket->SocketProtocol.pfnOptionSet = EslSocketOptionSet;\r | |
495 | pSocket->SocketProtocol.pfnPoll = EslSocketPoll;\r | |
496 | pSocket->SocketProtocol.pfnReceive = EslSocketReceive;\r | |
497 | pSocket->SocketProtocol.pfnSend = EslSocketTransmit;\r | |
498 | pSocket->SocketProtocol.pfnShutdown = EslSocketShutdown;\r | |
499 | pSocket->SocketProtocol.pfnSocket = EslSocket;\r | |
500 | \r | |
501 | pSocket->MaxRxBuf = MAX_RX_DATA;\r | |
502 | pSocket->MaxTxBuf = MAX_TX_DATA;\r | |
503 | \r | |
504 | //\r | |
505 | // Install the socket protocol on the specified handle\r | |
506 | //\r | |
507 | Status = gBS->InstallMultipleProtocolInterfaces (\r | |
508 | pChildHandle,\r | |
509 | &gEfiSocketProtocolGuid,\r | |
510 | &pSocket->SocketProtocol,\r | |
511 | NULL\r | |
512 | );\r | |
513 | if ( !EFI_ERROR ( Status )) {\r | |
514 | DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r | |
515 | "Installed: gEfiSocketProtocolGuid on 0x%08x\r\n",\r | |
516 | *pChildHandle ));\r | |
517 | pSocket->SocketProtocol.SocketHandle = *pChildHandle;\r | |
518 | \r | |
519 | //\r | |
520 | // Synchronize with the socket layer\r | |
521 | //\r | |
522 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
523 | \r | |
524 | //\r | |
525 | // Add this socket to the list\r | |
526 | //\r | |
527 | pLayer = &mEslLayer;\r | |
528 | pSocket->pNext = pLayer->pSocketList;\r | |
529 | pLayer->pSocketList = pSocket;\r | |
530 | \r | |
531 | //\r | |
532 | // Release the socket layer synchronization\r | |
533 | //\r | |
534 | RESTORE_TPL ( TplPrevious );\r | |
535 | \r | |
536 | //\r | |
537 | // Return the socket structure address\r | |
538 | //\r | |
539 | *ppSocket = pSocket;\r | |
540 | }\r | |
541 | else {\r | |
542 | DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,\r | |
543 | "ERROR - Failed to install gEfiSocketProtocolGuid on 0x%08x, Status: %r\r\n",\r | |
544 | *pChildHandle,\r | |
545 | Status ));\r | |
546 | }\r | |
547 | \r | |
548 | //\r | |
549 | // Release the socket if necessary\r | |
550 | //\r | |
551 | if ( EFI_ERROR ( Status )) {\r | |
552 | gBS->FreePool ( pSocket );\r | |
553 | DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,\r | |
554 | "0x%08x: Free pSocket, %d bytes\r\n",\r | |
555 | pSocket,\r | |
556 | sizeof ( *pSocket )));\r | |
557 | pSocket = NULL;\r | |
558 | }\r | |
559 | }\r | |
560 | else {\r | |
561 | DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,\r | |
562 | "ERROR - Failed socket allocation, Status: %r\r\n",\r | |
563 | Status ));\r | |
564 | }\r | |
565 | \r | |
566 | //\r | |
567 | // Return the operation status\r | |
568 | //\r | |
569 | DBG_EXIT_STATUS ( Status );\r | |
570 | return Status;\r | |
571 | }\r | |
572 | \r | |
573 | \r | |
574 | /**\r | |
575 | Bind a name to a socket.\r | |
576 | \r | |
577 | The ::SocketBind routine connects a name to a socket on the local machine. The\r | |
578 | <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html">POSIX</a>\r | |
579 | documentation for the bind routine is available online for reference.\r | |
580 | \r | |
581 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
582 | \r | |
583 | @param [in] pSockAddr Address of a sockaddr structure that contains the\r | |
584 | connection point on the local machine. An IPv4 address\r | |
585 | of INADDR_ANY specifies that the connection is made to\r | |
586 | all of the network stacks on the platform. Specifying a\r | |
587 | specific IPv4 address restricts the connection to the\r | |
588 | network stack supporting that address. Specifying zero\r | |
589 | for the port causes the network layer to assign a port\r | |
590 | number from the dynamic range. Specifying a specific\r | |
591 | port number causes the network layer to use that port.\r | |
592 | \r | |
593 | @param [in] SockAddrLen Specifies the length in bytes of the sockaddr structure.\r | |
594 | \r | |
595 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
596 | \r | |
597 | @retval EFI_SUCCESS - Socket successfully created\r | |
598 | \r | |
599 | **/\r | |
600 | EFI_STATUS\r | |
601 | EslSocketBind (\r | |
602 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
603 | IN const struct sockaddr * pSockAddr,\r | |
604 | IN socklen_t SockAddrLength,\r | |
605 | OUT int * pErrno\r | |
606 | )\r | |
607 | {\r | |
608 | DT_SOCKET * pSocket;\r | |
609 | EFI_STATUS Status;\r | |
610 | EFI_TPL TplPrevious;\r | |
611 | \r | |
612 | DBG_ENTER ( );\r | |
613 | \r | |
614 | //\r | |
615 | // Assume success\r | |
616 | //\r | |
617 | Status = EFI_SUCCESS;\r | |
618 | \r | |
619 | //\r | |
620 | // Validate the socket\r | |
621 | //\r | |
622 | pSocket = NULL;\r | |
623 | if ( NULL != pSocketProtocol ) {\r | |
624 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
625 | \r | |
626 | //\r | |
627 | // Validate the structure pointer\r | |
628 | //\r | |
629 | if ( NULL == pSockAddr ) {\r | |
630 | DEBUG (( DEBUG_BIND,\r | |
631 | "ERROR - pSockAddr is NULL!\r\n" ));\r | |
632 | Status = EFI_INVALID_PARAMETER;\r | |
633 | pSocket->errno = EFAULT;\r | |
634 | }\r | |
635 | else{\r | |
636 | //\r | |
637 | // Validate the name length\r | |
638 | //\r | |
639 | if (( SockAddrLength < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))\r | |
640 | || ( pSockAddr->sa_len < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))) {\r | |
641 | DEBUG (( DEBUG_BIND,\r | |
642 | "ERROR - Invalid bind name length: %d, sa_len: %d\r\n",\r | |
643 | SockAddrLength,\r | |
644 | pSockAddr->sa_len ));\r | |
645 | Status = EFI_INVALID_PARAMETER;\r | |
646 | pSocket->errno = EINVAL;\r | |
647 | }\r | |
648 | else {\r | |
649 | //\r | |
650 | // Set the socket address length\r | |
651 | //\r | |
652 | if ( SockAddrLength > pSockAddr->sa_len ) {\r | |
653 | SockAddrLength = pSockAddr->sa_len;\r | |
654 | }\r | |
655 | \r | |
656 | //\r | |
657 | // Synchronize with the socket layer\r | |
658 | //\r | |
659 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
660 | \r | |
661 | //\r | |
662 | // Validate the local address\r | |
663 | //\r | |
664 | switch ( pSockAddr->sa_family ) {\r | |
665 | default:\r | |
666 | DEBUG (( DEBUG_BIND,\r | |
667 | "ERROR - Invalid bind address family: %d\r\n",\r | |
668 | pSockAddr->sa_family ));\r | |
669 | Status = EFI_INVALID_PARAMETER;\r | |
670 | pSocket->errno = EADDRNOTAVAIL;\r | |
671 | break;\r | |
672 | \r | |
673 | case AF_INET:\r | |
674 | //\r | |
675 | // Determine the connection point within the network stack\r | |
676 | //\r | |
677 | switch ( pSocket->Type ) {\r | |
678 | default:\r | |
679 | DEBUG (( DEBUG_BIND,\r | |
680 | "ERROR - Invalid socket type: %d\r\n",\r | |
681 | pSocket->Type));\r | |
682 | Status = EFI_INVALID_PARAMETER;\r | |
683 | pSocket->errno = EADDRNOTAVAIL;\r | |
684 | break;\r | |
685 | \r | |
686 | case SOCK_STREAM:\r | |
687 | case SOCK_SEQPACKET:\r | |
688 | Status = EslTcpBind4 ( pSocket,\r | |
689 | pSockAddr,\r | |
690 | SockAddrLength );\r | |
691 | break;\r | |
692 | \r | |
693 | case SOCK_DGRAM:\r | |
694 | Status = EslUdpBind4 ( pSocket,\r | |
695 | pSockAddr,\r | |
696 | SockAddrLength );\r | |
697 | break;\r | |
698 | }\r | |
699 | break;\r | |
700 | }\r | |
701 | \r | |
702 | //\r | |
703 | // Mark this socket as bound if successful\r | |
704 | //\r | |
705 | if ( !EFI_ERROR ( Status )) {\r | |
706 | pSocket->State = SOCKET_STATE_BOUND;\r | |
707 | }\r | |
708 | \r | |
709 | //\r | |
710 | // Release the socket layer synchronization\r | |
711 | //\r | |
712 | RESTORE_TPL ( TplPrevious );\r | |
713 | }\r | |
714 | }\r | |
715 | }\r | |
716 | \r | |
717 | //\r | |
718 | // Return the operation status\r | |
719 | //\r | |
720 | if ( NULL != pErrno ) {\r | |
721 | if ( NULL != pSocket ) {\r | |
722 | *pErrno = pSocket->errno;\r | |
723 | }\r | |
724 | else\r | |
725 | {\r | |
726 | Status = EFI_INVALID_PARAMETER;\r | |
727 | *pErrno = EBADF;\r | |
728 | }\r | |
729 | }\r | |
730 | DBG_EXIT_STATUS ( Status );\r | |
731 | return Status;\r | |
732 | }\r | |
733 | \r | |
734 | \r | |
735 | /**\r | |
736 | Determine if the socket is closed\r | |
737 | \r | |
738 | Reverses the operations of the ::SocketAllocate() routine.\r | |
739 | \r | |
740 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
741 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
742 | \r | |
743 | @retval EFI_SUCCESS Socket successfully closed\r | |
744 | @retval EFI_NOT_READY Close still in progress\r | |
745 | @retval EFI_ALREADY Close operation already in progress\r | |
746 | @retval Other Failed to close the socket\r | |
747 | \r | |
748 | **/\r | |
749 | EFI_STATUS\r | |
750 | EslSocketClosePoll (\r | |
751 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
752 | IN int * pErrno\r | |
753 | )\r | |
754 | {\r | |
755 | int errno;\r | |
756 | DT_LAYER * pLayer;\r | |
757 | DT_SOCKET * pNextSocket;\r | |
758 | DT_SOCKET * pSocket;\r | |
759 | EFI_STATUS Status;\r | |
760 | EFI_TPL TplPrevious;\r | |
761 | \r | |
762 | DBG_ENTER ( );\r | |
763 | \r | |
764 | //\r | |
765 | // Assume success\r | |
766 | //\r | |
767 | errno = 0;\r | |
768 | Status = EFI_SUCCESS;\r | |
769 | \r | |
770 | //\r | |
771 | // Synchronize with the socket layer\r | |
772 | //\r | |
773 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
774 | \r | |
775 | //\r | |
776 | // Locate the socket\r | |
777 | //\r | |
778 | pLayer = &mEslLayer;\r | |
779 | pNextSocket = pLayer->pSocketList;\r | |
780 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
781 | while ( NULL != pNextSocket ) {\r | |
782 | if ( pNextSocket == pSocket ) {\r | |
783 | //\r | |
784 | // Determine if the socket is in the closing state\r | |
785 | //\r | |
786 | if ( SOCKET_STATE_CLOSED == pSocket->State ) {\r | |
787 | //\r | |
788 | // Walk the list of ports\r | |
789 | //\r | |
790 | if ( NULL == pSocket->pPortList ) {\r | |
791 | //\r | |
792 | // All the ports are closed\r | |
793 | // Close the WaitAccept event if necessary\r | |
794 | //\r | |
795 | if ( NULL != pSocket->WaitAccept ) {\r | |
796 | Status = gBS->CloseEvent ( pSocket->WaitAccept );\r | |
797 | if ( !EFI_ERROR ( Status )) {\r | |
798 | DEBUG (( DEBUG_SOCKET | DEBUG_CLOSE | DEBUG_POOL,\r | |
799 | "0x%08x: Closed WaitAccept event\r\n",\r | |
800 | pSocket->WaitAccept ));\r | |
801 | //\r | |
802 | // Return the transmit status\r | |
803 | //\r | |
804 | Status = pSocket->TxError;\r | |
805 | if ( EFI_ERROR ( Status )) {\r | |
806 | pSocket->errno = EIO;\r | |
807 | }\r | |
808 | }\r | |
809 | else {\r | |
810 | DEBUG (( DEBUG_ERROR | DEBUG_SOCKET | DEBUG_CLOSE | DEBUG_POOL,\r | |
811 | "ERROR - Failed to close the WaitAccept event, Status: %r\r\n",\r | |
812 | Status ));\r | |
813 | ASSERT ( EFI_SUCCESS == Status );\r | |
814 | }\r | |
815 | }\r | |
816 | }\r | |
817 | else {\r | |
818 | //\r | |
819 | // At least one port is still open\r | |
820 | //\r | |
821 | Status = EFI_NOT_READY;\r | |
822 | errno = EAGAIN;\r | |
823 | }\r | |
824 | }\r | |
825 | else {\r | |
826 | //\r | |
827 | // SocketCloseStart was not called\r | |
828 | //\r | |
829 | Status = EFI_NOT_STARTED;\r | |
830 | errno = EPERM;\r | |
831 | }\r | |
832 | break;\r | |
833 | }\r | |
834 | \r | |
835 | //\r | |
836 | // Set the next socket\r | |
837 | //\r | |
838 | pNextSocket = pNextSocket->pNext;\r | |
839 | }\r | |
840 | \r | |
841 | //\r | |
842 | // Handle the error case where the socket was already closed\r | |
843 | //\r | |
844 | if ( NULL == pSocket ) {\r | |
845 | //\r | |
846 | // Socket not found\r | |
847 | //\r | |
848 | Status = EFI_NOT_FOUND;\r | |
849 | errno = ENOTSOCK;\r | |
850 | }\r | |
851 | \r | |
852 | //\r | |
853 | // Release the socket layer synchronization\r | |
854 | //\r | |
855 | RESTORE_TPL ( TplPrevious );\r | |
856 | \r | |
857 | //\r | |
858 | // Return the operation status\r | |
859 | //\r | |
860 | if ( NULL != pErrno ) {\r | |
861 | *pErrno = errno;\r | |
862 | }\r | |
863 | DBG_EXIT_STATUS ( Status );\r | |
864 | return Status;\r | |
865 | }\r | |
866 | \r | |
867 | \r | |
868 | /**\r | |
869 | Start the close operation on the socket\r | |
870 | \r | |
871 | Start closing the socket by closing all of the ports. Upon\r | |
872 | completion, the ::SocketPoll() routine finishes closing the\r | |
873 | socket.\r | |
874 | \r | |
875 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
876 | @param [in] bCloseNow Boolean to control close behavior\r | |
877 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
878 | \r | |
879 | @retval EFI_SUCCESS Socket successfully closed\r | |
880 | @retval EFI_NOT_READY Close still in progress\r | |
881 | @retval EFI_ALREADY Close operation already in progress\r | |
882 | @retval Other Failed to close the socket\r | |
883 | \r | |
884 | **/\r | |
885 | EFI_STATUS\r | |
886 | EslSocketCloseStart (\r | |
887 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
888 | IN BOOLEAN bCloseNow,\r | |
889 | IN int * pErrno\r | |
890 | )\r | |
891 | {\r | |
892 | int errno;\r | |
893 | DT_PORT * pNextPort;\r | |
894 | DT_PORT * pPort;\r | |
895 | DT_SOCKET * pSocket;\r | |
896 | EFI_STATUS Status;\r | |
897 | EFI_TPL TplPrevious;\r | |
898 | \r | |
899 | DBG_ENTER ( );\r | |
900 | \r | |
901 | //\r | |
902 | // Assume success\r | |
903 | //\r | |
904 | Status = EFI_SUCCESS;\r | |
905 | errno = 0;\r | |
906 | \r | |
907 | //\r | |
908 | // Synchronize with the socket layer\r | |
909 | //\r | |
910 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
911 | \r | |
912 | //\r | |
913 | // Determine if the socket is already closed\r | |
914 | //\r | |
915 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
916 | if ( SOCKET_STATE_CLOSED > pSocket->State ) {\r | |
917 | //\r | |
918 | // Update the socket state\r | |
919 | //\r | |
920 | pSocket->State = SOCKET_STATE_CLOSED;\r | |
921 | \r | |
922 | //\r | |
923 | // Walk the list of ports\r | |
924 | //\r | |
925 | pPort = pSocket->pPortList;\r | |
926 | while ( NULL != pPort ) {\r | |
927 | //\r | |
928 | // Start closing the ports\r | |
929 | //\r | |
930 | pNextPort = pPort->pLinkSocket;\r | |
931 | Status = pPort->pfnCloseStart ( pPort,\r | |
932 | bCloseNow,\r | |
933 | DEBUG_CLOSE | DEBUG_LISTEN | DEBUG_CONNECTION );\r | |
934 | if (( EFI_SUCCESS != Status )\r | |
935 | && ( EFI_NOT_READY != Status )) {\r | |
936 | errno = EIO;\r | |
937 | break;\r | |
938 | }\r | |
939 | \r | |
940 | //\r | |
941 | // Set the next port\r | |
942 | //\r | |
943 | pPort = pNextPort;\r | |
944 | }\r | |
945 | \r | |
946 | //\r | |
947 | // Attempt to finish closing the socket\r | |
948 | //\r | |
949 | if ( NULL == pPort ) {\r | |
950 | Status = EslSocketClosePoll ( pSocketProtocol, &errno );\r | |
951 | }\r | |
952 | }\r | |
953 | else {\r | |
954 | Status = EFI_ALREADY_STARTED;\r | |
955 | errno = EALREADY;\r | |
956 | }\r | |
957 | \r | |
958 | //\r | |
959 | // Release the socket layer synchronization\r | |
960 | //\r | |
961 | RESTORE_TPL ( TplPrevious );\r | |
962 | \r | |
963 | //\r | |
964 | // Return the operation status\r | |
965 | //\r | |
966 | if ( NULL != pErrno ) {\r | |
967 | *pErrno = errno;\r | |
968 | }\r | |
969 | DBG_EXIT_STATUS ( Status );\r | |
970 | return Status;\r | |
971 | }\r | |
972 | \r | |
973 | \r | |
974 | /**\r | |
975 | Connect to a remote system via the network.\r | |
976 | \r | |
977 | The ::SocketConnect routine attempts to establish a connection to a\r | |
978 | socket on the local or remote system using the specified address.\r | |
979 | The POSIX\r | |
980 | <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html">connect</a>\r | |
981 | documentation is available online.\r | |
982 | \r | |
983 | There are three states associated with a connection:\r | |
984 | <ul>\r | |
985 | <li>Not connected</li>\r | |
986 | <li>Connection in progress</li>\r | |
987 | <li>Connected</li>\r | |
988 | </ul>\r | |
989 | In the "Not connected" state, calls to ::connect start the connection\r | |
990 | processing and update the state to "Connection in progress". During\r | |
991 | the "Connection in progress" state, connect polls for connection completion\r | |
992 | and moves the state to "Connected" after the connection is established.\r | |
993 | Note that these states are only visible when the file descriptor is marked\r | |
994 | with O_NONBLOCK. Also, the POLL_WRITE bit is set when the connection\r | |
995 | completes and may be used by poll or select as an indicator to call\r | |
996 | connect again.\r | |
997 | \r | |
998 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
999 | \r | |
1000 | @param [in] pSockAddr Network address of the remote system.\r | |
1001 | \r | |
1002 | @param [in] SockAddrLength Length in bytes of the network address.\r | |
1003 | \r | |
1004 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
1005 | \r | |
1006 | @retval EFI_SUCCESS The connection was successfully established.\r | |
1007 | @retval EFI_NOT_READY The connection is in progress, call this routine again.\r | |
1008 | @retval Others The connection attempt failed.\r | |
1009 | \r | |
1010 | **/\r | |
1011 | EFI_STATUS\r | |
1012 | EslSocketConnect (\r | |
1013 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
1014 | IN const struct sockaddr * pSockAddr,\r | |
1015 | IN socklen_t SockAddrLength,\r | |
1016 | IN int * pErrno\r | |
1017 | )\r | |
1018 | {\r | |
1019 | DT_SOCKET * pSocket;\r | |
1020 | EFI_STATUS Status;\r | |
1021 | EFI_TPL TplPrevious;\r | |
1022 | \r | |
1023 | DEBUG (( DEBUG_CONNECT, "Entering SocketConnect\r\n" ));\r | |
1024 | \r | |
1025 | //\r | |
1026 | // Assume success\r | |
1027 | //\r | |
1028 | Status = EFI_SUCCESS;\r | |
1029 | \r | |
1030 | //\r | |
1031 | // Validate the socket\r | |
1032 | //\r | |
1033 | pSocket = NULL;\r | |
1034 | if ( NULL != pSocketProtocol ) {\r | |
1035 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
1036 | \r | |
1037 | //\r | |
1038 | // Validate the name length\r | |
1039 | //\r | |
1040 | if (( SockAddrLength < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))\r | |
1041 | || ( pSockAddr->sa_len < ( sizeof ( struct sockaddr ) - sizeof ( pSockAddr->sa_data )))) {\r | |
1042 | DEBUG (( DEBUG_CONNECT,\r | |
1043 | "ERROR - Invalid bind name length: %d, sa_len: %d\r\n",\r | |
1044 | SockAddrLength,\r | |
1045 | pSockAddr->sa_len ));\r | |
1046 | Status = EFI_INVALID_PARAMETER;\r | |
1047 | pSocket->errno = EINVAL;\r | |
1048 | }\r | |
1049 | else {\r | |
1050 | //\r | |
1051 | // Assume success\r | |
1052 | //\r | |
1053 | pSocket->errno = 0;\r | |
1054 | \r | |
1055 | //\r | |
1056 | // Set the socket address length\r | |
1057 | //\r | |
1058 | if ( SockAddrLength > pSockAddr->sa_len ) {\r | |
1059 | SockAddrLength = pSockAddr->sa_len;\r | |
1060 | }\r | |
1061 | \r | |
1062 | //\r | |
1063 | // Synchronize with the socket layer\r | |
1064 | //\r | |
1065 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
1066 | \r | |
1067 | //\r | |
1068 | // Validate the socket state\r | |
1069 | //\r | |
1070 | switch ( pSocket->State ) {\r | |
1071 | default:\r | |
1072 | //\r | |
1073 | // Wrong socket state\r | |
1074 | //\r | |
1075 | pSocket->errno = EIO;\r | |
1076 | Status = EFI_DEVICE_ERROR;\r | |
1077 | break;\r | |
1078 | \r | |
1079 | case SOCKET_STATE_NOT_CONFIGURED:\r | |
1080 | case SOCKET_STATE_BOUND:\r | |
1081 | //\r | |
1082 | // Validate the local address\r | |
1083 | //\r | |
1084 | switch ( pSockAddr->sa_family ) {\r | |
1085 | default:\r | |
1086 | DEBUG (( DEBUG_CONNECT,\r | |
1087 | "ERROR - Invalid bind address family: %d\r\n",\r | |
1088 | pSockAddr->sa_family ));\r | |
1089 | Status = EFI_INVALID_PARAMETER;\r | |
1090 | pSocket->errno = EADDRNOTAVAIL;\r | |
1091 | break;\r | |
1092 | \r | |
1093 | case AF_INET:\r | |
1094 | //\r | |
1095 | // Determine the connection point within the network stack\r | |
1096 | //\r | |
1097 | switch ( pSocket->Type ) {\r | |
1098 | default:\r | |
1099 | DEBUG (( DEBUG_CONNECT,\r | |
1100 | "ERROR - Invalid socket type: %d\r\n",\r | |
1101 | pSocket->Type));\r | |
1102 | Status = EFI_INVALID_PARAMETER;\r | |
1103 | pSocket->errno = EADDRNOTAVAIL;\r | |
1104 | break;\r | |
1105 | \r | |
1106 | case SOCK_STREAM:\r | |
1107 | case SOCK_SEQPACKET:\r | |
1108 | //\r | |
1109 | // Start the connection processing\r | |
1110 | //\r | |
1111 | Status = EslTcpConnectStart4 ( pSocket,\r | |
1112 | pSockAddr,\r | |
1113 | SockAddrLength );\r | |
1114 | \r | |
1115 | //\r | |
1116 | // Set the next state if connecting\r | |
1117 | //\r | |
1118 | if ( EFI_NOT_READY == Status ) {\r | |
1119 | pSocket->State = SOCKET_STATE_CONNECTING;\r | |
1120 | }\r | |
1121 | break;\r | |
1122 | \r | |
1123 | case SOCK_DGRAM:\r | |
1124 | Status = EslUdpConnect4 ( pSocket,\r | |
1125 | pSockAddr,\r | |
1126 | SockAddrLength );\r | |
1127 | break;\r | |
1128 | }\r | |
1129 | break;\r | |
1130 | }\r | |
1131 | break;\r | |
1132 | \r | |
1133 | case SOCKET_STATE_CONNECTING:\r | |
1134 | //\r | |
1135 | // Validate the local address\r | |
1136 | //\r | |
1137 | switch ( pSockAddr->sa_family ) {\r | |
1138 | default:\r | |
1139 | DEBUG (( DEBUG_CONNECT,\r | |
1140 | "ERROR - Invalid bind address family: %d\r\n",\r | |
1141 | pSockAddr->sa_family ));\r | |
1142 | Status = EFI_INVALID_PARAMETER;\r | |
1143 | pSocket->errno = EADDRNOTAVAIL;\r | |
1144 | break;\r | |
1145 | \r | |
1146 | case AF_INET:\r | |
1147 | //\r | |
1148 | // Determine the connection point within the network stack\r | |
1149 | //\r | |
1150 | switch ( pSocket->Type ) {\r | |
1151 | default:\r | |
1152 | DEBUG (( DEBUG_CONNECT,\r | |
1153 | "ERROR - Invalid socket type: %d\r\n",\r | |
1154 | pSocket->Type));\r | |
1155 | Status = EFI_INVALID_PARAMETER;\r | |
1156 | pSocket->errno = EADDRNOTAVAIL;\r | |
1157 | break;\r | |
1158 | \r | |
1159 | case SOCK_STREAM:\r | |
1160 | case SOCK_SEQPACKET:\r | |
1161 | //\r | |
1162 | // Determine if the connection processing is completed\r | |
1163 | //\r | |
1164 | Status = EslTcpConnectPoll4 ( pSocket );\r | |
1165 | \r | |
1166 | //\r | |
1167 | // Set the next state if connected\r | |
1168 | //\r | |
1169 | if ( EFI_NOT_READY != Status ) {\r | |
1170 | if ( !EFI_ERROR ( Status )) {\r | |
1171 | pSocket->State = SOCKET_STATE_CONNECTED;\r | |
1172 | }\r | |
1173 | else {\r | |
1174 | pSocket->State = SOCKET_STATE_BOUND;\r | |
1175 | }\r | |
1176 | }\r | |
1177 | break;\r | |
1178 | \r | |
1179 | case SOCK_DGRAM:\r | |
1180 | //\r | |
1181 | // Already connected\r | |
1182 | //\r | |
1183 | pSocket->errno = EISCONN;\r | |
1184 | Status = EFI_ALREADY_STARTED;\r | |
1185 | break;\r | |
1186 | }\r | |
1187 | break;\r | |
1188 | }\r | |
1189 | break;\r | |
1190 | \r | |
1191 | case SOCKET_STATE_CONNECTED:\r | |
1192 | //\r | |
1193 | // Already connected\r | |
1194 | //\r | |
1195 | pSocket->errno = EISCONN;\r | |
1196 | Status = EFI_ALREADY_STARTED;\r | |
1197 | break;\r | |
1198 | }\r | |
1199 | \r | |
1200 | //\r | |
1201 | // Release the socket layer synchronization\r | |
1202 | //\r | |
1203 | RESTORE_TPL ( TplPrevious );\r | |
1204 | }\r | |
1205 | }\r | |
1206 | \r | |
1207 | //\r | |
1208 | // Return the operation status\r | |
1209 | //\r | |
1210 | if ( NULL != pErrno ) {\r | |
1211 | if ( NULL != pSocket ) {\r | |
1212 | *pErrno = pSocket->errno;\r | |
1213 | }\r | |
1214 | else\r | |
1215 | {\r | |
1216 | //\r | |
1217 | // Bad socket protocol\r | |
1218 | //\r | |
1219 | DEBUG (( DEBUG_ERROR | DEBUG_CONNECT,\r | |
1220 | "ERROR - pSocketProtocol invalid!\r\n" ));\r | |
1221 | Status = EFI_INVALID_PARAMETER;\r | |
1222 | *pErrno = EBADF;\r | |
1223 | }\r | |
1224 | }\r | |
1225 | \r | |
1226 | //\r | |
1227 | // Return the operation status\r | |
1228 | //\r | |
1229 | DEBUG (( DEBUG_CONNECT, "Exiting SocketConnect, Status: %r\r\n", Status ));\r | |
1230 | return Status;\r | |
1231 | }\r | |
1232 | \r | |
1233 | \r | |
1234 | /**\r | |
1235 | Creates a child handle and installs a protocol.\r | |
1236 | \r | |
1237 | The CreateChild() function installs a protocol on ChildHandle. \r | |
1238 | If pChildHandle is a pointer to NULL, then a new handle is created and returned in pChildHandle. \r | |
1239 | If pChildHandle is not a pointer to NULL, then the protocol installs on the existing pChildHandle.\r | |
1240 | \r | |
1241 | @param [in] pThis Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r | |
1242 | @param [in] pChildHandle Pointer to the handle of the child to create. If it is NULL,\r | |
1243 | then a new handle is created. If it is a pointer to an existing UEFI handle, \r | |
1244 | then the protocol is added to the existing UEFI handle.\r | |
1245 | \r | |
1246 | @retval EFI_SUCCESS The protocol was added to ChildHandle.\r | |
1247 | @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r | |
1248 | @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r | |
1249 | the child\r | |
1250 | @retval other The child handle was not created\r | |
1251 | \r | |
1252 | **/\r | |
1253 | EFI_STATUS\r | |
1254 | EFIAPI\r | |
1255 | EslSocketCreateChild (\r | |
1256 | IN EFI_SERVICE_BINDING_PROTOCOL * pThis,\r | |
1257 | IN OUT EFI_HANDLE * pChildHandle\r | |
1258 | )\r | |
1259 | {\r | |
1260 | DT_SOCKET * pSocket;\r | |
1261 | EFI_STATUS Status;\r | |
1262 | \r | |
1263 | DBG_ENTER ( );\r | |
1264 | \r | |
1265 | //\r | |
1266 | // Create a socket structure\r | |
1267 | //\r | |
1268 | Status = EslSocketAllocate ( pChildHandle,\r | |
1269 | DEBUG_SOCKET,\r | |
1270 | &pSocket );\r | |
1271 | \r | |
1272 | //\r | |
1273 | // Return the operation status\r | |
1274 | //\r | |
1275 | DBG_EXIT_STATUS ( Status );\r | |
1276 | return Status;\r | |
1277 | }\r | |
1278 | \r | |
1279 | \r | |
1280 | /**\r | |
1281 | Destroys a child handle with a protocol installed on it.\r | |
1282 | \r | |
1283 | The DestroyChild() function does the opposite of CreateChild(). It removes a protocol \r | |
1284 | that was installed by CreateChild() from ChildHandle. If the removed protocol is the \r | |
1285 | last protocol on ChildHandle, then ChildHandle is destroyed.\r | |
1286 | \r | |
1287 | @param [in] pThis Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r | |
1288 | @param [in] ChildHandle Handle of the child to destroy\r | |
1289 | \r | |
1290 | @retval EFI_SUCCESS The protocol was removed from ChildHandle.\r | |
1291 | @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r | |
1292 | @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.\r | |
1293 | @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r | |
1294 | because its services are being used.\r | |
1295 | @retval other The child handle was not destroyed\r | |
1296 | \r | |
1297 | **/\r | |
1298 | EFI_STATUS\r | |
1299 | EFIAPI\r | |
1300 | EslSocketDestroyChild (\r | |
1301 | IN EFI_SERVICE_BINDING_PROTOCOL * pThis,\r | |
1302 | IN EFI_HANDLE ChildHandle\r | |
1303 | )\r | |
1304 | {\r | |
1305 | DT_LAYER * pLayer;\r | |
1306 | DT_SOCKET * pSocket;\r | |
1307 | DT_SOCKET * pSocketPrevious;\r | |
1308 | EFI_SOCKET_PROTOCOL * pSocketProtocol;\r | |
1309 | EFI_STATUS Status;\r | |
1310 | EFI_TPL TplPrevious;\r | |
1311 | \r | |
1312 | DBG_ENTER ( );\r | |
1313 | \r | |
1314 | //\r | |
1315 | // Locate the socket control structure\r | |
1316 | //\r | |
1317 | pLayer = &mEslLayer;\r | |
1318 | Status = gBS->OpenProtocol (\r | |
1319 | ChildHandle,\r | |
1320 | &gEfiSocketProtocolGuid,\r | |
1321 | (VOID **)&pSocketProtocol,\r | |
1322 | pLayer->ImageHandle,\r | |
1323 | NULL,\r | |
1324 | EFI_OPEN_PROTOCOL_GET_PROTOCOL\r | |
1325 | );\r | |
1326 | if ( !EFI_ERROR ( Status )) {\r | |
1327 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
1328 | \r | |
1329 | //\r | |
1330 | // Synchronize with the socket layer\r | |
1331 | //\r | |
1332 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
1333 | \r | |
1334 | //\r | |
1335 | // Walk the socket list\r | |
1336 | //\r | |
1337 | pSocketPrevious = pLayer->pSocketList;\r | |
1338 | if ( NULL != pSocketPrevious ) {\r | |
1339 | if ( pSocket == pSocketPrevious ) {\r | |
1340 | //\r | |
1341 | // Remove the socket from the head of the list\r | |
1342 | //\r | |
1343 | pLayer->pSocketList = pSocket->pNext;\r | |
1344 | }\r | |
1345 | else {\r | |
1346 | //\r | |
1347 | // Find the socket in the middle of the list\r | |
1348 | //\r | |
1349 | while (( NULL != pSocketPrevious )\r | |
1350 | && ( pSocket != pSocketPrevious->pNext )) {\r | |
1351 | //\r | |
1352 | // Set the next socket\r | |
1353 | //\r | |
1354 | pSocketPrevious = pSocketPrevious->pNext;\r | |
1355 | }\r | |
1356 | if ( NULL != pSocketPrevious ) {\r | |
1357 | //\r | |
1358 | // Remove the socket from the middle of the list\r | |
1359 | //\r | |
1360 | pSocketPrevious = pSocket->pNext;\r | |
1361 | }\r | |
1362 | }\r | |
1363 | }\r | |
1364 | else {\r | |
1365 | DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r | |
1366 | "ERROR - Socket list is empty!\r\n" ));\r | |
1367 | }\r | |
1368 | \r | |
1369 | //\r | |
1370 | // Release the socket layer synchronization\r | |
1371 | //\r | |
1372 | RESTORE_TPL ( TplPrevious );\r | |
1373 | \r | |
1374 | //\r | |
1375 | // Determine if the socket was found\r | |
1376 | //\r | |
1377 | if ( NULL != pSocketPrevious ) {\r | |
1378 | pSocket->pNext = NULL;\r | |
1379 | \r | |
1380 | //\r | |
1381 | // Remove the socket protocol\r | |
1382 | //\r | |
1383 | Status = gBS->UninstallMultipleProtocolInterfaces (\r | |
1384 | ChildHandle,\r | |
1385 | &gEfiSocketProtocolGuid,\r | |
1386 | &pSocket->SocketProtocol,\r | |
1387 | NULL );\r | |
1388 | if ( !EFI_ERROR ( Status )) {\r | |
1389 | DEBUG (( DEBUG_POOL | DEBUG_INFO,\r | |
1390 | "Removed: gEfiSocketProtocolGuid from 0x%08x\r\n",\r | |
1391 | ChildHandle ));\r | |
1392 | \r | |
1393 | //\r | |
1394 | // Free the socket structure\r | |
1395 | //\r | |
1396 | Status = gBS->FreePool ( pSocket );\r | |
1397 | if ( !EFI_ERROR ( Status )) {\r | |
1398 | DEBUG (( DEBUG_POOL,\r | |
1399 | "0x%08x: Free pSocket, %d bytes\r\n",\r | |
1400 | pSocket,\r | |
1401 | sizeof ( *pSocket )));\r | |
1402 | }\r | |
1403 | else {\r | |
1404 | DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r | |
1405 | "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",\r | |
1406 | pSocket,\r | |
1407 | Status ));\r | |
1408 | }\r | |
1409 | }\r | |
1410 | else {\r | |
1411 | DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,\r | |
1412 | "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",\r | |
1413 | ChildHandle,\r | |
1414 | Status ));\r | |
1415 | }\r | |
1416 | }\r | |
1417 | else {\r | |
1418 | DEBUG (( DEBUG_ERROR | DEBUG_INFO,\r | |
1419 | "ERROR - The socket was not in the socket list!\r\n" ));\r | |
1420 | Status = EFI_NOT_FOUND;\r | |
1421 | }\r | |
1422 | }\r | |
1423 | else {\r | |
1424 | DEBUG (( DEBUG_ERROR,\r | |
1425 | "ERROR - Failed to open socket protocol on 0x%08x, Status; %r\r\n",\r | |
1426 | ChildHandle,\r | |
1427 | Status ));\r | |
1428 | }\r | |
1429 | \r | |
1430 | //\r | |
1431 | // Return the operation status\r | |
1432 | //\r | |
1433 | DBG_EXIT_STATUS ( Status );\r | |
1434 | return Status;\r | |
1435 | }\r | |
1436 | \r | |
1437 | \r | |
1438 | /**\r | |
1439 | Get the local address.\r | |
1440 | \r | |
1441 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
1442 | \r | |
1443 | @param [out] pAddress Network address to receive the local system address\r | |
1444 | \r | |
1445 | @param [in,out] pAddressLength Length of the local network address structure\r | |
1446 | \r | |
1447 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
1448 | \r | |
1449 | @retval EFI_SUCCESS - Local address successfully returned\r | |
1450 | \r | |
1451 | **/\r | |
1452 | EFI_STATUS\r | |
1453 | EslSocketGetLocalAddress (\r | |
1454 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
1455 | OUT struct sockaddr * pAddress,\r | |
1456 | IN OUT socklen_t * pAddressLength,\r | |
1457 | IN int * pErrno\r | |
1458 | )\r | |
1459 | {\r | |
1460 | DT_SOCKET * pSocket;\r | |
1461 | EFI_STATUS Status;\r | |
1462 | EFI_TPL TplPrevious;\r | |
1463 | \r | |
1464 | DBG_ENTER ( );\r | |
1465 | \r | |
1466 | //\r | |
1467 | // Assume success\r | |
1468 | //\r | |
1469 | Status = EFI_SUCCESS;\r | |
1470 | \r | |
1471 | //\r | |
1472 | // Validate the socket\r | |
1473 | //\r | |
1474 | pSocket = NULL;\r | |
1475 | if ( NULL != pSocketProtocol ) {\r | |
1476 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
1477 | \r | |
1478 | //\r | |
1479 | // Verify the address buffer and length address\r | |
1480 | //\r | |
1481 | if (( NULL != pAddress ) && ( NULL != pAddressLength )) {\r | |
1482 | //\r | |
1483 | // Verify the socket state\r | |
1484 | //\r | |
1485 | if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r | |
1486 | //\r | |
1487 | // Synchronize with the socket layer\r | |
1488 | //\r | |
1489 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
1490 | \r | |
1491 | //\r | |
1492 | // Validate the local address\r | |
1493 | //\r | |
1494 | switch ( pSocket->Domain ) {\r | |
1495 | default:\r | |
1496 | DEBUG (( DEBUG_RX,\r | |
1497 | "ERROR - Invalid socket address family: %d\r\n",\r | |
1498 | pSocket->Domain ));\r | |
1499 | Status = EFI_INVALID_PARAMETER;\r | |
1500 | pSocket->errno = EADDRNOTAVAIL;\r | |
1501 | break;\r | |
1502 | \r | |
1503 | case AF_INET:\r | |
1504 | //\r | |
1505 | // Determine the connection point within the network stack\r | |
1506 | //\r | |
1507 | switch ( pSocket->Type ) {\r | |
1508 | default:\r | |
1509 | DEBUG (( DEBUG_RX,\r | |
1510 | "ERROR - Invalid socket type: %d\r\n",\r | |
1511 | pSocket->Type));\r | |
1512 | Status = EFI_INVALID_PARAMETER;\r | |
1513 | break;\r | |
1514 | \r | |
1515 | case SOCK_STREAM:\r | |
1516 | case SOCK_SEQPACKET:\r | |
1517 | //\r | |
1518 | // Get the local address\r | |
1519 | //\r | |
1520 | Status = EslTcpGetLocalAddress4 ( pSocket,\r | |
1521 | pAddress,\r | |
1522 | pAddressLength );\r | |
1523 | break;\r | |
1524 | \r | |
1525 | case SOCK_DGRAM:\r | |
1526 | //\r | |
1527 | // Get the local address\r | |
1528 | //\r | |
1529 | Status = EslUdpGetLocalAddress4 ( pSocket,\r | |
1530 | pAddress,\r | |
1531 | pAddressLength );\r | |
1532 | break;\r | |
1533 | }\r | |
1534 | break;\r | |
1535 | }\r | |
1536 | \r | |
1537 | //\r | |
1538 | // Release the socket layer synchronization\r | |
1539 | //\r | |
1540 | RESTORE_TPL ( TplPrevious );\r | |
1541 | }\r | |
1542 | else {\r | |
1543 | pSocket->errno = ENOTCONN;\r | |
1544 | Status = EFI_NOT_STARTED;\r | |
1545 | }\r | |
1546 | }\r | |
1547 | else {\r | |
1548 | pSocket->errno = EINVAL;\r | |
1549 | Status = EFI_INVALID_PARAMETER;\r | |
1550 | }\r | |
1551 | }\r | |
1552 | \r | |
1553 | //\r | |
1554 | // Return the operation status\r | |
1555 | //\r | |
1556 | if ( NULL != pErrno ) {\r | |
1557 | if ( NULL != pSocket ) {\r | |
1558 | *pErrno = pSocket->errno;\r | |
1559 | }\r | |
1560 | else\r | |
1561 | {\r | |
1562 | Status = EFI_INVALID_PARAMETER;\r | |
1563 | *pErrno = EBADF;\r | |
1564 | }\r | |
1565 | }\r | |
1566 | DBG_EXIT_STATUS ( Status );\r | |
1567 | return Status;\r | |
1568 | }\r | |
1569 | \r | |
1570 | \r | |
1571 | /**\r | |
1572 | Get the peer address.\r | |
1573 | \r | |
1574 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
1575 | \r | |
1576 | @param [out] pAddress Network address to receive the remote system address\r | |
1577 | \r | |
1578 | @param [in,out] pAddressLength Length of the remote network address structure\r | |
1579 | \r | |
1580 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
1581 | \r | |
1582 | @retval EFI_SUCCESS - Remote address successfully returned\r | |
1583 | \r | |
1584 | **/\r | |
1585 | EFI_STATUS\r | |
1586 | EslSocketGetPeerAddress (\r | |
1587 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
1588 | OUT struct sockaddr * pAddress,\r | |
1589 | IN OUT socklen_t * pAddressLength,\r | |
1590 | IN int * pErrno\r | |
1591 | )\r | |
1592 | {\r | |
1593 | DT_SOCKET * pSocket;\r | |
1594 | EFI_STATUS Status;\r | |
1595 | EFI_TPL TplPrevious;\r | |
1596 | \r | |
1597 | DBG_ENTER ( );\r | |
1598 | \r | |
1599 | //\r | |
1600 | // Assume success\r | |
1601 | //\r | |
1602 | Status = EFI_SUCCESS;\r | |
1603 | \r | |
1604 | //\r | |
1605 | // Validate the socket\r | |
1606 | //\r | |
1607 | pSocket = NULL;\r | |
1608 | if ( NULL != pSocketProtocol ) {\r | |
1609 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
1610 | \r | |
1611 | //\r | |
1612 | // Verify the address buffer and length address\r | |
1613 | //\r | |
1614 | if (( NULL != pAddress ) && ( NULL != pAddressLength )) {\r | |
1615 | //\r | |
1616 | // Verify the socket state\r | |
1617 | //\r | |
1618 | if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r | |
1619 | //\r | |
1620 | // Synchronize with the socket layer\r | |
1621 | //\r | |
1622 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
1623 | \r | |
1624 | //\r | |
1625 | // Validate the local address\r | |
1626 | //\r | |
1627 | switch ( pSocket->Domain ) {\r | |
1628 | default:\r | |
1629 | DEBUG (( DEBUG_RX,\r | |
1630 | "ERROR - Invalid socket address family: %d\r\n",\r | |
1631 | pSocket->Domain ));\r | |
1632 | Status = EFI_INVALID_PARAMETER;\r | |
1633 | pSocket->errno = EADDRNOTAVAIL;\r | |
1634 | break;\r | |
1635 | \r | |
1636 | case AF_INET:\r | |
1637 | //\r | |
1638 | // Determine the connection point within the network stack\r | |
1639 | //\r | |
1640 | switch ( pSocket->Type ) {\r | |
1641 | default:\r | |
1642 | DEBUG (( DEBUG_RX,\r | |
1643 | "ERROR - Invalid socket type: %d\r\n",\r | |
1644 | pSocket->Type));\r | |
1645 | Status = EFI_INVALID_PARAMETER;\r | |
1646 | break;\r | |
1647 | \r | |
1648 | case SOCK_STREAM:\r | |
1649 | case SOCK_SEQPACKET:\r | |
1650 | //\r | |
1651 | // Verify the port state\r | |
1652 | //\r | |
1653 | Status = EslTcpGetRemoteAddress4 ( pSocket,\r | |
1654 | pAddress,\r | |
1655 | pAddressLength );\r | |
1656 | break;\r | |
1657 | \r | |
1658 | case SOCK_DGRAM:\r | |
1659 | //\r | |
1660 | // Verify the port state\r | |
1661 | //\r | |
1662 | Status = EslUdpGetRemoteAddress4 ( pSocket,\r | |
1663 | pAddress,\r | |
1664 | pAddressLength );\r | |
1665 | break;\r | |
1666 | }\r | |
1667 | break;\r | |
1668 | }\r | |
1669 | \r | |
1670 | //\r | |
1671 | // Release the socket layer synchronization\r | |
1672 | //\r | |
1673 | RESTORE_TPL ( TplPrevious );\r | |
1674 | }\r | |
1675 | else {\r | |
1676 | pSocket->errno = ENOTCONN;\r | |
1677 | Status = EFI_NOT_STARTED;\r | |
1678 | }\r | |
1679 | }\r | |
1680 | else {\r | |
1681 | pSocket->errno = EINVAL;\r | |
1682 | Status = EFI_INVALID_PARAMETER;\r | |
1683 | }\r | |
1684 | }\r | |
1685 | \r | |
1686 | //\r | |
1687 | // Return the operation status\r | |
1688 | //\r | |
1689 | if ( NULL != pErrno ) {\r | |
1690 | if ( NULL != pSocket ) {\r | |
1691 | *pErrno = pSocket->errno;\r | |
1692 | }\r | |
1693 | else\r | |
1694 | {\r | |
1695 | Status = EFI_INVALID_PARAMETER;\r | |
1696 | *pErrno = EBADF;\r | |
1697 | }\r | |
1698 | }\r | |
1699 | DBG_EXIT_STATUS ( Status );\r | |
1700 | return Status;\r | |
1701 | }\r | |
1702 | \r | |
1703 | \r | |
1704 | /**\r | |
1705 | Establish the known port to listen for network connections.\r | |
1706 | \r | |
1707 | The ::SocketListen routine places the port into a state that enables connection\r | |
1708 | attempts. Connections are placed into FIFO order in a queue to be serviced\r | |
1709 | by the application. The application calls the ::SocketAccept routine to remove\r | |
1710 | the next connection from the queue and get the associated socket. The\r | |
1711 | <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html">POSIX</a>\r | |
1712 | documentation for the listen routine is available online for reference.\r | |
1713 | \r | |
1714 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
1715 | \r | |
1716 | @param [in] Backlog Backlog specifies the maximum FIFO depth for\r | |
1717 | the connections waiting for the application\r | |
1718 | to call accept. Connection attempts received\r | |
1719 | while the queue is full are refused.\r | |
1720 | \r | |
1721 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
1722 | \r | |
1723 | @retval EFI_SUCCESS - Socket successfully created\r | |
1724 | @retval Other - Failed to enable the socket for listen\r | |
1725 | \r | |
1726 | **/\r | |
1727 | EFI_STATUS\r | |
1728 | EslSocketListen (\r | |
1729 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
1730 | IN INT32 Backlog,\r | |
1731 | OUT int * pErrno\r | |
1732 | )\r | |
1733 | {\r | |
1734 | DT_SOCKET * pSocket;\r | |
1735 | EFI_STATUS Status;\r | |
1736 | EFI_STATUS TempStatus;\r | |
1737 | EFI_TPL TplPrevious;\r | |
1738 | \r | |
1739 | DBG_ENTER ( );\r | |
1740 | \r | |
1741 | //\r | |
1742 | // Assume success\r | |
1743 | //\r | |
1744 | Status = EFI_SUCCESS;\r | |
1745 | \r | |
1746 | //\r | |
1747 | // Validate the socket\r | |
1748 | //\r | |
1749 | pSocket = NULL;\r | |
1750 | if ( NULL != pSocketProtocol ) {\r | |
1751 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
1752 | \r | |
1753 | //\r | |
1754 | // Assume success\r | |
1755 | //\r | |
1756 | pSocket->Status = EFI_SUCCESS;\r | |
1757 | pSocket->errno = 0;\r | |
1758 | \r | |
1759 | //\r | |
1760 | // Verify that the bind operation was successful\r | |
1761 | //\r | |
1762 | if ( SOCKET_STATE_BOUND == pSocket->State ) {\r | |
1763 | //\r | |
1764 | // Synchronize with the socket layer\r | |
1765 | //\r | |
1766 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
1767 | \r | |
1768 | //\r | |
1769 | // Create the event for SocketAccept completion\r | |
1770 | //\r | |
1771 | Status = gBS->CreateEvent ( 0,\r | |
1772 | TplPrevious,\r | |
1773 | NULL,\r | |
1774 | NULL,\r | |
1775 | &pSocket->WaitAccept );\r | |
1776 | if ( !EFI_ERROR ( Status )) {\r | |
1777 | DEBUG (( DEBUG_POOL,\r | |
1778 | "0x%08x: Created WaitAccept event\r\n",\r | |
1779 | pSocket->WaitAccept ));\r | |
1780 | //\r | |
1781 | // Set the maximum FIFO depth\r | |
1782 | //\r | |
1783 | if ( 0 >= Backlog ) {\r | |
1784 | Backlog = MAX_PENDING_CONNECTIONS;\r | |
1785 | }\r | |
1786 | else {\r | |
1787 | if ( SOMAXCONN < Backlog ) {\r | |
1788 | Backlog = SOMAXCONN;\r | |
1789 | }\r | |
1790 | else {\r | |
1791 | pSocket->MaxFifoDepth = Backlog;\r | |
1792 | }\r | |
1793 | }\r | |
1794 | \r | |
1795 | //\r | |
1796 | // Validate the local address\r | |
1797 | //\r | |
1798 | switch ( pSocket->Domain ) {\r | |
1799 | default:\r | |
1800 | DEBUG (( DEBUG_BIND,\r | |
1801 | "ERROR - Invalid socket address family: %d\r\n",\r | |
1802 | pSocket->Domain ));\r | |
1803 | Status = EFI_INVALID_PARAMETER;\r | |
1804 | pSocket->errno = EADDRNOTAVAIL;\r | |
1805 | break;\r | |
1806 | \r | |
1807 | case AF_INET:\r | |
1808 | //\r | |
1809 | // Determine the connection point within the network stack\r | |
1810 | //\r | |
1811 | switch ( pSocket->Type ) {\r | |
1812 | default:\r | |
1813 | DEBUG (( DEBUG_BIND,\r | |
1814 | "ERROR - Invalid socket type: %d\r\n",\r | |
1815 | pSocket->Type));\r | |
1816 | Status = EFI_INVALID_PARAMETER;\r | |
1817 | pSocket->errno = EADDRNOTAVAIL;\r | |
1818 | break;\r | |
1819 | \r | |
1820 | case SOCK_STREAM:\r | |
1821 | case SOCK_SEQPACKET:\r | |
1822 | Status = EslTcpListen4 ( pSocket );\r | |
1823 | break;\r | |
1824 | \r | |
1825 | /*\r | |
1826 | case SOCK_DGRAM:\r | |
1827 | Status = UdpListen4 ( pSocket );\r | |
1828 | break;\r | |
1829 | */\r | |
1830 | }\r | |
1831 | break;\r | |
1832 | }\r | |
1833 | \r | |
1834 | //\r | |
1835 | // Place the socket in the listen state if successful\r | |
1836 | //\r | |
1837 | if ( !EFI_ERROR ( Status )) {\r | |
1838 | pSocket->State = SOCKET_STATE_LISTENING;\r | |
1839 | }\r | |
1840 | else {\r | |
1841 | //\r | |
1842 | // Not waiting for SocketAccept to complete\r | |
1843 | //\r | |
1844 | TempStatus = gBS->CloseEvent ( pSocket->WaitAccept );\r | |
1845 | if ( !EFI_ERROR ( TempStatus )) {\r | |
1846 | DEBUG (( DEBUG_POOL,\r | |
1847 | "0x%08x: Closed WaitAccept event\r\n",\r | |
1848 | pSocket->WaitAccept ));\r | |
1849 | pSocket->WaitAccept = NULL;\r | |
1850 | }\r | |
1851 | else {\r | |
1852 | DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r | |
1853 | "ERROR - Failed to close WaitAccept event, Status: %r\r\n",\r | |
1854 | TempStatus ));\r | |
1855 | ASSERT ( EFI_SUCCESS == TempStatus );\r | |
1856 | }\r | |
1857 | }\r | |
1858 | }\r | |
1859 | else {\r | |
1860 | DEBUG (( DEBUG_ERROR | DEBUG_LISTEN,\r | |
1861 | "ERROR - Failed to create the WaitAccept event, Status: %r\r\n",\r | |
1862 | Status ));\r | |
1863 | pSocket->errno = ENOMEM;\r | |
1864 | }\r | |
1865 | \r | |
1866 | //\r | |
1867 | // Release the socket layer synchronization\r | |
1868 | //\r | |
1869 | RESTORE_TPL ( TplPrevious );\r | |
1870 | }\r | |
1871 | else {\r | |
1872 | DEBUG (( DEBUG_ERROR | DEBUG_LISTEN,\r | |
1873 | "ERROR - Bind operation must be performed first!\r\n" ));\r | |
1874 | pSocket->errno = EDESTADDRREQ;\r | |
1875 | }\r | |
1876 | }\r | |
1877 | \r | |
1878 | //\r | |
1879 | // Return the operation status\r | |
1880 | //\r | |
1881 | if ( NULL != pErrno ) {\r | |
1882 | if ( NULL != pSocket ) {\r | |
1883 | *pErrno = pSocket->errno;\r | |
1884 | }\r | |
1885 | else\r | |
1886 | {\r | |
1887 | Status = EFI_INVALID_PARAMETER;\r | |
1888 | *pErrno = EBADF;\r | |
1889 | }\r | |
1890 | }\r | |
1891 | DBG_EXIT_STATUS ( Status );\r | |
1892 | return Status;\r | |
1893 | }\r | |
1894 | \r | |
1895 | \r | |
1896 | /**\r | |
1897 | Get the socket options\r | |
1898 | \r | |
1899 | Retrieve the socket options one at a time by name. The\r | |
1900 | <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html">POSIX</a>\r | |
1901 | documentation is available online.\r | |
1902 | \r | |
1903 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
1904 | @param [in] level Option protocol level\r | |
1905 | @param [in] OptionName Name of the option\r | |
1906 | @param [out] pOptionValue Buffer to receive the option value\r | |
1907 | @param [in,out] pOptionLength Length of the buffer in bytes,\r | |
1908 | upon return length of the option value in bytes\r | |
1909 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
1910 | \r | |
1911 | @retval EFI_SUCCESS - Socket data successfully received\r | |
1912 | \r | |
1913 | **/\r | |
1914 | EFI_STATUS\r | |
1915 | EslSocketOptionGet (\r | |
1916 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
1917 | IN int level,\r | |
1918 | IN int OptionName,\r | |
1919 | OUT void * __restrict pOptionValue,\r | |
1920 | IN OUT socklen_t * __restrict pOptionLength,\r | |
1921 | IN int * pErrno\r | |
1922 | )\r | |
1923 | {\r | |
1924 | int errno;\r | |
1925 | socklen_t LengthInBytes;\r | |
1926 | socklen_t MaxBytes;\r | |
1927 | UINT8 * pOptionData;\r | |
1928 | DT_SOCKET * pSocket;\r | |
1929 | EFI_STATUS Status;\r | |
1930 | \r | |
1931 | DBG_ENTER ( );\r | |
1932 | \r | |
1933 | //\r | |
1934 | // Assume failure\r | |
1935 | //\r | |
1936 | errno = EINVAL;\r | |
1937 | Status = EFI_INVALID_PARAMETER;\r | |
1938 | \r | |
1939 | //\r | |
1940 | // Validate the socket\r | |
1941 | //\r | |
1942 | pSocket = NULL;\r | |
1943 | if (( NULL != pSocketProtocol )\r | |
1944 | && ( NULL != pOptionValue )\r | |
1945 | && ( NULL != pOptionLength )) {\r | |
1946 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
1947 | LengthInBytes = 0;\r | |
1948 | MaxBytes = *pOptionLength;\r | |
1949 | pOptionData = NULL;\r | |
1950 | switch ( level ) {\r | |
1951 | default:\r | |
1952 | //\r | |
1953 | // Protocol level not supported\r | |
1954 | //\r | |
1955 | errno = ENOTSUP;\r | |
1956 | Status = EFI_UNSUPPORTED;\r | |
1957 | break;\r | |
1958 | \r | |
1959 | case SOL_SOCKET:\r | |
1960 | switch ( OptionName ) {\r | |
1961 | default:\r | |
1962 | //\r | |
1963 | // Option not supported\r | |
1964 | //\r | |
1965 | errno = ENOTSUP;\r | |
1966 | Status = EFI_UNSUPPORTED;\r | |
1967 | break;\r | |
1968 | \r | |
1969 | case SO_RCVTIMEO:\r | |
1970 | //\r | |
1971 | // Return the receive timeout\r | |
1972 | //\r | |
1973 | pOptionData = (UINT8 *)&pSocket->RxTimeout;\r | |
1974 | LengthInBytes = sizeof ( pSocket->RxTimeout );\r | |
1975 | break;\r | |
1976 | \r | |
1977 | case SO_RCVBUF:\r | |
1978 | //\r | |
1979 | // Return the maximum transmit buffer size\r | |
1980 | //\r | |
1981 | pOptionData = (UINT8 *)&pSocket->MaxRxBuf;\r | |
1982 | LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r | |
1983 | break;\r | |
1984 | \r | |
1985 | case SO_SNDBUF:\r | |
1986 | //\r | |
1987 | // Return the maximum transmit buffer size\r | |
1988 | //\r | |
1989 | pOptionData = (UINT8 *)&pSocket->MaxTxBuf;\r | |
1990 | LengthInBytes = sizeof ( pSocket->MaxTxBuf );\r | |
1991 | break;\r | |
1992 | \r | |
1993 | case SO_TYPE:\r | |
1994 | //\r | |
1995 | // Return the socket type\r | |
1996 | //\r | |
1997 | pOptionData = (UINT8 *)&pSocket->Type;\r | |
1998 | LengthInBytes = sizeof ( pSocket->Type );\r | |
1999 | break;\r | |
2000 | }\r | |
2001 | break;\r | |
2002 | }\r | |
2003 | \r | |
2004 | //\r | |
2005 | // Return the option length\r | |
2006 | //\r | |
2007 | *pOptionLength = LengthInBytes;\r | |
2008 | \r | |
2009 | //\r | |
2010 | // Return the option value\r | |
2011 | //\r | |
2012 | if ( NULL != pOptionData ) {\r | |
2013 | //\r | |
2014 | // Silently truncate the value length\r | |
2015 | //\r | |
2016 | if ( LengthInBytes > MaxBytes ) {\r | |
2017 | LengthInBytes = MaxBytes;\r | |
2018 | }\r | |
2019 | CopyMem ( pOptionValue, pOptionData, LengthInBytes );\r | |
2020 | errno = 0;\r | |
2021 | Status = EFI_SUCCESS;\r | |
2022 | }\r | |
2023 | }\r | |
2024 | \r | |
2025 | //\r | |
2026 | // Return the operation status\r | |
2027 | //\r | |
2028 | if ( NULL != pErrno ) {\r | |
2029 | *pErrno = errno;\r | |
2030 | }\r | |
2031 | DBG_EXIT_STATUS ( Status );\r | |
2032 | return Status;\r | |
2033 | }\r | |
2034 | \r | |
2035 | \r | |
2036 | /**\r | |
2037 | Set the socket options\r | |
2038 | \r | |
2039 | Adjust the socket options one at a time by name. The\r | |
2040 | <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html">POSIX</a>\r | |
2041 | documentation is available online.\r | |
2042 | \r | |
2043 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
2044 | @param [in] level Option protocol level\r | |
2045 | @param [in] OptionName Name of the option\r | |
2046 | @param [in] pOptionValue Buffer containing the option value\r | |
2047 | @param [in] OptionLength Length of the buffer in bytes\r | |
2048 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
2049 | \r | |
2050 | @retval EFI_SUCCESS - Socket data successfully received\r | |
2051 | \r | |
2052 | **/\r | |
2053 | EFI_STATUS\r | |
2054 | EslSocketOptionSet (\r | |
2055 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
2056 | IN int level,\r | |
2057 | IN int OptionName,\r | |
2058 | IN CONST void * pOptionValue,\r | |
2059 | IN socklen_t OptionLength,\r | |
2060 | IN int * pErrno\r | |
2061 | )\r | |
2062 | {\r | |
2063 | int errno;\r | |
2064 | socklen_t LengthInBytes;\r | |
2065 | UINT8 * pOptionData;\r | |
2066 | DT_SOCKET * pSocket;\r | |
2067 | EFI_STATUS Status;\r | |
2068 | \r | |
2069 | DBG_ENTER ( );\r | |
2070 | \r | |
2071 | //\r | |
2072 | // Assume failure\r | |
2073 | //\r | |
2074 | errno = EINVAL;\r | |
2075 | Status = EFI_INVALID_PARAMETER;\r | |
2076 | \r | |
2077 | //\r | |
2078 | // Validate the socket\r | |
2079 | //\r | |
2080 | pSocket = NULL;\r | |
2081 | if (( NULL != pSocketProtocol )\r | |
2082 | && ( NULL != pOptionValue )) {\r | |
2083 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
2084 | LengthInBytes = 0;\r | |
2085 | pOptionData = NULL;\r | |
2086 | switch ( level ) {\r | |
2087 | default:\r | |
2088 | //\r | |
2089 | // Protocol level not supported\r | |
2090 | //\r | |
2091 | errno = ENOTSUP;\r | |
2092 | Status = EFI_UNSUPPORTED;\r | |
2093 | break;\r | |
2094 | \r | |
2095 | case SOL_SOCKET:\r | |
2096 | switch ( OptionName ) {\r | |
2097 | default:\r | |
2098 | //\r | |
2099 | // Option not supported\r | |
2100 | //\r | |
2101 | errno = ENOTSUP;\r | |
2102 | Status = EFI_UNSUPPORTED;\r | |
2103 | break;\r | |
2104 | \r | |
2105 | case SO_RCVTIMEO:\r | |
2106 | //\r | |
2107 | // Return the receive timeout\r | |
2108 | //\r | |
2109 | pOptionData = (UINT8 *)&pSocket->RxTimeout;\r | |
2110 | LengthInBytes = sizeof ( pSocket->RxTimeout );\r | |
2111 | break;\r | |
2112 | \r | |
2113 | case SO_RCVBUF:\r | |
2114 | //\r | |
2115 | // Return the maximum transmit buffer size\r | |
2116 | //\r | |
2117 | pOptionData = (UINT8 *)&pSocket->MaxRxBuf;\r | |
2118 | LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r | |
2119 | break;\r | |
2120 | \r | |
2121 | case SO_SNDBUF:\r | |
2122 | //\r | |
2123 | // Send buffer size\r | |
2124 | //\r | |
2125 | //\r | |
2126 | // Return the maximum transmit buffer size\r | |
2127 | //\r | |
2128 | pOptionData = (UINT8 *)&pSocket->MaxTxBuf;\r | |
2129 | LengthInBytes = sizeof ( pSocket->MaxTxBuf );\r | |
2130 | break;\r | |
2131 | }\r | |
2132 | break;\r | |
2133 | }\r | |
2134 | \r | |
2135 | //\r | |
2136 | // Validate the option length\r | |
2137 | //\r | |
2138 | if ( LengthInBytes <= OptionLength ) {\r | |
2139 | //\r | |
2140 | // Set the option value\r | |
2141 | //\r | |
2142 | if ( NULL != pOptionData ) {\r | |
2143 | CopyMem ( pOptionData, pOptionValue, LengthInBytes );\r | |
2144 | errno = 0;\r | |
2145 | Status = EFI_SUCCESS;\r | |
2146 | }\r | |
2147 | }\r | |
2148 | }\r | |
2149 | \r | |
2150 | //\r | |
2151 | // Return the operation status\r | |
2152 | //\r | |
2153 | if ( NULL != pErrno ) {\r | |
2154 | *pErrno = errno;\r | |
2155 | }\r | |
2156 | DBG_EXIT_STATUS ( Status );\r | |
2157 | return Status;\r | |
2158 | }\r | |
2159 | \r | |
2160 | \r | |
2161 | /**\r | |
2162 | Allocate a packet for a receive or transmit operation\r | |
2163 | \r | |
2164 | @param [in] ppPacket Address to receive the DT_PACKET structure\r | |
2165 | @param [in] LengthInBytes Length of the packet structure\r | |
2166 | @param [in] DebugFlags Flags for debug messages\r | |
2167 | \r | |
2168 | @retval EFI_SUCCESS - The packet was allocated successfully\r | |
2169 | \r | |
2170 | **/\r | |
2171 | EFI_STATUS\r | |
2172 | EslSocketPacketAllocate (\r | |
2173 | IN DT_PACKET ** ppPacket,\r | |
2174 | IN size_t LengthInBytes,\r | |
2175 | IN UINTN DebugFlags\r | |
2176 | )\r | |
2177 | {\r | |
2178 | DT_PACKET * pPacket;\r | |
2179 | EFI_STATUS Status;\r | |
2180 | \r | |
2181 | DBG_ENTER ( );\r | |
2182 | \r | |
2183 | //\r | |
2184 | // Allocate a packet structure\r | |
2185 | //\r | |
2186 | LengthInBytes += sizeof ( *pPacket )\r | |
2187 | - sizeof ( pPacket->Op );\r | |
2188 | Status = gBS->AllocatePool ( EfiRuntimeServicesData,\r | |
2189 | LengthInBytes,\r | |
2190 | (VOID **)&pPacket );\r | |
2191 | if ( !EFI_ERROR ( Status )) {\r | |
2192 | DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,\r | |
2193 | "0x%08x: Allocate pPacket, %d bytes\r\n",\r | |
2194 | pPacket,\r | |
2195 | LengthInBytes ));\r | |
2196 | pPacket->PacketSize = LengthInBytes;\r | |
2197 | }\r | |
2198 | else {\r | |
2199 | DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INFO,\r | |
2200 | "ERROR - Packet allocation failed for %d bytes, Status: %r\r\n",\r | |
2201 | LengthInBytes,\r | |
2202 | Status ));\r | |
2203 | pPacket = NULL;\r | |
2204 | }\r | |
2205 | \r | |
2206 | //\r | |
2207 | // Return the packet\r | |
2208 | //\r | |
2209 | *ppPacket = pPacket;\r | |
2210 | \r | |
2211 | //\r | |
2212 | // Return the operation status\r | |
2213 | //\r | |
2214 | DBG_EXIT_STATUS ( Status );\r | |
2215 | return Status;\r | |
2216 | }\r | |
2217 | \r | |
2218 | \r | |
2219 | /**\r | |
2220 | Free a packet used for receive or transmit operation\r | |
2221 | \r | |
2222 | @param [in] pPacket Address of the DT_PACKET structure\r | |
2223 | @param [in] DebugFlags Flags for debug messages\r | |
2224 | \r | |
2225 | @retval EFI_SUCCESS - The packet was allocated successfully\r | |
2226 | \r | |
2227 | **/\r | |
2228 | EFI_STATUS\r | |
2229 | EslSocketPacketFree (\r | |
2230 | IN DT_PACKET * pPacket,\r | |
2231 | IN UINTN DebugFlags\r | |
2232 | )\r | |
2233 | {\r | |
2234 | UINTN LengthInBytes;\r | |
2235 | EFI_STATUS Status;\r | |
2236 | \r | |
2237 | DBG_ENTER ( );\r | |
2238 | \r | |
2239 | //\r | |
2240 | // Allocate a packet structure\r | |
2241 | //\r | |
2242 | LengthInBytes = pPacket->PacketSize;\r | |
2243 | Status = gBS->FreePool ( pPacket );\r | |
2244 | if ( !EFI_ERROR ( Status )) {\r | |
2245 | DEBUG (( DebugFlags | DEBUG_POOL,\r | |
2246 | "0x%08x: Free pPacket, %d bytes\r\n",\r | |
2247 | pPacket,\r | |
2248 | LengthInBytes ));\r | |
2249 | }\r | |
2250 | else {\r | |
2251 | DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INFO,\r | |
2252 | "ERROR - Failed to free packet 0x%08x, Status: %r\r\n",\r | |
2253 | pPacket,\r | |
2254 | Status ));\r | |
2255 | }\r | |
2256 | \r | |
2257 | //\r | |
2258 | // Return the operation status\r | |
2259 | //\r | |
2260 | DBG_EXIT_STATUS ( Status );\r | |
2261 | return Status;\r | |
2262 | }\r | |
2263 | \r | |
2264 | \r | |
2265 | /**\r | |
2266 | Poll a socket for pending activity.\r | |
2267 | \r | |
2268 | The SocketPoll routine checks a socket for pending activity associated\r | |
2269 | with the event mask. Activity is returned in the detected event buffer.\r | |
2270 | \r | |
2271 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
2272 | \r | |
2273 | @param [in] Events Events of interest for this socket\r | |
2274 | \r | |
2275 | @param [in] pEvents Address to receive the detected events\r | |
2276 | \r | |
2277 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
2278 | \r | |
2279 | @retval EFI_SUCCESS - Socket successfully polled\r | |
2280 | @retval EFI_INVALID_PARAMETER - When pEvents is NULL\r | |
2281 | \r | |
2282 | **/\r | |
2283 | EFI_STATUS\r | |
2284 | EslSocketPoll (\r | |
2285 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
2286 | IN short Events,\r | |
2287 | IN short * pEvents,\r | |
2288 | IN int * pErrno\r | |
2289 | )\r | |
2290 | {\r | |
2291 | short DetectedEvents;\r | |
2292 | DT_SOCKET * pSocket;\r | |
2293 | EFI_STATUS Status;\r | |
2294 | EFI_TPL TplPrevious;\r | |
2295 | short ValidEvents;\r | |
2296 | \r | |
2297 | DEBUG (( DEBUG_POLL, "Entering SocketPoll\r\n" ));\r | |
2298 | \r | |
2299 | //\r | |
2300 | // Assume success\r | |
2301 | //\r | |
2302 | Status = EFI_SUCCESS;\r | |
2303 | DetectedEvents = 0;\r | |
2304 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
2305 | pSocket->errno = 0;\r | |
2306 | \r | |
2307 | //\r | |
2308 | // Verify the socket state\r | |
2309 | //\r | |
2310 | if ( !pSocket->bConfigured ) {\r | |
2311 | //\r | |
2312 | // Synchronize with the socket layer\r | |
2313 | //\r | |
2314 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
2315 | \r | |
2316 | //\r | |
2317 | // Validate the local address\r | |
2318 | //\r | |
2319 | switch ( pSocket->Domain ) {\r | |
2320 | default:\r | |
2321 | DEBUG (( DEBUG_RX,\r | |
2322 | "ERROR - Invalid socket address family: %d\r\n",\r | |
2323 | pSocket->Domain ));\r | |
2324 | Status = EFI_INVALID_PARAMETER;\r | |
2325 | pSocket->errno = EADDRNOTAVAIL;\r | |
2326 | break;\r | |
2327 | \r | |
2328 | case AF_INET:\r | |
2329 | //\r | |
2330 | // Determine the connection point within the network stack\r | |
2331 | //\r | |
2332 | switch ( pSocket->Type ) {\r | |
2333 | default:\r | |
2334 | DEBUG (( DEBUG_RX,\r | |
2335 | "ERROR - Invalid socket type: %d\r\n",\r | |
2336 | pSocket->Type));\r | |
2337 | Status = EFI_INVALID_PARAMETER;\r | |
2338 | pSocket->errno = EADDRNOTAVAIL;\r | |
2339 | break;\r | |
2340 | \r | |
2341 | case SOCK_STREAM:\r | |
2342 | case SOCK_SEQPACKET:\r | |
2343 | //\r | |
2344 | // Verify the port state\r | |
2345 | //\r | |
2346 | Status = EslTcpSocketIsConfigured4 ( pSocket );\r | |
2347 | break;\r | |
2348 | \r | |
2349 | case SOCK_DGRAM:\r | |
2350 | //\r | |
2351 | // Verify the port state\r | |
2352 | //\r | |
2353 | Status = EslUdpSocketIsConfigured4 ( pSocket );\r | |
2354 | break;\r | |
2355 | }\r | |
2356 | break;\r | |
2357 | }\r | |
2358 | \r | |
2359 | //\r | |
2360 | // Release the socket layer synchronization\r | |
2361 | //\r | |
2362 | RESTORE_TPL ( TplPrevious );\r | |
2363 | }\r | |
2364 | if ( !EFI_ERROR ( Status )) {\r | |
2365 | //\r | |
2366 | // Check for invalid events\r | |
2367 | //\r | |
2368 | ValidEvents = POLLIN\r | |
2369 | | POLLPRI\r | |
2370 | | POLLOUT | POLLWRNORM\r | |
2371 | | POLLERR\r | |
2372 | | POLLHUP\r | |
2373 | | POLLNVAL\r | |
2374 | | POLLRDNORM\r | |
2375 | | POLLRDBAND\r | |
2376 | | POLLWRBAND ;\r | |
2377 | if ( 0 != ( Events & ( ~ValidEvents ))) {\r | |
2378 | DetectedEvents |= POLLNVAL;\r | |
2379 | DEBUG (( DEBUG_INFO | DEBUG_POLL,\r | |
2380 | "ERROR - Invalid event mask, Valid Events: 0x%04x, Invalid Events: 0x%04x\r\n",\r | |
2381 | Events & ValidEvents,\r | |
2382 | Events & ( ~ValidEvents )));\r | |
2383 | }\r | |
2384 | else {\r | |
2385 | //\r | |
2386 | // Check for pending connections\r | |
2387 | //\r | |
2388 | if ( 0 != pSocket->FifoDepth ) {\r | |
2389 | //\r | |
2390 | // A connection is waiting for an accept call\r | |
2391 | // See posix connect documentation at\r | |
2392 | // http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.htm\r | |
2393 | //\r | |
2394 | DetectedEvents |= POLLIN | POLLRDNORM;\r | |
2395 | }\r | |
2396 | if ( pSocket->bConnected ) {\r | |
2397 | //\r | |
2398 | // A connection is present\r | |
2399 | // See posix connect documentation at\r | |
2400 | // http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.htm\r | |
2401 | //\r | |
2402 | DetectedEvents |= POLLOUT | POLLWRNORM;\r | |
2403 | }\r | |
2404 | \r | |
2405 | //\r | |
2406 | // The following bits are set based upon the POSIX poll documentation at\r | |
2407 | // http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html\r | |
2408 | //\r | |
2409 | \r | |
2410 | //\r | |
2411 | // Check for urgent receive data\r | |
2412 | //\r | |
2413 | if ( 0 < pSocket->RxOobBytes ) {\r | |
2414 | DetectedEvents |= POLLRDBAND | POLLPRI | POLLIN;\r | |
2415 | }\r | |
2416 | \r | |
2417 | //\r | |
2418 | // Check for normal receive data\r | |
2419 | //\r | |
2420 | if (( 0 < pSocket->RxBytes )\r | |
2421 | || ( EFI_SUCCESS != pSocket->RxError )) {\r | |
2422 | DetectedEvents |= POLLRDNORM | POLLIN;\r | |
2423 | }\r | |
2424 | \r | |
2425 | //\r | |
2426 | // Handle the receive errors\r | |
2427 | //\r | |
2428 | if (( EFI_SUCCESS != pSocket->RxError )\r | |
2429 | && ( 0 == ( DetectedEvents & POLLIN ))) {\r | |
2430 | DetectedEvents |= POLLERR | POLLIN | POLLRDNORM | POLLRDBAND;\r | |
2431 | }\r | |
2432 | \r | |
2433 | //\r | |
2434 | // Check for urgent transmit data buffer space\r | |
2435 | //\r | |
2436 | if (( MAX_TX_DATA > pSocket->TxOobBytes )\r | |
2437 | || ( EFI_SUCCESS != pSocket->TxError )) {\r | |
2438 | DetectedEvents |= POLLWRBAND;\r | |
2439 | }\r | |
2440 | \r | |
2441 | //\r | |
2442 | // Check for normal transmit data buffer space\r | |
2443 | //\r | |
2444 | if (( MAX_TX_DATA > pSocket->TxBytes )\r | |
2445 | || ( EFI_SUCCESS != pSocket->TxError )) {\r | |
2446 | DetectedEvents |= POLLWRNORM;\r | |
2447 | }\r | |
2448 | \r | |
2449 | //\r | |
2450 | // Handle the transmit error\r | |
2451 | //\r | |
2452 | if ( EFI_ERROR ( pSocket->TxError )) {\r | |
2453 | DetectedEvents |= POLLERR;\r | |
2454 | }\r | |
2455 | }\r | |
2456 | }\r | |
2457 | \r | |
2458 | //\r | |
2459 | // Return the detected events\r | |
2460 | //\r | |
2461 | *pEvents = DetectedEvents & ( Events\r | |
2462 | | POLLERR\r | |
2463 | | POLLHUP\r | |
2464 | | POLLNVAL );\r | |
2465 | \r | |
2466 | //\r | |
2467 | // Return the operation status\r | |
2468 | //\r | |
2469 | DEBUG (( DEBUG_POLL, "Exiting SocketPoll, Status: %r\r\n", Status ));\r | |
2470 | return Status;\r | |
2471 | }\r | |
2472 | \r | |
2473 | \r | |
2474 | /**\r | |
2475 | Receive data from a network connection.\r | |
2476 | \r | |
2477 | \r | |
2478 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
2479 | \r | |
2480 | @param [in] Flags Message control flags\r | |
2481 | \r | |
2482 | @param [in] BufferLength Length of the the buffer\r | |
2483 | \r | |
2484 | @param [in] pBuffer Address of a buffer to receive the data.\r | |
2485 | \r | |
2486 | @param [in] pDataLength Number of received data bytes in the buffer.\r | |
2487 | \r | |
2488 | @param [out] pAddress Network address to receive the remote system address\r | |
2489 | \r | |
2490 | @param [in,out] pAddressLength Length of the remote network address structure\r | |
2491 | \r | |
2492 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
2493 | \r | |
2494 | @retval EFI_SUCCESS - Socket data successfully received\r | |
2495 | \r | |
2496 | **/\r | |
2497 | EFI_STATUS\r | |
2498 | EslSocketReceive (\r | |
2499 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
2500 | IN INT32 Flags,\r | |
2501 | IN size_t BufferLength,\r | |
2502 | IN UINT8 * pBuffer,\r | |
2503 | OUT size_t * pDataLength,\r | |
2504 | OUT struct sockaddr * pAddress,\r | |
2505 | IN OUT socklen_t * pAddressLength,\r | |
2506 | IN int * pErrno\r | |
2507 | )\r | |
2508 | {\r | |
2509 | DT_SOCKET * pSocket;\r | |
2510 | EFI_STATUS Status;\r | |
2511 | EFI_TPL TplPrevious;\r | |
2512 | \r | |
2513 | DBG_ENTER ( );\r | |
2514 | \r | |
2515 | //\r | |
2516 | // Assume success\r | |
2517 | //\r | |
2518 | Status = EFI_SUCCESS;\r | |
2519 | \r | |
2520 | //\r | |
2521 | // Validate the socket\r | |
2522 | //\r | |
2523 | pSocket = NULL;\r | |
2524 | if ( NULL != pSocketProtocol ) {\r | |
2525 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
2526 | \r | |
2527 | //\r | |
1c34b250 | 2528 | // Return the transmit error if necessary\r |
d7ce7006 | 2529 | //\r |
1c34b250 | 2530 | if ( EFI_SUCCESS != pSocket->TxError ) {\r |
2531 | pSocket->errno = EIO;\r | |
2532 | Status = pSocket->TxError;\r | |
2533 | pSocket->TxError = EFI_SUCCESS;\r | |
d7ce7006 | 2534 | }\r |
1c34b250 | 2535 | else {\r |
d7ce7006 | 2536 | //\r |
1c34b250 | 2537 | // Verify the socket state\r |
d7ce7006 | 2538 | //\r |
1c34b250 | 2539 | if ( !pSocket->bConfigured ) {\r |
d7ce7006 | 2540 | //\r |
2541 | // Synchronize with the socket layer\r | |
2542 | //\r | |
2543 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
2544 | \r | |
2545 | //\r | |
2546 | // Validate the local address\r | |
2547 | //\r | |
2548 | switch ( pSocket->Domain ) {\r | |
2549 | default:\r | |
2550 | DEBUG (( DEBUG_RX,\r | |
2551 | "ERROR - Invalid socket address family: %d\r\n",\r | |
2552 | pSocket->Domain ));\r | |
2553 | Status = EFI_INVALID_PARAMETER;\r | |
2554 | pSocket->errno = EADDRNOTAVAIL;\r | |
2555 | break;\r | |
2556 | \r | |
2557 | case AF_INET:\r | |
2558 | //\r | |
2559 | // Determine the connection point within the network stack\r | |
2560 | //\r | |
2561 | switch ( pSocket->Type ) {\r | |
2562 | default:\r | |
2563 | DEBUG (( DEBUG_RX,\r | |
2564 | "ERROR - Invalid socket type: %d\r\n",\r | |
2565 | pSocket->Type));\r | |
2566 | Status = EFI_INVALID_PARAMETER;\r | |
d7ce7006 | 2567 | break;\r |
2568 | \r | |
2569 | case SOCK_STREAM:\r | |
2570 | case SOCK_SEQPACKET:\r | |
1c34b250 | 2571 | //\r |
2572 | // Verify the port state\r | |
2573 | //\r | |
2574 | Status = EslTcpSocketIsConfigured4 ( pSocket );\r | |
d7ce7006 | 2575 | break;\r |
2576 | \r | |
2577 | case SOCK_DGRAM:\r | |
1c34b250 | 2578 | //\r |
2579 | // Verify the port state\r | |
2580 | //\r | |
2581 | Status = EslUdpSocketIsConfigured4 ( pSocket );\r | |
d7ce7006 | 2582 | break;\r |
2583 | }\r | |
2584 | break;\r | |
2585 | }\r | |
2586 | \r | |
2587 | //\r | |
2588 | // Release the socket layer synchronization\r | |
2589 | //\r | |
2590 | RESTORE_TPL ( TplPrevious );\r | |
1c34b250 | 2591 | \r |
2592 | //\r | |
2593 | // Set errno if a failure occurs\r | |
2594 | //\r | |
2595 | if ( EFI_ERROR ( Status )) {\r | |
2596 | pSocket->errno = EADDRNOTAVAIL;\r | |
2597 | }\r | |
2598 | }\r | |
2599 | if ( !EFI_ERROR ( Status )) {\r | |
2600 | //\r | |
2601 | // Validate the buffer length\r | |
2602 | //\r | |
2603 | if (( NULL == pDataLength )\r | |
2604 | && ( 0 > pDataLength )\r | |
2605 | && ( NULL == pBuffer )) {\r | |
2606 | if ( NULL == pDataLength ) {\r | |
2607 | DEBUG (( DEBUG_RX,\r | |
2608 | "ERROR - pDataLength is NULL!\r\n" ));\r | |
2609 | }\r | |
2610 | else if ( NULL == pBuffer ) {\r | |
2611 | DEBUG (( DEBUG_RX,\r | |
2612 | "ERROR - pBuffer is NULL!\r\n" ));\r | |
2613 | }\r | |
2614 | else {\r | |
2615 | DEBUG (( DEBUG_RX,\r | |
2616 | "ERROR - Data length < 0!\r\n" ));\r | |
2617 | }\r | |
2618 | Status = EFI_INVALID_PARAMETER;\r | |
2619 | pSocket->errno = EFAULT;\r | |
2620 | }\r | |
2621 | else{\r | |
2622 | //\r | |
2623 | // Synchronize with the socket layer\r | |
2624 | //\r | |
2625 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
2626 | \r | |
2627 | //\r | |
2628 | // Validate the local address\r | |
2629 | //\r | |
2630 | switch ( pSocket->Domain ) {\r | |
2631 | default:\r | |
2632 | DEBUG (( DEBUG_RX,\r | |
2633 | "ERROR - Invalid socket address family: %d\r\n",\r | |
2634 | pSocket->Domain ));\r | |
2635 | Status = EFI_INVALID_PARAMETER;\r | |
2636 | pSocket->errno = EADDRNOTAVAIL;\r | |
2637 | break;\r | |
2638 | \r | |
2639 | case AF_INET:\r | |
2640 | //\r | |
2641 | // Determine the connection point within the network stack\r | |
2642 | //\r | |
2643 | switch ( pSocket->Type ) {\r | |
2644 | default:\r | |
2645 | DEBUG (( DEBUG_RX,\r | |
2646 | "ERROR - Invalid socket type: %d\r\n",\r | |
2647 | pSocket->Type));\r | |
2648 | Status = EFI_INVALID_PARAMETER;\r | |
2649 | pSocket->errno = EADDRNOTAVAIL;\r | |
2650 | break;\r | |
2651 | \r | |
2652 | case SOCK_STREAM:\r | |
2653 | case SOCK_SEQPACKET:\r | |
2654 | Status = EslTcpReceive4 ( pSocket,\r | |
2655 | Flags,\r | |
2656 | BufferLength,\r | |
2657 | pBuffer,\r | |
2658 | pDataLength,\r | |
2659 | pAddress,\r | |
2660 | pAddressLength );\r | |
2661 | break;\r | |
2662 | \r | |
2663 | case SOCK_DGRAM:\r | |
2664 | Status = EslUdpReceive4 ( pSocket,\r | |
2665 | Flags,\r | |
2666 | BufferLength,\r | |
2667 | pBuffer,\r | |
2668 | pDataLength,\r | |
2669 | pAddress,\r | |
2670 | pAddressLength);\r | |
2671 | break;\r | |
2672 | }\r | |
2673 | break;\r | |
2674 | }\r | |
2675 | \r | |
2676 | //\r | |
2677 | // Release the socket layer synchronization\r | |
2678 | //\r | |
2679 | RESTORE_TPL ( TplPrevious );\r | |
2680 | }\r | |
d7ce7006 | 2681 | }\r |
2682 | }\r | |
2683 | }\r | |
2684 | \r | |
2685 | //\r | |
2686 | // Return the operation status\r | |
2687 | //\r | |
2688 | if ( NULL != pErrno ) {\r | |
2689 | if ( NULL != pSocket ) {\r | |
2690 | *pErrno = pSocket->errno;\r | |
2691 | }\r | |
2692 | else\r | |
2693 | {\r | |
2694 | Status = EFI_INVALID_PARAMETER;\r | |
2695 | *pErrno = EBADF;\r | |
2696 | }\r | |
2697 | }\r | |
2698 | DBG_EXIT_STATUS ( Status );\r | |
2699 | return Status;\r | |
2700 | }\r | |
2701 | \r | |
2702 | \r | |
2703 | /**\r | |
2704 | Shutdown the socket receive and transmit operations\r | |
2705 | \r | |
2706 | The SocketShutdown routine stops the socket receive and transmit\r | |
2707 | operations.\r | |
2708 | \r | |
2709 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
2710 | \r | |
2711 | @param [in] How Which operations to stop\r | |
2712 | \r | |
2713 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
2714 | \r | |
2715 | @retval EFI_SUCCESS - Socket operations successfully shutdown\r | |
2716 | \r | |
2717 | **/\r | |
2718 | EFI_STATUS\r | |
2719 | EslSocketShutdown (\r | |
2720 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
2721 | IN int How,\r | |
2722 | IN int * pErrno\r | |
2723 | )\r | |
2724 | {\r | |
2725 | DT_SOCKET * pSocket;\r | |
2726 | EFI_STATUS Status;\r | |
2727 | EFI_TPL TplPrevious;\r | |
2728 | \r | |
2729 | DBG_ENTER ( );\r | |
2730 | \r | |
2731 | //\r | |
2732 | // Assume success\r | |
2733 | //\r | |
2734 | Status = EFI_SUCCESS;\r | |
2735 | \r | |
2736 | //\r | |
2737 | // Validate the socket\r | |
2738 | //\r | |
2739 | pSocket = NULL;\r | |
2740 | if ( NULL != pSocketProtocol ) {\r | |
2741 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
2742 | \r | |
2743 | //\r | |
2744 | // Verify that the socket is connected\r | |
2745 | //\r | |
2746 | if ( pSocket->bConnected ) {\r | |
2747 | //\r | |
2748 | // Validate the How value\r | |
2749 | //\r | |
2750 | if (( SHUT_RD <= How ) && ( SHUT_RDWR >= How )) {\r | |
2751 | //\r | |
2752 | // Synchronize with the socket layer\r | |
2753 | //\r | |
2754 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
2755 | \r | |
2756 | //\r | |
2757 | // Disable the receiver if requested\r | |
2758 | //\r | |
2759 | if (( SHUT_RD == How ) || ( SHUT_RDWR == How )) {\r | |
2760 | pSocket->bRxDisable = TRUE;\r | |
2761 | }\r | |
2762 | \r | |
2763 | //\r | |
2764 | // Disable the transmitter if requested\r | |
2765 | //\r | |
2766 | if (( SHUT_WR == How ) || ( SHUT_RDWR == How )) {\r | |
2767 | pSocket->bTxDisable = TRUE;\r | |
2768 | }\r | |
2769 | \r | |
2770 | //\r | |
2771 | // Validate the local address\r | |
2772 | //\r | |
2773 | switch ( pSocket->Domain ) {\r | |
2774 | default:\r | |
2775 | DEBUG (( DEBUG_RX,\r | |
2776 | "ERROR - Invalid socket address family: %d\r\n",\r | |
2777 | pSocket->Domain ));\r | |
2778 | Status = EFI_INVALID_PARAMETER;\r | |
2779 | pSocket->errno = EADDRNOTAVAIL;\r | |
2780 | break;\r | |
2781 | \r | |
2782 | case AF_INET:\r | |
2783 | //\r | |
2784 | // Determine the connection point within the network stack\r | |
2785 | //\r | |
2786 | switch ( pSocket->Type ) {\r | |
2787 | default:\r | |
2788 | DEBUG (( DEBUG_RX,\r | |
2789 | "ERROR - Invalid socket type: %d\r\n",\r | |
2790 | pSocket->Type));\r | |
2791 | Status = EFI_INVALID_PARAMETER;\r | |
2792 | break;\r | |
2793 | \r | |
2794 | case SOCK_STREAM:\r | |
2795 | case SOCK_SEQPACKET:\r | |
2796 | //\r | |
2797 | // Cancel the pending receive operation\r | |
2798 | //\r | |
2799 | Status = EslTcpRxCancel4 ( pSocket );\r | |
2800 | break;\r | |
2801 | \r | |
2802 | case SOCK_DGRAM:\r | |
2803 | //\r | |
2804 | // Cancel the pending receive operation\r | |
2805 | //\r | |
2806 | Status = EslUdpRxCancel4 ( pSocket );\r | |
2807 | break;\r | |
2808 | }\r | |
2809 | break;\r | |
2810 | }\r | |
2811 | \r | |
2812 | //\r | |
2813 | // Release the socket layer synchronization\r | |
2814 | //\r | |
2815 | RESTORE_TPL ( TplPrevious );\r | |
2816 | }\r | |
2817 | else {\r | |
2818 | //\r | |
2819 | // The socket is not connected\r | |
2820 | //\r | |
2821 | pSocket->errno = ENOTCONN;\r | |
2822 | Status = EFI_NOT_STARTED;\r | |
2823 | }\r | |
2824 | }\r | |
2825 | else {\r | |
2826 | //\r | |
2827 | // Invalid How value\r | |
2828 | //\r | |
2829 | pSocket->errno = EINVAL;\r | |
2830 | Status = EFI_INVALID_PARAMETER;\r | |
2831 | }\r | |
2832 | }\r | |
2833 | \r | |
2834 | //\r | |
2835 | // Return the operation status\r | |
2836 | //\r | |
2837 | if ( NULL != pErrno ) {\r | |
2838 | if ( NULL != pSocket ) {\r | |
2839 | *pErrno = pSocket->errno;\r | |
2840 | }\r | |
2841 | else\r | |
2842 | {\r | |
2843 | Status = EFI_INVALID_PARAMETER;\r | |
2844 | *pErrno = EBADF;\r | |
2845 | }\r | |
2846 | }\r | |
2847 | DBG_EXIT_STATUS ( Status );\r | |
2848 | return Status;\r | |
2849 | }\r | |
2850 | \r | |
2851 | \r | |
2852 | /**\r | |
2853 | Send data using a network connection.\r | |
2854 | \r | |
2855 | The SocketTransmit routine queues the data for transmission to the\r | |
2856 | remote network connection.\r | |
2857 | \r | |
2858 | @param [in] pSocketProtocol Address of the socket protocol structure.\r | |
2859 | \r | |
2860 | @param [in] Flags Message control flags\r | |
2861 | \r | |
2862 | @param [in] BufferLength Length of the the buffer\r | |
2863 | \r | |
2864 | @param [in] pBuffer Address of a buffer containing the data to send\r | |
2865 | \r | |
2866 | @param [in] pDataLength Address to receive the number of data bytes sent\r | |
2867 | \r | |
2868 | @param [in] pAddress Network address of the remote system address\r | |
2869 | \r | |
2870 | @param [in] AddressLength Length of the remote network address structure\r | |
2871 | \r | |
2872 | @param [out] pErrno Address to receive the errno value upon completion.\r | |
2873 | \r | |
2874 | @retval EFI_SUCCESS - Socket data successfully queued for transmit\r | |
2875 | \r | |
2876 | **/\r | |
2877 | EFI_STATUS\r | |
2878 | EslSocketTransmit (\r | |
2879 | IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r | |
2880 | IN int Flags,\r | |
2881 | IN size_t BufferLength,\r | |
2882 | IN CONST UINT8 * pBuffer,\r | |
2883 | OUT size_t * pDataLength,\r | |
2884 | IN const struct sockaddr * pAddress,\r | |
2885 | IN socklen_t AddressLength,\r | |
2886 | IN int * pErrno\r | |
2887 | )\r | |
2888 | {\r | |
2889 | DT_SOCKET * pSocket;\r | |
2890 | EFI_STATUS Status;\r | |
2891 | EFI_TPL TplPrevious;\r | |
2892 | \r | |
2893 | DBG_ENTER ( );\r | |
2894 | \r | |
2895 | //\r | |
2896 | // Assume success\r | |
2897 | //\r | |
2898 | Status = EFI_SUCCESS;\r | |
2899 | \r | |
2900 | //\r | |
2901 | // Validate the socket\r | |
2902 | //\r | |
2903 | pSocket = NULL;\r | |
2904 | if ( NULL != pSocketProtocol ) {\r | |
2905 | pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r | |
2906 | \r | |
2907 | //\r | |
1c34b250 | 2908 | // Return the transmit error if necessary\r |
d7ce7006 | 2909 | //\r |
1c34b250 | 2910 | if ( EFI_SUCCESS != pSocket->TxError ) {\r |
2911 | pSocket->errno = EIO;\r | |
2912 | Status = pSocket->TxError;\r | |
2913 | pSocket->TxError = EFI_SUCCESS;\r | |
2914 | }\r | |
2915 | else {\r | |
d7ce7006 | 2916 | //\r |
1c34b250 | 2917 | // Verify the socket state\r |
d7ce7006 | 2918 | //\r |
1c34b250 | 2919 | if ( !pSocket->bConfigured ) {\r |
2920 | //\r | |
2921 | // Synchronize with the socket layer\r | |
2922 | //\r | |
2923 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
2924 | \r | |
d7ce7006 | 2925 | //\r |
1c34b250 | 2926 | // Validate the local address\r |
d7ce7006 | 2927 | //\r |
1c34b250 | 2928 | switch ( pSocket->Domain ) {\r |
d7ce7006 | 2929 | default:\r |
2930 | DEBUG (( DEBUG_RX,\r | |
1c34b250 | 2931 | "ERROR - Invalid socket address family: %d\r\n",\r |
2932 | pSocket->Domain ));\r | |
d7ce7006 | 2933 | Status = EFI_INVALID_PARAMETER;\r |
1c34b250 | 2934 | pSocket->errno = EADDRNOTAVAIL;\r |
d7ce7006 | 2935 | break;\r |
1c34b250 | 2936 | \r |
2937 | case AF_INET:\r | |
d7ce7006 | 2938 | //\r |
1c34b250 | 2939 | // Determine the connection point within the network stack\r |
d7ce7006 | 2940 | //\r |
1c34b250 | 2941 | switch ( pSocket->Type ) {\r |
2942 | default:\r | |
2943 | DEBUG (( DEBUG_RX,\r | |
2944 | "ERROR - Invalid socket type: %d\r\n",\r | |
2945 | pSocket->Type));\r | |
2946 | Status = EFI_INVALID_PARAMETER;\r | |
2947 | break;\r | |
2948 | \r | |
2949 | case SOCK_STREAM:\r | |
2950 | case SOCK_SEQPACKET:\r | |
2951 | //\r | |
2952 | // Verify the port state\r | |
2953 | //\r | |
2954 | Status = EslTcpSocketIsConfigured4 ( pSocket );\r | |
2955 | break;\r | |
2956 | \r | |
2957 | case SOCK_DGRAM:\r | |
2958 | //\r | |
2959 | // Verify the port state\r | |
2960 | //\r | |
2961 | Status = EslUdpSocketIsConfigured4 ( pSocket );\r | |
2962 | break;\r | |
2963 | }\r | |
d7ce7006 | 2964 | break;\r |
2965 | }\r | |
1c34b250 | 2966 | \r |
d7ce7006 | 2967 | //\r |
1c34b250 | 2968 | // Release the socket layer synchronization\r |
d7ce7006 | 2969 | //\r |
1c34b250 | 2970 | RESTORE_TPL ( TplPrevious );\r |
2971 | \r | |
2972 | //\r | |
2973 | // Set errno if a failure occurs\r | |
2974 | //\r | |
2975 | if ( EFI_ERROR ( Status )) {\r | |
2976 | pSocket->errno = EADDRNOTAVAIL;\r | |
d7ce7006 | 2977 | }\r |
1c34b250 | 2978 | }\r |
2979 | if ( !EFI_ERROR ( Status )) {\r | |
2980 | //\r | |
2981 | // Verify that transmit is still allowed\r | |
2982 | //\r | |
2983 | if ( !pSocket->bTxDisable ) {\r | |
d7ce7006 | 2984 | //\r |
1c34b250 | 2985 | // Validate the buffer length\r |
d7ce7006 | 2986 | //\r |
1c34b250 | 2987 | if (( NULL == pDataLength )\r |
2988 | && ( 0 > pDataLength )\r | |
2989 | && ( NULL == pBuffer )) {\r | |
2990 | if ( NULL == pDataLength ) {\r | |
2991 | DEBUG (( DEBUG_RX,\r | |
2992 | "ERROR - pDataLength is NULL!\r\n" ));\r | |
2993 | }\r | |
2994 | else if ( NULL == pBuffer ) {\r | |
2995 | DEBUG (( DEBUG_RX,\r | |
2996 | "ERROR - pBuffer is NULL!\r\n" ));\r | |
2997 | }\r | |
2998 | else {\r | |
2999 | DEBUG (( DEBUG_RX,\r | |
3000 | "ERROR - Data length < 0!\r\n" ));\r | |
3001 | }\r | |
d7ce7006 | 3002 | Status = EFI_INVALID_PARAMETER;\r |
3003 | pSocket->errno = EFAULT;\r | |
3004 | }\r | |
3005 | else {\r | |
3006 | //\r | |
1c34b250 | 3007 | // Validate the remote network address\r |
d7ce7006 | 3008 | //\r |
1c34b250 | 3009 | if (( NULL != pAddress )\r |
3010 | && ( AddressLength < pAddress->sa_len )) {\r | |
3011 | DEBUG (( DEBUG_TX,\r | |
3012 | "ERROR - Invalid sin_len field in address\r\n" ));\r | |
d7ce7006 | 3013 | Status = EFI_INVALID_PARAMETER;\r |
1c34b250 | 3014 | pSocket->errno = EFAULT;\r |
3015 | }\r | |
3016 | else {\r | |
3017 | //\r | |
3018 | // Synchronize with the socket layer\r | |
3019 | //\r | |
3020 | RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r | |
d7ce7006 | 3021 | \r |
d7ce7006 | 3022 | //\r |
1c34b250 | 3023 | // Validate the local address\r |
d7ce7006 | 3024 | //\r |
1c34b250 | 3025 | switch ( pSocket->Domain ) {\r |
d7ce7006 | 3026 | default:\r |
3027 | DEBUG (( DEBUG_RX,\r | |
1c34b250 | 3028 | "ERROR - Invalid socket address family: %d\r\n",\r |
3029 | pSocket->Domain ));\r | |
d7ce7006 | 3030 | Status = EFI_INVALID_PARAMETER;\r |
3031 | pSocket->errno = EADDRNOTAVAIL;\r | |
3032 | break;\r | |
3033 | \r | |
1c34b250 | 3034 | case AF_INET:\r |
3035 | //\r | |
3036 | // Determine the connection point within the network stack\r | |
3037 | //\r | |
3038 | switch ( pSocket->Type ) {\r | |
3039 | default:\r | |
3040 | DEBUG (( DEBUG_RX,\r | |
3041 | "ERROR - Invalid socket type: %d\r\n",\r | |
3042 | pSocket->Type));\r | |
3043 | Status = EFI_INVALID_PARAMETER;\r | |
3044 | pSocket->errno = EADDRNOTAVAIL;\r | |
3045 | break;\r | |
3046 | \r | |
3047 | case SOCK_STREAM:\r | |
3048 | case SOCK_SEQPACKET:\r | |
3049 | Status = EslTcpTxBuffer4 ( pSocket,\r | |
3050 | Flags,\r | |
3051 | BufferLength,\r | |
3052 | pBuffer,\r | |
3053 | pDataLength );\r | |
3054 | break;\r | |
3055 | \r | |
3056 | case SOCK_DGRAM:\r | |
3057 | Status = EslUdpTxBuffer4 ( pSocket,\r | |
3058 | Flags,\r | |
3059 | BufferLength,\r | |
3060 | pBuffer,\r | |
3061 | pDataLength,\r | |
3062 | pAddress,\r | |
3063 | AddressLength );\r | |
3064 | break;\r | |
3065 | }\r | |
d7ce7006 | 3066 | break;\r |
3067 | }\r | |
d7ce7006 | 3068 | \r |
1c34b250 | 3069 | //\r |
3070 | // Release the socket layer synchronization\r | |
3071 | //\r | |
3072 | RESTORE_TPL ( TplPrevious );\r | |
3073 | }\r | |
d7ce7006 | 3074 | }\r |
3075 | }\r | |
1c34b250 | 3076 | else {\r |
3077 | //\r | |
3078 | // The transmitter was shutdown\r | |
3079 | //\r | |
3080 | pSocket->errno = EPIPE;\r | |
3081 | Status = EFI_NOT_STARTED;\r | |
3082 | }\r | |
d7ce7006 | 3083 | }\r |
3084 | }\r | |
3085 | }\r | |
3086 | \r | |
3087 | //\r | |
3088 | // Return the operation status\r | |
3089 | //\r | |
3090 | if ( NULL != pErrno ) {\r | |
3091 | if ( NULL != pSocket ) {\r | |
3092 | *pErrno = pSocket->errno;\r | |
3093 | }\r | |
3094 | else\r | |
3095 | {\r | |
3096 | Status = EFI_INVALID_PARAMETER;\r | |
3097 | *pErrno = EBADF;\r | |
3098 | }\r | |
3099 | }\r | |
3100 | DBG_EXIT_STATUS ( Status );\r | |
3101 | return Status;\r | |
3102 | }\r | |
3103 | \r | |
3104 | \r | |
3105 | /**\r | |
3106 | Socket layer's service binding protocol delcaration.\r | |
3107 | **/\r | |
3108 | EFI_SERVICE_BINDING_PROTOCOL mEfiServiceBinding = {\r | |
3109 | EslSocketCreateChild,\r | |
3110 | EslSocketDestroyChild\r | |
3111 | };\r |