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