]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/EfiSocketLib/Socket.c
add IPv4 address copy macro.
[mirror_edk2.git] / StdLib / EfiSocketLib / Socket.c
CommitLineData
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
27CONST 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
40CONST UINTN cEslSocketBindingEntries = DIM ( cEslSocketBinding );\r
41\r
42DT_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
91EFI_STATUS\r
92EslSocket (\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
237EFI_STATUS\r
238EslSocketAccept (\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
448EFI_STATUS\r
449EFIAPI\r
450EslSocketAllocate (\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
600EFI_STATUS\r
601EslSocketBind (\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
749EFI_STATUS\r
750EslSocketClosePoll (\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
885EFI_STATUS\r
886EslSocketCloseStart (\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
1011EFI_STATUS\r
1012EslSocketConnect (\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
1253EFI_STATUS\r
1254EFIAPI\r
1255EslSocketCreateChild (\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
1298EFI_STATUS\r
1299EFIAPI\r
1300EslSocketDestroyChild (\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
1452EFI_STATUS\r
1453EslSocketGetLocalAddress (\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
1585EFI_STATUS\r
1586EslSocketGetPeerAddress (\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
1727EFI_STATUS\r
1728EslSocketListen (\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
1914EFI_STATUS\r
1915EslSocketOptionGet (\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
2053EFI_STATUS\r
2054EslSocketOptionSet (\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
2171EFI_STATUS\r
2172EslSocketPacketAllocate (\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
2228EFI_STATUS\r
2229EslSocketPacketFree (\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
2283EFI_STATUS\r
2284EslSocketPoll (\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
2497EFI_STATUS\r
2498EslSocketReceive (\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
2528 // Verify the socket state\r
2529 //\r
2530 if ( !pSocket->bConfigured ) {\r
2531 //\r
2532 // Synchronize with the socket layer\r
2533 //\r
2534 RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
2535\r
2536 //\r
2537 // Validate the local address\r
2538 //\r
2539 switch ( pSocket->Domain ) {\r
2540 default:\r
2541 DEBUG (( DEBUG_RX,\r
2542 "ERROR - Invalid socket address family: %d\r\n",\r
2543 pSocket->Domain ));\r
2544 Status = EFI_INVALID_PARAMETER;\r
2545 pSocket->errno = EADDRNOTAVAIL;\r
2546 break;\r
2547\r
2548 case AF_INET:\r
2549 //\r
2550 // Determine the connection point within the network stack\r
2551 //\r
2552 switch ( pSocket->Type ) {\r
2553 default:\r
2554 DEBUG (( DEBUG_RX,\r
2555 "ERROR - Invalid socket type: %d\r\n",\r
2556 pSocket->Type));\r
2557 Status = EFI_INVALID_PARAMETER;\r
2558 break;\r
2559\r
2560 case SOCK_STREAM:\r
2561 case SOCK_SEQPACKET:\r
2562 //\r
2563 // Verify the port state\r
2564 //\r
2565 Status = EslTcpSocketIsConfigured4 ( pSocket );\r
2566 break;\r
2567\r
2568 case SOCK_DGRAM:\r
2569 //\r
2570 // Verify the port state\r
2571 //\r
2572 Status = EslUdpSocketIsConfigured4 ( pSocket );\r
2573 break;\r
2574 }\r
2575 break;\r
2576 }\r
2577\r
2578 //\r
2579 // Release the socket layer synchronization\r
2580 //\r
2581 RESTORE_TPL ( TplPrevious );\r
2582\r
2583 //\r
2584 // Set errno if a failure occurs\r
2585 //\r
2586 if ( EFI_ERROR ( Status )) {\r
2587 pSocket->errno = EADDRNOTAVAIL;\r
2588 }\r
2589 }\r
2590 if ( !EFI_ERROR ( Status )) {\r
2591 //\r
2592 // Validate the buffer length\r
2593 //\r
2594 if (( NULL == pDataLength )\r
2595 && ( 0 > pDataLength )\r
2596 && ( NULL == pBuffer )) {\r
2597 if ( NULL == pDataLength ) {\r
2598 DEBUG (( DEBUG_RX,\r
2599 "ERROR - pDataLength is NULL!\r\n" ));\r
2600 }\r
2601 else if ( NULL == pBuffer ) {\r
2602 DEBUG (( DEBUG_RX,\r
2603 "ERROR - pBuffer is NULL!\r\n" ));\r
2604 }\r
2605 else {\r
2606 DEBUG (( DEBUG_RX,\r
2607 "ERROR - Data length < 0!\r\n" ));\r
2608 }\r
2609 Status = EFI_INVALID_PARAMETER;\r
2610 pSocket->errno = EFAULT;\r
2611 }\r
2612 else{\r
2613 //\r
2614 // Synchronize with the socket layer\r
2615 //\r
2616 RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
2617\r
2618 //\r
2619 // Validate the local address\r
2620 //\r
2621 switch ( pSocket->Domain ) {\r
2622 default:\r
2623 DEBUG (( DEBUG_RX,\r
2624 "ERROR - Invalid socket address family: %d\r\n",\r
2625 pSocket->Domain ));\r
2626 Status = EFI_INVALID_PARAMETER;\r
2627 pSocket->errno = EADDRNOTAVAIL;\r
2628 break;\r
2629\r
2630 case AF_INET:\r
2631 //\r
2632 // Determine the connection point within the network stack\r
2633 //\r
2634 switch ( pSocket->Type ) {\r
2635 default:\r
2636 DEBUG (( DEBUG_RX,\r
2637 "ERROR - Invalid socket type: %d\r\n",\r
2638 pSocket->Type));\r
2639 Status = EFI_INVALID_PARAMETER;\r
2640 pSocket->errno = EADDRNOTAVAIL;\r
2641 break;\r
2642\r
2643 case SOCK_STREAM:\r
2644 case SOCK_SEQPACKET:\r
2645 Status = EslTcpReceive4 ( pSocket,\r
2646 Flags,\r
2647 BufferLength,\r
2648 pBuffer,\r
2649 pDataLength,\r
2650 pAddress,\r
2651 pAddressLength );\r
2652 break;\r
2653\r
2654 case SOCK_DGRAM:\r
2655 Status = EslUdpReceive4 ( pSocket,\r
2656 Flags,\r
2657 BufferLength,\r
2658 pBuffer,\r
2659 pDataLength,\r
2660 pAddress,\r
2661 pAddressLength);\r
2662 break;\r
2663 }\r
2664 break;\r
2665 }\r
2666\r
2667 //\r
2668 // Release the socket layer synchronization\r
2669 //\r
2670 RESTORE_TPL ( TplPrevious );\r
2671 }\r
2672 }\r
2673 }\r
2674\r
2675 //\r
2676 // Return the operation status\r
2677 //\r
2678 if ( NULL != pErrno ) {\r
2679 if ( NULL != pSocket ) {\r
2680 *pErrno = pSocket->errno;\r
2681 }\r
2682 else\r
2683 {\r
2684 Status = EFI_INVALID_PARAMETER;\r
2685 *pErrno = EBADF;\r
2686 }\r
2687 }\r
2688 DBG_EXIT_STATUS ( Status );\r
2689 return Status;\r
2690}\r
2691\r
2692\r
2693/**\r
2694 Shutdown the socket receive and transmit operations\r
2695\r
2696 The SocketShutdown routine stops the socket receive and transmit\r
2697 operations.\r
2698\r
2699 @param [in] pSocketProtocol Address of the socket protocol structure.\r
2700 \r
2701 @param [in] How Which operations to stop\r
2702 \r
2703 @param [out] pErrno Address to receive the errno value upon completion.\r
2704\r
2705 @retval EFI_SUCCESS - Socket operations successfully shutdown\r
2706\r
2707 **/\r
2708EFI_STATUS\r
2709EslSocketShutdown (\r
2710 IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
2711 IN int How,\r
2712 IN int * pErrno\r
2713 )\r
2714{\r
2715 DT_SOCKET * pSocket;\r
2716 EFI_STATUS Status;\r
2717 EFI_TPL TplPrevious;\r
2718 \r
2719 DBG_ENTER ( );\r
2720 \r
2721 //\r
2722 // Assume success\r
2723 //\r
2724 Status = EFI_SUCCESS;\r
2725\r
2726 //\r
2727 // Validate the socket\r
2728 //\r
2729 pSocket = NULL;\r
2730 if ( NULL != pSocketProtocol ) {\r
2731 pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
2732\r
2733 //\r
2734 // Verify that the socket is connected\r
2735 //\r
2736 if ( pSocket->bConnected ) {\r
2737 //\r
2738 // Validate the How value\r
2739 //\r
2740 if (( SHUT_RD <= How ) && ( SHUT_RDWR >= How )) {\r
2741 //\r
2742 // Synchronize with the socket layer\r
2743 //\r
2744 RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
2745\r
2746 //\r
2747 // Disable the receiver if requested\r
2748 //\r
2749 if (( SHUT_RD == How ) || ( SHUT_RDWR == How )) {\r
2750 pSocket->bRxDisable = TRUE;\r
2751 }\r
2752\r
2753 //\r
2754 // Disable the transmitter if requested\r
2755 //\r
2756 if (( SHUT_WR == How ) || ( SHUT_RDWR == How )) {\r
2757 pSocket->bTxDisable = TRUE;\r
2758 }\r
2759\r
2760 //\r
2761 // Validate the local address\r
2762 //\r
2763 switch ( pSocket->Domain ) {\r
2764 default:\r
2765 DEBUG (( DEBUG_RX,\r
2766 "ERROR - Invalid socket address family: %d\r\n",\r
2767 pSocket->Domain ));\r
2768 Status = EFI_INVALID_PARAMETER;\r
2769 pSocket->errno = EADDRNOTAVAIL;\r
2770 break;\r
2771 \r
2772 case AF_INET:\r
2773 //\r
2774 // Determine the connection point within the network stack\r
2775 //\r
2776 switch ( pSocket->Type ) {\r
2777 default:\r
2778 DEBUG (( DEBUG_RX,\r
2779 "ERROR - Invalid socket type: %d\r\n",\r
2780 pSocket->Type));\r
2781 Status = EFI_INVALID_PARAMETER;\r
2782 break;\r
2783 \r
2784 case SOCK_STREAM:\r
2785 case SOCK_SEQPACKET:\r
2786 //\r
2787 // Cancel the pending receive operation\r
2788 //\r
2789 Status = EslTcpRxCancel4 ( pSocket );\r
2790 break;\r
2791 \r
2792 case SOCK_DGRAM:\r
2793 //\r
2794 // Cancel the pending receive operation\r
2795 //\r
2796 Status = EslUdpRxCancel4 ( pSocket );\r
2797 break;\r
2798 }\r
2799 break;\r
2800 }\r
2801 \r
2802 //\r
2803 // Release the socket layer synchronization\r
2804 //\r
2805 RESTORE_TPL ( TplPrevious );\r
2806 }\r
2807 else {\r
2808 //\r
2809 // The socket is not connected\r
2810 //\r
2811 pSocket->errno = ENOTCONN;\r
2812 Status = EFI_NOT_STARTED;\r
2813 }\r
2814 }\r
2815 else {\r
2816 //\r
2817 // Invalid How value\r
2818 //\r
2819 pSocket->errno = EINVAL;\r
2820 Status = EFI_INVALID_PARAMETER;\r
2821 }\r
2822 }\r
2823\r
2824 //\r
2825 // Return the operation status\r
2826 //\r
2827 if ( NULL != pErrno ) {\r
2828 if ( NULL != pSocket ) {\r
2829 *pErrno = pSocket->errno;\r
2830 }\r
2831 else\r
2832 {\r
2833 Status = EFI_INVALID_PARAMETER;\r
2834 *pErrno = EBADF;\r
2835 }\r
2836 }\r
2837 DBG_EXIT_STATUS ( Status );\r
2838 return Status;\r
2839}\r
2840\r
2841\r
2842/**\r
2843 Send data using a network connection.\r
2844\r
2845 The SocketTransmit routine queues the data for transmission to the\r
2846 remote network connection.\r
2847\r
2848 @param [in] pSocketProtocol Address of the socket protocol structure.\r
2849 \r
2850 @param [in] Flags Message control flags\r
2851 \r
2852 @param [in] BufferLength Length of the the buffer\r
2853 \r
2854 @param [in] pBuffer Address of a buffer containing the data to send\r
2855 \r
2856 @param [in] pDataLength Address to receive the number of data bytes sent\r
2857\r
2858 @param [in] pAddress Network address of the remote system address\r
2859\r
2860 @param [in] AddressLength Length of the remote network address structure\r
2861\r
2862 @param [out] pErrno Address to receive the errno value upon completion.\r
2863\r
2864 @retval EFI_SUCCESS - Socket data successfully queued for transmit\r
2865\r
2866 **/\r
2867EFI_STATUS\r
2868EslSocketTransmit (\r
2869 IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
2870 IN int Flags,\r
2871 IN size_t BufferLength,\r
2872 IN CONST UINT8 * pBuffer,\r
2873 OUT size_t * pDataLength,\r
2874 IN const struct sockaddr * pAddress,\r
2875 IN socklen_t AddressLength,\r
2876 IN int * pErrno\r
2877 )\r
2878{\r
2879 DT_SOCKET * pSocket;\r
2880 EFI_STATUS Status;\r
2881 EFI_TPL TplPrevious;\r
2882\r
2883 DBG_ENTER ( );\r
2884\r
2885 //\r
2886 // Assume success\r
2887 //\r
2888 Status = EFI_SUCCESS;\r
2889\r
2890 //\r
2891 // Validate the socket\r
2892 //\r
2893 pSocket = NULL;\r
2894 if ( NULL != pSocketProtocol ) {\r
2895 pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
2896\r
2897 //\r
2898 // Verify the socket state\r
2899 //\r
2900 if ( !pSocket->bConfigured ) {\r
2901 //\r
2902 // Synchronize with the socket layer\r
2903 //\r
2904 RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
2905 \r
2906 //\r
2907 // Validate the local address\r
2908 //\r
2909 switch ( pSocket->Domain ) {\r
2910 default:\r
2911 DEBUG (( DEBUG_RX,\r
2912 "ERROR - Invalid socket address family: %d\r\n",\r
2913 pSocket->Domain ));\r
2914 Status = EFI_INVALID_PARAMETER;\r
2915 pSocket->errno = EADDRNOTAVAIL;\r
2916 break;\r
2917 \r
2918 case AF_INET:\r
2919 //\r
2920 // Determine the connection point within the network stack\r
2921 //\r
2922 switch ( pSocket->Type ) {\r
2923 default:\r
2924 DEBUG (( DEBUG_RX,\r
2925 "ERROR - Invalid socket type: %d\r\n",\r
2926 pSocket->Type));\r
2927 Status = EFI_INVALID_PARAMETER;\r
2928 break;\r
2929 \r
2930 case SOCK_STREAM:\r
2931 case SOCK_SEQPACKET:\r
2932 //\r
2933 // Verify the port state\r
2934 //\r
2935 Status = EslTcpSocketIsConfigured4 ( pSocket );\r
2936 break;\r
2937 \r
2938 case SOCK_DGRAM:\r
2939 //\r
2940 // Verify the port state\r
2941 //\r
2942 Status = EslUdpSocketIsConfigured4 ( pSocket );\r
2943 break;\r
2944 }\r
2945 break;\r
2946 }\r
2947 \r
2948 //\r
2949 // Release the socket layer synchronization\r
2950 //\r
2951 RESTORE_TPL ( TplPrevious );\r
2952 \r
2953 //\r
2954 // Set errno if a failure occurs\r
2955 //\r
2956 if ( EFI_ERROR ( Status )) {\r
2957 pSocket->errno = EADDRNOTAVAIL;\r
2958 }\r
2959 }\r
2960 if ( !EFI_ERROR ( Status )) {\r
2961 //\r
2962 // Verify that transmit is still allowed\r
2963 //\r
2964 if ( !pSocket->bTxDisable ) {\r
2965 //\r
2966 // Validate the buffer length\r
2967 //\r
2968 if (( NULL == pDataLength )\r
2969 && ( 0 > pDataLength )\r
2970 && ( NULL == pBuffer )) {\r
2971 if ( NULL == pDataLength ) {\r
2972 DEBUG (( DEBUG_RX,\r
2973 "ERROR - pDataLength is NULL!\r\n" ));\r
2974 }\r
2975 else if ( NULL == pBuffer ) {\r
2976 DEBUG (( DEBUG_RX,\r
2977 "ERROR - pBuffer is NULL!\r\n" ));\r
2978 }\r
2979 else {\r
2980 DEBUG (( DEBUG_RX,\r
2981 "ERROR - Data length < 0!\r\n" ));\r
2982 }\r
2983 Status = EFI_INVALID_PARAMETER;\r
2984 pSocket->errno = EFAULT;\r
2985 }\r
2986 else {\r
2987 //\r
2988 // Validate the remote network address\r
2989 //\r
2990 if (( NULL != pAddress )\r
2991 && ( AddressLength < pAddress->sa_len )) {\r
2992 DEBUG (( DEBUG_TX,\r
2993 "ERROR - Invalid sin_len field in address\r\n" ));\r
2994 Status = EFI_INVALID_PARAMETER;\r
2995 pSocket->errno = EFAULT;\r
2996 }\r
2997 else {\r
2998 //\r
2999 // Synchronize with the socket layer\r
3000 //\r
3001 RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
3002\r
3003 //\r
3004 // Validate the local address\r
3005 //\r
3006 switch ( pSocket->Domain ) {\r
3007 default:\r
3008 DEBUG (( DEBUG_RX,\r
3009 "ERROR - Invalid socket address family: %d\r\n",\r
3010 pSocket->Domain ));\r
3011 Status = EFI_INVALID_PARAMETER;\r
3012 pSocket->errno = EADDRNOTAVAIL;\r
3013 break;\r
3014\r
3015 case AF_INET:\r
3016 //\r
3017 // Determine the connection point within the network stack\r
3018 //\r
3019 switch ( pSocket->Type ) {\r
3020 default:\r
3021 DEBUG (( DEBUG_RX,\r
3022 "ERROR - Invalid socket type: %d\r\n",\r
3023 pSocket->Type));\r
3024 Status = EFI_INVALID_PARAMETER;\r
3025 pSocket->errno = EADDRNOTAVAIL;\r
3026 break;\r
3027\r
3028 case SOCK_STREAM:\r
3029 case SOCK_SEQPACKET:\r
3030 Status = EslTcpTxBuffer4 ( pSocket,\r
3031 Flags,\r
3032 BufferLength,\r
3033 pBuffer,\r
3034 pDataLength );\r
3035 break;\r
3036\r
3037 case SOCK_DGRAM:\r
3038 Status = EslUdpTxBuffer4 ( pSocket,\r
3039 Flags,\r
3040 BufferLength,\r
3041 pBuffer,\r
3042 pDataLength,\r
3043 pAddress,\r
3044 AddressLength );\r
3045 break;\r
3046 }\r
3047 break;\r
3048 }\r
3049\r
3050 //\r
3051 // Release the socket layer synchronization\r
3052 //\r
3053 RESTORE_TPL ( TplPrevious );\r
3054 }\r
3055 }\r
3056 }\r
3057 else {\r
3058 //\r
3059 // The transmitter was shutdown\r
3060 //\r
3061 pSocket->errno = EPIPE;\r
3062 Status = EFI_NOT_STARTED;\r
3063 }\r
3064 }\r
3065 }\r
3066\r
3067 //\r
3068 // Return the operation status\r
3069 //\r
3070 if ( NULL != pErrno ) {\r
3071 if ( NULL != pSocket ) {\r
3072 *pErrno = pSocket->errno;\r
3073 }\r
3074 else\r
3075 {\r
3076 Status = EFI_INVALID_PARAMETER;\r
3077 *pErrno = EBADF;\r
3078 }\r
3079 }\r
3080 DBG_EXIT_STATUS ( Status );\r
3081 return Status;\r
3082}\r
3083\r
3084\r
3085/**\r
3086 Socket layer's service binding protocol delcaration.\r
3087**/\r
3088EFI_SERVICE_BINDING_PROTOCOL mEfiServiceBinding = {\r
3089 EslSocketCreateChild,\r
3090 EslSocketDestroyChild\r
3091};\r