2 Implement the TCP6 driver support for the socket layer.
4 Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available
6 under the terms and conditions of the BSD License which accompanies this
7 distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 \section ConnectionManagement Connection Management
16 The ::EslTcp6Listen routine initially places the SOCK_STREAM or
17 SOCK_SEQPACKET socket into a listen state. When a remote machine
18 makes a connection to the socket, the TCPv6 network layer calls
19 ::EslTcp6ListenComplete to complete the connection processing.
20 EslTcp6ListenComplete manages the connections by placing them in
21 FIFO order in a queue to be serviced by the application. When the
22 number of connections exceeds the backlog (ESL_SOCKET::MaxFifoDepth),
23 the new connection is closed. Eventually, the application indirectly
24 calls ::EslTcp6Accept to remove the next connection from the queue
25 and get the associated socket.
33 Attempt to connect to a remote TCP port
35 This routine starts the connection processing for a SOCK_STREAM
36 or SOCK_SEQPAKCET socket using the TCPv6 network layer. It
37 configures the local TCPv6 connection point and then attempts to
38 connect to a remote system. Upon completion, the
39 ::EslTcp6ConnectComplete routine gets called with the connection
42 This routine is called by ::EslSocketConnect to initiate the TCPv6
43 network specific connect operations. The connection processing is
44 initiated by this routine and finished by ::EslTcp6ConnectComplete.
45 This pair of routines walks through the list of local TCPv6
46 connection points until a connection to the remote system is
49 @param [in] pSocket Address of an ::ESL_SOCKET structure.
51 @retval EFI_SUCCESS The connection was successfully established.
52 @retval EFI_NOT_READY The connection is in progress, call this routine again.
53 @retval Others The connection attempt failed.
58 IN ESL_SOCKET
* pSocket
63 Process the connection attempt
65 A system has initiated a connection attempt with a socket in the
66 listen state. Attempt to complete the connection.
68 The TCPv6 layer calls this routine when a connection is made to
69 the socket in the listen state. See the
70 \ref ConnectionManagement section.
72 @param [in] Event The listen completion event
74 @param [in] pPort Address of an ::ESL_PORT structure.
78 EslTcp6ListenComplete (
85 Accept a network connection.
87 This routine waits for a network connection to the socket and
88 returns the remote network address to the caller if requested.
90 This routine is called by ::EslSocketAccept to handle the TCPv6 protocol
91 specific accept operations for SOCK_STREAM and SOCK_SEQPACKET sockets.
92 See the \ref ConnectionManagement section.
94 @param [in] pSocket Address of an ::ESL_SOCKET structure.
96 @param [in] pSockAddr Address of a buffer to receive the remote
99 @param [in, out] pSockAddrLength Length in bytes of the address buffer.
100 On output specifies the length of the
101 remote network address.
103 @retval EFI_SUCCESS Remote address is available
104 @retval Others Remote address not available
109 IN ESL_SOCKET
* pSocket
,
110 IN
struct sockaddr
* pSockAddr
,
111 IN OUT socklen_t
* pSockAddrLength
115 struct sockaddr_in6
* pRemoteAddress
;
116 ESL_TCP6_CONTEXT
* pTcp6
;
122 // Validate the socket length
124 pRemoteAddress
= (struct sockaddr_in6
*) pSockAddr
;
125 if (( NULL
== pSockAddrLength
)
126 || ( sizeof ( *pRemoteAddress
) > *pSockAddrLength
)) {
128 // Invalid socket address
130 Status
= EFI_INVALID_PARAMETER
;
131 pSocket
->errno
= EINVAL
;
132 DEBUG (( DEBUG_ACCEPT
,
133 "ERROR - Invalid address length\r\n" ));
139 Status
= EFI_SUCCESS
;
142 // Locate the address context
144 pPort
= pSocket
->pPortList
;
145 pTcp6
= &pPort
->Context
.Tcp6
;
148 // Fill-in the remote address structure
150 ZeroMem ( pRemoteAddress
, sizeof ( *pRemoteAddress
));
151 pRemoteAddress
->sin6_len
= sizeof ( *pRemoteAddress
);
152 pRemoteAddress
->sin6_family
= AF_INET6
;
153 pRemoteAddress
->sin6_port
= SwapBytes16 ( pTcp6
->ConfigData
.AccessPoint
.RemotePort
);
154 CopyMem ( &pRemoteAddress
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
155 &pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[0],
156 sizeof ( pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
));
160 // Return the operation status
162 DBG_EXIT_STATUS ( Status
);
168 Process the remote connection completion event.
170 This routine handles the completion of a connection attempt. It
171 releases the port (TCPv6 adapter connection) in the case of an
172 error and start a connection attempt on the next port. If the
173 connection attempt was successful then this routine releases all
176 This routine is called by the TCPv6 layer when a connect request
177 completes. It sets the ESL_SOCKET::bConnected flag to notify the
178 ::EslTcp6ConnectComplete routine that the connection is available.
179 The flag is set when the connection is established or no more ports
180 exist in the list. The connection status is passed via
181 ESL_SOCKET::ConnectStatus.
183 @param [in] Event The connect completion event
185 @param [in] pPort Address of an ::ESL_PORT structure.
189 EslTcp6ConnectComplete (
194 BOOLEAN bRemoveFirstPort
;
195 BOOLEAN bRemovePorts
;
196 ESL_PORT
* pNextPort
;
197 ESL_SOCKET
* pSocket
;
198 ESL_TCP6_CONTEXT
* pTcp6
;
204 // Locate the TCP context
206 pSocket
= pPort
->pSocket
;
207 pTcp6
= &pPort
->Context
.Tcp6
;
210 // Get the connection status
212 bRemoveFirstPort
= FALSE
;
213 bRemovePorts
= FALSE
;
214 Status
= pTcp6
->ConnectToken
.CompletionToken
.Status
;
215 pSocket
->ConnectStatus
= Status
;
216 if ( !EFI_ERROR ( Status
)) {
218 // The connection was successful
220 DEBUG (( DEBUG_CONNECT
,
221 "0x%08x: Port connected to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
223 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[0],
224 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[1],
225 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[2],
226 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[3],
227 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[4],
228 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[5],
229 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[6],
230 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[7],
231 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[8],
232 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[9],
233 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[10],
234 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[11],
235 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[12],
236 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[13],
237 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[14],
238 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[15],
239 pTcp6
->ConfigData
.AccessPoint
.RemotePort
));
242 // Start the receive operations
244 pSocket
->bConfigured
= TRUE
;
245 pSocket
->State
= SOCKET_STATE_CONNECTED
;
246 EslSocketRxStart ( pPort
);
249 // Remove the rest of the ports
255 // The connection failed
257 if ( pPort
->bConfigured
) {
258 DEBUG (( DEBUG_CONNECT
,
259 "0x%08x: Port connection to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d failed, Status: %r\r\n",
261 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[0],
262 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[1],
263 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[2],
264 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[3],
265 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[4],
266 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[5],
267 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[6],
268 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[7],
269 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[8],
270 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[9],
271 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[10],
272 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[11],
273 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[12],
274 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[13],
275 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[14],
276 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[15],
277 pTcp6
->ConfigData
.AccessPoint
.RemotePort
,
282 // Close the current port
284 Status
= EslSocketPortClose ( pPort
);
285 if ( !EFI_ERROR ( Status
)) {
286 DEBUG (( DEBUG_CONNECT
,
287 "0x%08x: Port closed\r\n",
291 DEBUG (( DEBUG_CONNECT
,
292 "ERROR - Failed to close port 0x%08x, Status: %r\r\n",
298 // Try to connect using the next port
300 Status
= EslTcp6ConnectStart ( pSocket
);
301 if ( EFI_NOT_READY
!= Status
) {
302 bRemoveFirstPort
= TRUE
;
307 // Remove the ports if necessary
309 if ( bRemoveFirstPort
|| bRemovePorts
) {
311 // Remove the first port if necessary
313 pPort
= pSocket
->pPortList
;
314 if (( !bRemoveFirstPort
) && ( NULL
!= pPort
)) {
315 pPort
= pPort
->pLinkSocket
;
319 // Remove the rest of the list
321 while ( NULL
!= pPort
) {
322 pNextPort
= pPort
->pLinkSocket
;
323 EslSocketPortClose ( pPort
);
324 if ( !EFI_ERROR ( Status
)) {
325 DEBUG (( DEBUG_CONNECT
,
326 "0x%08x: Port closed\r\n",
330 DEBUG (( DEBUG_CONNECT
,
331 "ERROR - Failed to close port 0x%08x, Status: %r\r\n",
339 // Notify the poll routine
341 pSocket
->bConnected
= TRUE
;
349 Poll for completion of the connection attempt.
351 This routine polls the ESL_SOCKET::bConnected flag to determine
352 when the connection attempt is complete.
354 This routine is called from ::EslSocketConnect to determine when
355 the connection is complete. The ESL_SOCKET::bConnected flag is
356 set by ::EslTcp6ConnectComplete when the TCPv6 layer establishes
357 a connection or runs out of local network adapters. This routine
358 gets the connection status from ESL_SOCKET::ConnectStatus.
360 @param [in] pSocket Address of an ::ESL_SOCKET structure.
362 @retval EFI_SUCCESS The connection was successfully established.
363 @retval EFI_NOT_READY The connection is in progress, call this routine again.
364 @retval Others The connection attempt failed.
369 IN ESL_SOCKET
* pSocket
377 // Determine if the connection is complete
379 if ( !pSocket
->bConnected
) {
383 pSocket
->errno
= EAGAIN
;
384 Status
= EFI_NOT_READY
;
388 // The connection processing is complete
390 pSocket
->bConnected
= FALSE
;
393 // Translate the connection status
395 Status
= pSocket
->ConnectStatus
;
398 case EFI_DEVICE_ERROR
:
399 pSocket
->errno
= EIO
;
403 pSocket
->errno
= ECONNABORTED
;
406 case EFI_ACCESS_DENIED
:
407 pSocket
->errno
= EACCES
;
410 case EFI_CONNECTION_RESET
:
411 pSocket
->errno
= ECONNRESET
;
414 case EFI_INVALID_PARAMETER
:
415 pSocket
->errno
= EADDRNOTAVAIL
;
418 case EFI_HOST_UNREACHABLE
:
419 case EFI_NO_RESPONSE
:
420 pSocket
->errno
= EHOSTUNREACH
;
424 pSocket
->errno
= EAFNOSUPPORT
;
428 case EFI_NETWORK_UNREACHABLE
:
429 pSocket
->errno
= ENETDOWN
;
432 case EFI_OUT_OF_RESOURCES
:
433 pSocket
->errno
= ENOBUFS
;
436 case EFI_PORT_UNREACHABLE
:
437 case EFI_PROTOCOL_UNREACHABLE
:
438 case EFI_CONNECTION_REFUSED
:
439 pSocket
->errno
= ECONNREFUSED
;
447 pSocket
->errno
= ETIMEDOUT
;
450 case EFI_UNSUPPORTED
:
451 pSocket
->errno
= EOPNOTSUPP
;
456 // Display the translation
458 DEBUG (( DEBUG_CONNECT
,
459 "ERROR - errno: %d, Status: %r\r\n",
465 // Return the initialization status
467 DBG_EXIT_STATUS ( Status
);
473 Attempt to connect to a remote TCP port
475 This routine starts the connection processing for a SOCK_STREAM
476 or SOCK_SEQPAKCET socket using the TCPv6 network layer. It
477 configures the local TCPv6 connection point and then attempts to
478 connect to a remote system. Upon completion, the
479 ::EslTcp6ConnectComplete routine gets called with the connection
482 This routine is called by ::EslSocketConnect to initiate the TCPv6
483 network specific connect operations. The connection processing is
484 initiated by this routine and finished by ::EslTcp6ConnectComplete.
485 This pair of routines walks through the list of local TCPv6
486 connection points until a connection to the remote system is
489 @param [in] pSocket Address of an ::ESL_SOCKET structure.
491 @retval EFI_SUCCESS The connection was successfully established.
492 @retval EFI_NOT_READY The connection is in progress, call this routine again.
493 @retval Others The connection attempt failed.
497 EslTcp6ConnectStart (
498 IN ESL_SOCKET
* pSocket
502 ESL_TCP6_CONTEXT
* pTcp6
;
503 EFI_TCP6_PROTOCOL
* pTcp6Protocol
;
504 EFI_SIMPLE_NETWORK_MODE SnpModeData
;
510 // Determine if any more local adapters are available
512 pPort
= pSocket
->pPortList
;
513 if ( NULL
!= pPort
) {
515 // Configure the port
517 pTcp6
= &pPort
->Context
.Tcp6
;
518 pTcp6
->ConfigData
.AccessPoint
.ActiveFlag
= TRUE
;
519 pTcp6
->ConfigData
.TrafficClass
= 0;
520 pTcp6
->ConfigData
.HopLimit
= 255;
521 pTcp6Protocol
= pPort
->pProtocol
.TCPv6
;
522 Status
= pTcp6Protocol
->Configure ( pTcp6Protocol
,
523 &pTcp6
->ConfigData
);
524 if ( EFI_ERROR ( Status
)) {
525 DEBUG (( DEBUG_CONNECT
,
526 "ERROR - Failed to configure the Tcp6 port, Status: %r\r\n",
530 DEBUG (( DEBUG_CONNECT
,
531 "0x%08x: Port configured\r\n",
533 pPort
->bConfigured
= TRUE
;
536 // Verify the port connection
538 Status
= pTcp6Protocol
->GetModeData ( pTcp6Protocol
,
544 if ( !EFI_ERROR ( Status
)) {
545 if ( SnpModeData
.MediaPresentSupported
546 && ( !SnpModeData
.MediaPresent
)) {
548 // Port is not connected to the network
550 Status
= EFI_NO_MEDIA
;
554 // Attempt the connection to the remote system
556 Status
= pTcp6Protocol
->Connect ( pTcp6Protocol
,
557 &pTcp6
->ConnectToken
);
560 if ( EFI_ERROR ( Status
)) {
564 DEBUG (( DEBUG_CONNECT
,
565 "ERROR - Port 0x%08x not connected, Status: %r\r\n",
570 if ( !EFI_ERROR ( Status
)) {
572 // Connection in progress
574 pSocket
->errno
= EINPROGRESS
;
575 DEBUG (( DEBUG_CONNECT
,
576 "0x%08x: Port attempting connection to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
578 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[0],
579 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[1],
580 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[2],
581 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[3],
582 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[4],
583 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[5],
584 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[6],
585 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[7],
586 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[8],
587 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[9],
588 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[10],
589 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[11],
590 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[12],
591 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[13],
592 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[14],
593 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[15],
594 pTcp6
->ConfigData
.AccessPoint
.RemotePort
));
598 // Error return path is through EslTcp6ConnectComplete to
599 // enable retry on other ports
601 // Status to errno translation gets done in EslTcp4ConnectPoll
603 pTcp6
->ConnectToken
.CompletionToken
.Status
= Status
;
606 // Continue with the next port
608 gBS
->CheckEvent ( pTcp6
->ConnectToken
.CompletionToken
.Event
);
609 gBS
->SignalEvent ( pTcp6
->ConnectToken
.CompletionToken
.Event
);
611 Status
= EFI_NOT_READY
;
615 // No more local adapters available
617 pSocket
->errno
= ENETUNREACH
;
618 Status
= EFI_NO_RESPONSE
;
622 // Return the operation status
624 DBG_EXIT_STATUS ( Status
);
630 Establish the known port to listen for network connections.
632 This routine places the port into a state that enables connection
635 This routine is called by ::EslSocketListen to handle the network
636 specifics of the listen operation for SOCK_STREAM and SOCK_SEQPACKET
637 sockets. See the \ref ConnectionManagement section.
639 @param [in] pSocket Address of an ::ESL_SOCKET structure.
641 @retval EFI_SUCCESS - Socket successfully created
642 @retval Other - Failed to enable the socket for listen
647 IN ESL_SOCKET
* pSocket
650 ESL_PORT
* pNextPort
;
652 ESL_TCP6_CONTEXT
* pTcp6
;
653 EFI_TCP6_PROTOCOL
* pTcp6Protocol
;
659 // Verify the socket layer synchronization
661 VERIFY_TPL ( TPL_SOCKETS
);
664 // Use for/break instead of goto
668 // Assume no ports are available
670 pSocket
->errno
= EOPNOTSUPP
;
671 Status
= EFI_NOT_READY
;
674 // Walk the list of ports
676 pPort
= pSocket
->pPortList
;
677 while ( NULL
!= pPort
) {
684 // Use for/break insteak of goto
688 // Create the listen completion event
690 pTcp6
= &pPort
->Context
.Tcp6
;
691 Status
= gBS
->CreateEvent ( EVT_NOTIFY_SIGNAL
,
693 (EFI_EVENT_NOTIFY
)EslTcp6ListenComplete
,
695 &pTcp6
->ListenToken
.CompletionToken
.Event
);
696 if ( EFI_ERROR ( Status
)) {
697 DEBUG (( DEBUG_ERROR
| DEBUG_LISTEN
,
698 "ERROR - Failed to create the listen completion event, Status: %r\r\n",
700 pSocket
->errno
= ENOMEM
;
704 "0x%08x: Created listen completion event\r\n",
705 pTcp6
->ListenToken
.CompletionToken
.Event
));
708 // Configure the port
710 pTcp6Protocol
= pPort
->pProtocol
.TCPv6
;
711 Status
= pTcp6Protocol
->Configure ( pTcp6Protocol
,
712 &pTcp6
->ConfigData
);
713 if ( EFI_ERROR ( Status
)) {
714 DEBUG (( DEBUG_LISTEN
,
715 "ERROR - Failed to configure the Tcp6 port, Status: %r\r\n",
718 case EFI_ACCESS_DENIED
:
719 pSocket
->errno
= EACCES
;
723 case EFI_DEVICE_ERROR
:
724 pSocket
->errno
= EIO
;
727 case EFI_INVALID_PARAMETER
:
728 pSocket
->errno
= EADDRNOTAVAIL
;
732 pSocket
->errno
= EAFNOSUPPORT
;
735 case EFI_OUT_OF_RESOURCES
:
736 pSocket
->errno
= ENOBUFS
;
739 case EFI_UNSUPPORTED
:
740 pSocket
->errno
= EOPNOTSUPP
;
745 DEBUG (( DEBUG_LISTEN
,
746 "0x%08x: Port configured\r\n",
748 pPort
->bConfigured
= TRUE
;
751 // Start the listen operation on the port
753 Status
= pTcp6Protocol
->Accept ( pTcp6Protocol
,
754 &pTcp6
->ListenToken
);
755 if ( EFI_ERROR ( Status
)) {
756 DEBUG (( DEBUG_LISTEN
,
757 "ERROR - Failed Tcp6 accept, Status: %r\r\n",
760 case EFI_ACCESS_DENIED
:
761 pSocket
->errno
= EACCES
;
765 case EFI_DEVICE_ERROR
:
766 pSocket
->errno
= EIO
;
769 case EFI_INVALID_PARAMETER
:
770 pSocket
->errno
= EADDRNOTAVAIL
;
773 case EFI_NOT_STARTED
:
774 pSocket
->errno
= ENETDOWN
;
777 case EFI_OUT_OF_RESOURCES
:
778 pSocket
->errno
= ENOBUFS
;
783 DEBUG (( DEBUG_LISTEN
,
784 "0x%08x: Listen pending on Port\r\n",
788 // Listen is pending on this port
796 pNextPort
= pPort
->pLinkSocket
;
799 // Close the port upon error
801 if ( EFI_ERROR ( Status
)) {
802 EslSocketPortCloseStart ( pPort
, TRUE
, DEBUG_LISTEN
);
812 // Determine if any ports are in the listen state
814 if ( NULL
== pSocket
->pPortList
) {
816 // No ports in the listen state
818 pSocket
->MaxFifoDepth
= 0;
821 // Return the last error detected
827 // Mark the socket as configured
829 pSocket
->bConfigured
= TRUE
;
830 Status
= EFI_SUCCESS
;
836 DEBUG (( DEBUG_LISTEN
,
837 "0x%08x: pSocket - Listen pending on socket\r\n",
843 // Return the operation status
845 DBG_EXIT_STATUS ( Status
);
851 Process the connection attempt
853 A system has initiated a connection attempt with a socket in the
854 listen state. Attempt to complete the connection.
856 The TCPv6 layer calls this routine when a connection is made to
857 the socket in the listen state. See the
858 \ref ConnectionManagement section.
860 @param [in] Event The listen completion event
862 @param [in] pPort Address of an ::ESL_PORT structure.
866 EslTcp6ListenComplete (
871 EFI_HANDLE ChildHandle
;
872 struct sockaddr_in6 LocalAddress
;
873 EFI_TCP6_CONFIG_DATA
* pConfigData
;
875 ESL_SOCKET
* pNewSocket
;
876 ESL_SOCKET
* pSocket
;
877 ESL_TCP6_CONTEXT
* pTcp6
;
878 EFI_TCP6_PROTOCOL
* pTcp6Protocol
;
880 EFI_HANDLE TcpPortHandle
;
881 EFI_STATUS TempStatus
;
884 VERIFY_AT_TPL ( TPL_SOCKETS
);
889 Status
= EFI_SUCCESS
;
892 // Determine if this connection fits into the connection FIFO
894 pSocket
= pPort
->pSocket
;
895 TcpPortHandle
= pPort
->Context
.Tcp6
.ListenToken
.NewChildHandle
;
896 if (( SOCKET_STATE_LISTENING
== pSocket
->State
)
897 && ( pSocket
->MaxFifoDepth
> pSocket
->FifoDepth
)) {
899 // Allocate a socket for this connection
902 Status
= EslSocketAllocate ( &ChildHandle
,
905 if ( !EFI_ERROR ( Status
)) {
907 // Clone the socket parameters
909 pNewSocket
->pApi
= pSocket
->pApi
;
910 pNewSocket
->Domain
= pSocket
->Domain
;
911 pNewSocket
->Protocol
= pSocket
->Protocol
;
912 pNewSocket
->Type
= pSocket
->Type
;
915 // Build the local address
917 pTcp6
= &pPort
->Context
.Tcp6
;
918 LocalAddress
.sin6_len
= (uint8_t)pNewSocket
->pApi
->MinimumAddressLength
;
919 LocalAddress
.sin6_family
= AF_INET6
;
920 LocalAddress
.sin6_port
= 0;
921 CopyMem ( &LocalAddress
.sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
922 &pTcp6
->ConfigData
.AccessPoint
.StationAddress
.Addr
[ 0 ],
923 sizeof ( pTcp6
->ConfigData
.AccessPoint
.StationAddress
.Addr
));
926 // Allocate a port for this connection
927 // Note in this instance Configure may not be called with NULL!
929 Status
= EslSocketPortAllocate ( pNewSocket
,
932 (struct sockaddr
*)&LocalAddress
,
936 if ( !EFI_ERROR ( Status
)) {
938 // Restart the listen operation on the port
940 pTcp6Protocol
= pPort
->pProtocol
.TCPv6
;
941 Status
= pTcp6Protocol
->Accept ( pTcp6Protocol
,
942 &pTcp6
->ListenToken
);
945 // Close the TCP port using SocketClose
947 TcpPortHandle
= NULL
;
948 pTcp6
= &pNewPort
->Context
.Tcp6
;
951 // Check for an accept call error
953 if ( !EFI_ERROR ( Status
)) {
955 // Get the port configuration
957 pNewPort
->bConfigured
= TRUE
;
958 pConfigData
= &pTcp6
->ConfigData
;
959 pConfigData
->ControlOption
= &pTcp6
->Option
;
960 pTcp6Protocol
= pNewPort
->pProtocol
.TCPv6
;
961 Status
= pTcp6Protocol
->GetModeData ( pTcp6Protocol
,
967 if ( !EFI_ERROR ( Status
)) {
969 // Add the new socket to the connection FIFO
971 if ( NULL
== pSocket
->pFifoTail
) {
975 pSocket
->pFifoHead
= pNewSocket
;
979 // Add to end of list.
981 pSocket
->pFifoTail
->pNextConnection
= pNewSocket
;
983 pSocket
->pFifoTail
= pNewSocket
;
984 pSocket
->FifoDepth
+= 1;
987 // Update the socket state
989 pNewSocket
->State
= SOCKET_STATE_IN_FIFO
;
992 // Log the connection
994 DEBUG (( DEBUG_CONNECTION
| DEBUG_INFO
,
995 "0x%08x: Socket on port [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d connected to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
997 pConfigData
->AccessPoint
.StationAddress
.Addr
[0],
998 pConfigData
->AccessPoint
.StationAddress
.Addr
[1],
999 pConfigData
->AccessPoint
.StationAddress
.Addr
[2],
1000 pConfigData
->AccessPoint
.StationAddress
.Addr
[3],
1001 pConfigData
->AccessPoint
.StationAddress
.Addr
[4],
1002 pConfigData
->AccessPoint
.StationAddress
.Addr
[5],
1003 pConfigData
->AccessPoint
.StationAddress
.Addr
[6],
1004 pConfigData
->AccessPoint
.StationAddress
.Addr
[7],
1005 pConfigData
->AccessPoint
.StationAddress
.Addr
[8],
1006 pConfigData
->AccessPoint
.StationAddress
.Addr
[9],
1007 pConfigData
->AccessPoint
.StationAddress
.Addr
[10],
1008 pConfigData
->AccessPoint
.StationAddress
.Addr
[11],
1009 pConfigData
->AccessPoint
.StationAddress
.Addr
[12],
1010 pConfigData
->AccessPoint
.StationAddress
.Addr
[13],
1011 pConfigData
->AccessPoint
.StationAddress
.Addr
[14],
1012 pConfigData
->AccessPoint
.StationAddress
.Addr
[15],
1013 pConfigData
->AccessPoint
.StationPort
,
1014 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[0],
1015 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[1],
1016 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[2],
1017 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[3],
1018 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[4],
1019 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[5],
1020 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[6],
1021 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[7],
1022 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[8],
1023 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[9],
1024 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[10],
1025 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[11],
1026 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[12],
1027 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[13],
1028 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[14],
1029 pConfigData
->AccessPoint
.RemoteAddress
.Addr
[15],
1030 pConfigData
->AccessPoint
.RemotePort
));
1031 DEBUG (( DEBUG_CONNECTION
| DEBUG_INFO
,
1032 "0x%08x: Listen socket adding socket 0x%08x to FIFO, depth: %d\r\n",
1035 pSocket
->FifoDepth
));
1038 // Start the receive operation
1040 EslSocketRxStart ( pNewPort
);
1043 DEBUG (( DEBUG_ERROR
| DEBUG_CONNECTION
| DEBUG_INFO
,
1044 "ERROR - GetModeData failed on port 0x%08x, Status: %r\r\n",
1051 // The listen failed on this port
1053 DEBUG (( DEBUG_LISTEN
| DEBUG_INFO
,
1054 "ERROR - Listen failed on port 0x%08x, Status: %r\r\n",
1059 // Close the listening port
1061 EslSocketPortCloseStart ( pPort
, TRUE
, DEBUG_LISTEN
);
1066 // Done with the socket if necessary
1068 if ( EFI_ERROR ( Status
)) {
1069 TempStatus
= EslSocketCloseStart ( &pNewSocket
->SocketProtocol
,
1072 ASSERT ( EFI_SUCCESS
== TempStatus
);
1077 DEBUG (( DEBUG_CONNECTION
,
1078 "0x%08x: Socket FIFO full, connection refused\r\n",
1082 // The FIFO is full or the socket is in the wrong state
1084 Status
= EFI_BUFFER_TOO_SMALL
;
1088 // Close the connection if necessary
1090 if (( EFI_ERROR ( Status
))
1091 && ( NULL
== TcpPortHandle
)) {
1093 // TODO: Finish this code path
1094 // The new connection does not fit into the connection FIFO
1098 // Release the resources
1107 Get the local socket address.
1109 This routine returns the IPv6 address and TCP port number associated
1110 with the local socket.
1112 This routine is called by ::EslSocketGetLocalAddress to determine the
1113 network address for the SOCK_STREAM or SOCK_SEQPACKET socket.
1115 @param [in] pPort Address of an ::ESL_PORT structure.
1117 @param [out] pSockAddr Network address to receive the local system address
1121 EslTcp6LocalAddressGet (
1122 IN ESL_PORT
* pPort
,
1123 OUT
struct sockaddr
* pSockAddr
1126 struct sockaddr_in6
* pLocalAddress
;
1127 ESL_TCP6_CONTEXT
* pTcp6
;
1132 // Return the local address
1134 pTcp6
= &pPort
->Context
.Tcp6
;
1135 pLocalAddress
= (struct sockaddr_in6
*)pSockAddr
;
1136 pLocalAddress
->sin6_family
= AF_INET6
;
1137 pLocalAddress
->sin6_port
= SwapBytes16 ( pTcp6
->ConfigData
.AccessPoint
.StationPort
);
1138 CopyMem ( &pLocalAddress
->sin6_addr
,
1139 &pTcp6
->ConfigData
.AccessPoint
.StationAddress
.Addr
[0],
1140 sizeof ( pLocalAddress
->sin6_addr
));
1147 Set the local port address.
1149 This routine sets the local port address.
1151 This support routine is called by ::EslSocketPortAllocate.
1153 @param [in] pPort Address of an ESL_PORT structure
1154 @param [in] pSockAddr Address of a sockaddr structure that contains the
1155 connection point on the local machine. An IPv6 address
1156 of INADDR_ANY specifies that the connection is made to
1157 all of the network stacks on the platform. Specifying a
1158 specific IPv6 address restricts the connection to the
1159 network stack supporting that address. Specifying zero
1160 for the port causes the network layer to assign a port
1161 number from the dynamic range. Specifying a specific
1162 port number causes the network layer to use that port.
1164 @param [in] bBindTest TRUE = run bind testing
1166 @retval EFI_SUCCESS The operation was successful
1170 EslTcp6LocalAddressSet (
1171 IN ESL_PORT
* pPort
,
1172 IN CONST
struct sockaddr
* pSockAddr
,
1173 IN BOOLEAN bBindTest
1176 EFI_TCP6_ACCESS_POINT
* pAccessPoint
;
1177 CONST
struct sockaddr_in6
* pIpAddress
;
1183 // Validate the address
1185 pIpAddress
= (struct sockaddr_in6
*)pSockAddr
;
1187 // TODO: Fix the following check
1190 if ( INADDR_BROADCAST == pIpAddress->sin6_addr.s_addr ) {
1192 // The local address must not be the broadcast address
1194 Status = EFI_INVALID_PARAMETER;
1195 pPort->pSocket->errno = EADDRNOTAVAIL;
1201 // Set the local address
1203 pAccessPoint
= &pPort
->Context
.Tcp6
.ConfigData
.AccessPoint
;
1204 CopyMem ( &pAccessPoint
->StationAddress
.Addr
[0],
1205 &pIpAddress
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
1206 sizeof ( pIpAddress
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ]));
1209 // Validate the IP address
1211 pAccessPoint
->StationPort
= 0;
1212 Status
= bBindTest
? EslSocketBindTest ( pPort
, EADDRNOTAVAIL
)
1214 if ( !EFI_ERROR ( Status
)) {
1216 // Set the port number
1218 pAccessPoint
->StationPort
= SwapBytes16 ( pIpAddress
->sin6_port
);
1219 pPort
->pSocket
->bAddressSet
= TRUE
;
1222 // Display the local address
1224 DEBUG (( DEBUG_BIND
,
1225 "0x%08x: Port, Local Tcp6 Address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
1227 pAccessPoint
->StationAddress
.Addr
[0],
1228 pAccessPoint
->StationAddress
.Addr
[1],
1229 pAccessPoint
->StationAddress
.Addr
[2],
1230 pAccessPoint
->StationAddress
.Addr
[3],
1231 pAccessPoint
->StationAddress
.Addr
[4],
1232 pAccessPoint
->StationAddress
.Addr
[5],
1233 pAccessPoint
->StationAddress
.Addr
[6],
1234 pAccessPoint
->StationAddress
.Addr
[7],
1235 pAccessPoint
->StationAddress
.Addr
[8],
1236 pAccessPoint
->StationAddress
.Addr
[9],
1237 pAccessPoint
->StationAddress
.Addr
[10],
1238 pAccessPoint
->StationAddress
.Addr
[11],
1239 pAccessPoint
->StationAddress
.Addr
[12],
1240 pAccessPoint
->StationAddress
.Addr
[13],
1241 pAccessPoint
->StationAddress
.Addr
[14],
1242 pAccessPoint
->StationAddress
.Addr
[15],
1243 pAccessPoint
->StationPort
));
1248 // Return the operation status
1250 DBG_EXIT_STATUS ( Status
);
1256 Free a receive packet
1258 This routine performs the network specific operations necessary
1259 to free a receive packet.
1261 This routine is called by ::EslSocketPortCloseTxDone to free a
1264 @param [in] pPacket Address of an ::ESL_PACKET structure.
1265 @param [in, out] pRxBytes Address of the count of RX bytes
1270 IN ESL_PACKET
* pPacket
,
1271 IN OUT
size_t * pRxBytes
1277 // Account for the receive bytes
1279 *pRxBytes
-= pPacket
->Op
.Tcp6Rx
.RxData
.DataLength
;
1285 Initialize the network specific portions of an ::ESL_PORT structure.
1287 This routine initializes the network specific portions of an
1288 ::ESL_PORT structure for use by the socket.
1290 This support routine is called by ::EslSocketPortAllocate
1291 to connect the socket with the underlying network adapter
1292 running the TCPv6 protocol.
1294 @param [in] pPort Address of an ESL_PORT structure
1295 @param [in] DebugFlags Flags for debug messages
1297 @retval EFI_SUCCESS - Socket successfully created
1301 EslTcp6PortAllocate (
1302 IN ESL_PORT
* pPort
,
1306 EFI_TCP6_ACCESS_POINT
* pAccessPoint
;
1307 ESL_SOCKET
* pSocket
;
1308 ESL_TCP6_CONTEXT
* pTcp6
;
1314 // Use for/break instead of goto
1317 // Allocate the close event
1319 pSocket
= pPort
->pSocket
;
1320 pTcp6
= &pPort
->Context
.Tcp6
;
1321 Status
= gBS
->CreateEvent ( EVT_NOTIFY_SIGNAL
,
1323 (EFI_EVENT_NOTIFY
)EslSocketPortCloseComplete
,
1325 &pTcp6
->CloseToken
.CompletionToken
.Event
);
1326 if ( EFI_ERROR ( Status
)) {
1327 DEBUG (( DEBUG_ERROR
| DebugFlags
,
1328 "ERROR - Failed to create the close event, Status: %r\r\n",
1330 pSocket
->errno
= ENOMEM
;
1333 DEBUG (( DEBUG_CLOSE
| DEBUG_POOL
,
1334 "0x%08x: Created close event\r\n",
1335 pTcp6
->CloseToken
.CompletionToken
.Event
));
1338 // Allocate the connection event
1340 Status
= gBS
->CreateEvent ( EVT_NOTIFY_SIGNAL
,
1342 (EFI_EVENT_NOTIFY
)EslTcp6ConnectComplete
,
1344 &pTcp6
->ConnectToken
.CompletionToken
.Event
);
1345 if ( EFI_ERROR ( Status
)) {
1346 DEBUG (( DEBUG_ERROR
| DebugFlags
,
1347 "ERROR - Failed to create the connect event, Status: %r\r\n",
1349 pSocket
->errno
= ENOMEM
;
1352 DEBUG (( DEBUG_CLOSE
| DEBUG_POOL
,
1353 "0x%08x: Created connect event\r\n",
1354 pTcp6
->ConnectToken
.CompletionToken
.Event
));
1357 // Initialize the port
1359 pSocket
->TxPacketOffset
= OFFSET_OF ( ESL_PACKET
, Op
.Tcp6Tx
.TxData
);
1360 pSocket
->TxTokenEventOffset
= OFFSET_OF ( ESL_IO_MGMT
, Token
.Tcp6Tx
.CompletionToken
.Event
);
1361 pSocket
->TxTokenOffset
= OFFSET_OF ( EFI_TCP6_IO_TOKEN
, Packet
.TxData
);
1364 // Save the cancel, receive and transmit addresses
1365 // pPort->pfnRxCancel = NULL; since the UEFI implementation returns EFI_UNSUPPORTED
1367 pPort
->pfnConfigure
= (PFN_NET_CONFIGURE
)pPort
->pProtocol
.TCPv6
->Configure
;
1368 pPort
->pfnRxPoll
= (PFN_NET_POLL
)pPort
->pProtocol
.TCPv6
->Poll
;
1369 pPort
->pfnRxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.TCPv6
->Receive
;
1370 pPort
->pfnTxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.TCPv6
->Transmit
;
1373 // Set the configuration flags
1375 pAccessPoint
= &pPort
->Context
.Tcp6
.ConfigData
.AccessPoint
;
1376 pAccessPoint
->ActiveFlag
= FALSE
;
1377 pTcp6
->ConfigData
.TrafficClass
= 0;
1378 pTcp6
->ConfigData
.HopLimit
= 255;
1383 // Return the operation status
1385 DBG_EXIT_STATUS ( Status
);
1393 This routine releases the network specific resources allocated by
1394 ::EslTcp6PortAllocate.
1396 This routine is called by ::EslSocketPortClose.
1397 See the \ref PortCloseStateMachine section.
1399 @param [in] pPort Address of an ::ESL_PORT structure.
1401 @retval EFI_SUCCESS The port is closed
1402 @retval other Port close error
1411 ESL_TCP6_CONTEXT
* pTcp6
;
1417 // Locate the port in the socket list
1419 Status
= EFI_SUCCESS
;
1420 DebugFlags
= pPort
->DebugFlags
;
1421 pTcp6
= &pPort
->Context
.Tcp6
;
1424 // Done with the connect event
1426 if ( NULL
!= pTcp6
->ConnectToken
.CompletionToken
.Event
) {
1427 Status
= gBS
->CloseEvent ( pTcp6
->ConnectToken
.CompletionToken
.Event
);
1428 if ( !EFI_ERROR ( Status
)) {
1429 DEBUG (( DebugFlags
| DEBUG_POOL
,
1430 "0x%08x: Closed connect event\r\n",
1431 pTcp6
->ConnectToken
.CompletionToken
.Event
));
1434 DEBUG (( DEBUG_ERROR
| DebugFlags
,
1435 "ERROR - Failed to close the connect event, Status: %r\r\n",
1437 ASSERT ( EFI_SUCCESS
== Status
);
1442 // Done with the close event
1444 if ( NULL
!= pTcp6
->CloseToken
.CompletionToken
.Event
) {
1445 Status
= gBS
->CloseEvent ( pTcp6
->CloseToken
.CompletionToken
.Event
);
1446 if ( !EFI_ERROR ( Status
)) {
1447 DEBUG (( DebugFlags
| DEBUG_POOL
,
1448 "0x%08x: Closed close event\r\n",
1449 pTcp6
->CloseToken
.CompletionToken
.Event
));
1452 DEBUG (( DEBUG_ERROR
| DebugFlags
,
1453 "ERROR - Failed to close the close event, Status: %r\r\n",
1455 ASSERT ( EFI_SUCCESS
== Status
);
1460 // Done with the listen completion event
1462 if ( NULL
!= pTcp6
->ListenToken
.CompletionToken
.Event
) {
1463 Status
= gBS
->CloseEvent ( pTcp6
->ListenToken
.CompletionToken
.Event
);
1464 if ( !EFI_ERROR ( Status
)) {
1465 DEBUG (( DebugFlags
| DEBUG_POOL
,
1466 "0x%08x: Closed listen completion event\r\n",
1467 pTcp6
->ListenToken
.CompletionToken
.Event
));
1470 DEBUG (( DEBUG_ERROR
| DebugFlags
,
1471 "ERROR - Failed to close the listen completion event, Status: %r\r\n",
1473 ASSERT ( EFI_SUCCESS
== Status
);
1478 // Return the operation status
1480 DBG_EXIT_STATUS ( Status
);
1486 Perform the network specific close operation on the port.
1488 This routine performs a cancel operations on the TCPv6 port to
1489 shutdown the receive operations on the port.
1491 This routine is called by the ::EslSocketPortCloseTxDone
1492 routine after the port completes all of the transmission.
1494 @param [in] pPort Address of an ::ESL_PORT structure.
1496 @retval EFI_SUCCESS The port is closed, not normally returned
1497 @retval EFI_NOT_READY The port is still closing
1498 @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
1499 most likely the routine was called already.
1503 EslTcp6PortCloseOp (
1507 ESL_TCP6_CONTEXT
* pTcp6
;
1508 EFI_TCP6_PROTOCOL
* pTcp6Protocol
;
1514 // Close the configured port
1516 Status
= EFI_SUCCESS
;
1517 pTcp6
= &pPort
->Context
.Tcp6
;
1518 pTcp6Protocol
= pPort
->pProtocol
.TCPv6
;
1519 pTcp6
->CloseToken
.AbortOnClose
= pPort
->bCloseNow
;
1520 Status
= pTcp6Protocol
->Close ( pTcp6Protocol
,
1521 &pTcp6
->CloseToken
);
1522 if ( !EFI_ERROR ( Status
)) {
1523 DEBUG (( pPort
->DebugFlags
| DEBUG_CLOSE
| DEBUG_INFO
,
1524 "0x%08x: Port close started\r\n",
1528 DEBUG (( DEBUG_ERROR
| pPort
->DebugFlags
| DEBUG_CLOSE
| DEBUG_INFO
,
1529 "ERROR - Close failed on port 0x%08x, Status: %r\r\n",
1535 // Return the operation status
1537 DBG_EXIT_STATUS ( Status
);
1543 Receive data from a network connection.
1545 This routine attempts to return buffered data to the caller. The
1546 data is removed from the urgent queue if the message flag MSG_OOB
1547 is specified, otherwise data is removed from the normal queue.
1548 See the \ref ReceiveEngine section.
1550 This routine is called by ::EslSocketReceive to handle the network
1551 specific receive operation to support SOCK_STREAM and SOCK_SEQPACKET
1554 @param [in] pPort Address of an ::ESL_PORT structure.
1556 @param [in] pPacket Address of an ::ESL_PACKET structure.
1558 @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
1560 @param [in] BufferLength Length of the the buffer
1562 @param [in] pBuffer Address of a buffer to receive the data.
1564 @param [in] pDataLength Number of received data bytes in the buffer.
1566 @param [out] pAddress Network address to receive the remote system address
1568 @param [out] pSkipBytes Address to receive the number of bytes skipped
1570 @return Returns the address of the next free byte in the buffer.
1575 IN ESL_PORT
* pPort
,
1576 IN ESL_PACKET
* pPacket
,
1577 IN BOOLEAN
* pbConsumePacket
,
1578 IN
size_t BufferLength
,
1580 OUT
size_t * pDataLength
,
1581 OUT
struct sockaddr
* pAddress
,
1582 OUT
size_t * pSkipBytes
1586 struct sockaddr_in6
* pRemoteAddress
;
1587 ESL_TCP6_CONTEXT
* pTcp6
;
1592 // Return the remote system address if requested
1594 if ( NULL
!= pAddress
) {
1596 // Build the remote address
1598 pTcp6
= &pPort
->Context
.Tcp6
;
1600 "Getting packet remote address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
1601 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[0],
1602 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[1],
1603 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[2],
1604 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[3],
1605 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[4],
1606 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[5],
1607 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[6],
1608 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[7],
1609 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[8],
1610 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[9],
1611 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[10],
1612 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[11],
1613 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[12],
1614 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[13],
1615 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[14],
1616 pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[15],
1617 pTcp6
->ConfigData
.AccessPoint
.RemotePort
));
1618 pRemoteAddress
= (struct sockaddr_in6
*)pAddress
;
1619 CopyMem ( &pRemoteAddress
->sin6_addr
,
1620 &pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[0],
1621 sizeof ( pRemoteAddress
->sin6_addr
));
1622 pRemoteAddress
->sin6_port
= SwapBytes16 ( pTcp6
->ConfigData
.AccessPoint
.RemotePort
);
1626 // Determine the amount of received data
1628 DataLength
= pPacket
->ValidBytes
;
1629 if ( BufferLength
< DataLength
) {
1630 DataLength
= BufferLength
;
1634 // Move the data into the buffer
1637 "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",
1642 CopyMem ( pBuffer
, pPacket
->pBuffer
, DataLength
);
1645 // Set the next buffer address
1647 pBuffer
+= DataLength
;
1650 // Determine if the data is being read
1652 if ( *pbConsumePacket
) {
1654 // Account for the bytes consumed
1656 pPacket
->pBuffer
+= DataLength
;
1657 pPacket
->ValidBytes
-= DataLength
;
1659 "0x%08x: Port account for 0x%08x bytes\r\n",
1664 // Determine if the entire packet was consumed
1666 if (( 0 == pPacket
->ValidBytes
)
1667 || ( SOCK_STREAM
!= pPort
->pSocket
->Type
)) {
1669 // All done with this packet
1670 // Account for any discarded data
1672 *pSkipBytes
= pPacket
->ValidBytes
;
1677 // More data to consume later
1679 *pbConsumePacket
= FALSE
;
1684 // Return the data length and the buffer address
1686 *pDataLength
= DataLength
;
1687 DBG_EXIT_HEX ( pBuffer
);
1693 Get the remote socket address.
1695 This routine returns the address of the remote connection point
1696 associated with the SOCK_STREAM or SOCK_SEQPACKET socket.
1698 This routine is called by ::EslSocketGetPeerAddress to detemine
1699 the TCPv6 address and por number associated with the network adapter.
1701 @param [in] pPort Address of an ::ESL_PORT structure.
1703 @param [out] pAddress Network address to receive the remote system address
1707 EslTcp6RemoteAddressGet (
1708 IN ESL_PORT
* pPort
,
1709 OUT
struct sockaddr
* pAddress
1712 struct sockaddr_in6
* pRemoteAddress
;
1713 ESL_TCP6_CONTEXT
* pTcp6
;
1718 // Return the remote address
1720 pTcp6
= &pPort
->Context
.Tcp6
;
1721 pRemoteAddress
= (struct sockaddr_in6
*)pAddress
;
1722 pRemoteAddress
->sin6_family
= AF_INET6
;
1723 pRemoteAddress
->sin6_port
= SwapBytes16 ( pTcp6
->ConfigData
.AccessPoint
.RemotePort
);
1724 CopyMem ( &pRemoteAddress
->sin6_addr
,
1725 &pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[0],
1726 sizeof ( pRemoteAddress
->sin6_addr
));
1733 Set the remote address
1735 This routine sets the remote address in the port.
1737 This routine is called by ::EslSocketConnect to specify the
1738 remote network address.
1740 @param [in] pPort Address of an ::ESL_PORT structure.
1742 @param [in] pSockAddr Network address of the remote system.
1744 @param [in] SockAddrLength Length in bytes of the network address.
1746 @retval EFI_SUCCESS The operation was successful
1750 EslTcp6RemoteAddressSet (
1751 IN ESL_PORT
* pPort
,
1752 IN CONST
struct sockaddr
* pSockAddr
,
1753 IN socklen_t SockAddrLength
1756 CONST
struct sockaddr_in6
* pRemoteAddress
;
1757 ESL_TCP6_CONTEXT
* pTcp6
;
1763 // Set the remote address
1765 pTcp6
= &pPort
->Context
.Tcp6
;
1766 pRemoteAddress
= (struct sockaddr_in6
*)pSockAddr
;
1767 CopyMem ( &pTcp6
->ConfigData
.AccessPoint
.RemoteAddress
.Addr
[ 0 ],
1768 &pRemoteAddress
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
1769 sizeof ( pRemoteAddress
->sin6_addr
.__u6_addr
.__u6_addr8
));
1770 pTcp6
->ConfigData
.AccessPoint
.RemotePort
= SwapBytes16 ( pRemoteAddress
->sin6_port
);
1771 Status
= EFI_SUCCESS
;
1774 // TODO: Fix the following check
1777 if ( INADDR_BROADCAST == pRemoteAddress->sin6_addr.s_addr ) {
1778 DEBUG (( DEBUG_CONNECT,
1779 "ERROR - Invalid remote address\r\n" ));
1780 Status = EFI_INVALID_PARAMETER;
1781 pPort->pSocket->errno = EAFNOSUPPORT;
1786 // Return the operation status
1788 DBG_EXIT_STATUS ( Status
);
1794 Process the receive completion
1796 This routine queues the data in FIFO order in either the urgent
1797 or normal data queues depending upon the type of data received.
1798 See the \ref ReceiveEngine section.
1800 This routine is called by the TCPv6 driver when some data is
1803 Buffer the data that was just received.
1805 @param [in] Event The receive completion event
1807 @param [in] pIo Address of an ::ESL_IO_MGMT structure
1813 IN ESL_IO_MGMT
* pIo
1817 size_t LengthInBytes
;
1818 ESL_PACKET
* pPacket
;
1824 // Get the operation status.
1826 Status
= pIo
->Token
.Tcp6Rx
.CompletionToken
.Status
;
1829 // +--------------------+ +---------------------------+
1830 // | ESL_IO_MGMT | | ESL_PACKET |
1832 // | +---------------+ +-----------------------+ |
1833 // | | Token | | EFI_Tcp6_RECEIVE_DATA | |
1834 // | | RxData --> | | |
1835 // | | | +-----------------------+---+
1836 // | | Event | | Data Buffer |
1837 // +----+---------------+ | |
1839 // +---------------------------+
1842 // Duplicate the buffer address and length for use by the
1843 // buffer handling code in EslTcp6Receive. These fields are
1844 // used when a partial read is done of the data from the
1847 pPacket
= pIo
->pPacket
;
1848 pPacket
->pBuffer
= pPacket
->Op
.Tcp6Rx
.RxData
.FragmentTable
[0].FragmentBuffer
;
1849 LengthInBytes
= pPacket
->Op
.Tcp6Rx
.RxData
.DataLength
;
1850 pPacket
->ValidBytes
= LengthInBytes
;
1853 // Get the data type so that it may be linked to the
1854 // correct receive buffer list on the ESL_SOCKET structure
1856 bUrgent
= pPacket
->Op
.Tcp6Rx
.RxData
.UrgentFlag
;
1859 // Complete this request
1861 EslSocketRxComplete ( pIo
, Status
, LengthInBytes
, bUrgent
);
1867 Start a receive operation
1869 This routine posts a receive buffer to the TCPv6 driver.
1870 See the \ref ReceiveEngine section.
1872 This support routine is called by EslSocketRxStart.
1874 @param [in] pPort Address of an ::ESL_PORT structure.
1875 @param [in] pIo Address of an ::ESL_IO_MGMT structure.
1880 IN ESL_PORT
* pPort
,
1881 IN ESL_IO_MGMT
* pIo
1884 ESL_PACKET
* pPacket
;
1889 // Initialize the buffer for receive
1891 pPacket
= pIo
->pPacket
;
1892 pIo
->Token
.Tcp6Rx
.Packet
.RxData
= &pPacket
->Op
.Tcp6Rx
.RxData
;
1893 pPacket
->Op
.Tcp6Rx
.RxData
.DataLength
= sizeof ( pPacket
->Op
.Tcp6Rx
.Buffer
);
1894 pPacket
->Op
.Tcp6Rx
.RxData
.FragmentCount
= 1;
1895 pPacket
->Op
.Tcp6Rx
.RxData
.FragmentTable
[0].FragmentLength
= pPacket
->Op
.Tcp6Rx
.RxData
.DataLength
;
1896 pPacket
->Op
.Tcp6Rx
.RxData
.FragmentTable
[0].FragmentBuffer
= &pPacket
->Op
.Tcp6Rx
.Buffer
[0];
1903 Determine if the socket is configured.
1905 This routine uses the flag ESL_SOCKET::bConfigured to determine
1906 if the network layer's configuration routine has been called.
1908 This routine is called by EslSocketIsConfigured to verify
1909 that the socket has been configured.
1911 @param [in] pSocket Address of an ::ESL_SOCKET structure.
1913 @retval EFI_SUCCESS - The port is connected
1914 @retval EFI_NOT_STARTED - The port is not connected
1918 EslTcp6SocketIsConfigured (
1919 IN ESL_SOCKET
* pSocket
1927 // Determine the socket configuration status
1929 Status
= pSocket
->bConfigured
? EFI_SUCCESS
: EFI_NOT_STARTED
;
1932 // Return the port connected state.
1934 DBG_EXIT_STATUS ( Status
);
1940 Buffer data for transmission over a network connection.
1942 This routine buffers data for the transmit engine in one of two
1943 queues, one for urgent (out-of-band) data and the other for normal
1944 data. The urgent data is provided to TCP as soon as it is available,
1945 allowing the TCP layer to schedule transmission of the urgent data
1946 between packets of normal data.
1948 This routine is called by ::EslSocketTransmit to buffer
1949 data for transmission. When the \ref TransmitEngine has resources,
1950 this routine will start the transmission of the next buffer on
1951 the network connection.
1953 Transmission errors are returned during the next transmission or
1954 during the close operation. Only buffering errors are returned
1955 during the current transmission attempt.
1957 @param [in] pSocket Address of an ::ESL_SOCKET structure
1959 @param [in] Flags Message control flags
1961 @param [in] BufferLength Length of the the buffer
1963 @param [in] pBuffer Address of a buffer to receive the data.
1965 @param [in] pDataLength Number of received data bytes in the buffer.
1967 @param [in] pAddress Network address of the remote system address
1969 @param [in] AddressLength Length of the remote network address structure
1971 @retval EFI_SUCCESS - Socket data successfully buffered
1976 IN ESL_SOCKET
* pSocket
,
1978 IN
size_t BufferLength
,
1979 IN CONST UINT8
* pBuffer
,
1980 OUT
size_t * pDataLength
,
1981 IN
const struct sockaddr
* pAddress
,
1982 IN socklen_t AddressLength
1986 BOOLEAN bUrgentQueue
;
1987 ESL_PACKET
* pPacket
;
1988 ESL_IO_MGMT
** ppActive
;
1989 ESL_IO_MGMT
** ppFree
;
1991 ESL_PACKET
** ppQueueHead
;
1992 ESL_PACKET
** ppQueueTail
;
1993 ESL_PACKET
* pPreviousPacket
;
1995 EFI_TCP6_TRANSMIT_DATA
* pTxData
;
1997 EFI_TPL TplPrevious
;
2004 Status
= EFI_UNSUPPORTED
;
2005 pSocket
->errno
= ENOTCONN
;
2009 // Verify that the socket is connected
2011 if ( SOCKET_STATE_CONNECTED
== pSocket
->State
) {
2015 pPort
= pSocket
->pPortList
;
2016 if ( NULL
!= pPort
) {
2018 // Determine the queue head
2020 bUrgent
= (BOOLEAN
)( 0 != ( Flags
& MSG_OOB
));
2021 bUrgentQueue
= bUrgent
2022 && ( !pSocket
->bOobInLine
)
2023 && pSocket
->pApi
->bOobSupported
;
2024 if ( bUrgentQueue
) {
2025 ppQueueHead
= &pSocket
->pTxOobPacketListHead
;
2026 ppQueueTail
= &pSocket
->pTxOobPacketListTail
;
2027 ppActive
= &pPort
->pTxOobActive
;
2028 ppFree
= &pPort
->pTxOobFree
;
2029 pTxBytes
= &pSocket
->TxOobBytes
;
2032 ppQueueHead
= &pSocket
->pTxPacketListHead
;
2033 ppQueueTail
= &pSocket
->pTxPacketListTail
;
2034 ppActive
= &pPort
->pTxActive
;
2035 ppFree
= &pPort
->pTxFree
;
2036 pTxBytes
= &pSocket
->TxBytes
;
2040 // Verify that there is enough room to buffer another
2041 // transmit operation
2043 if ( pSocket
->MaxTxBuf
> *pTxBytes
) {
2044 if ( pPort
->bTxFlowControl
) {
2046 "TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\r\n0x%08x: pPort, TX flow control released, Max bytes: %d > %d bufferred bytes\r\n",
2050 pPort
->bTxFlowControl
= FALSE
;
2054 // Attempt to allocate the packet
2056 Status
= EslSocketPacketAllocate ( &pPacket
,
2057 sizeof ( pPacket
->Op
.Tcp6Tx
)
2058 - sizeof ( pPacket
->Op
.Tcp6Tx
.Buffer
)
2062 if ( !EFI_ERROR ( Status
)) {
2064 // Initialize the transmit operation
2066 pTxData
= &pPacket
->Op
.Tcp6Tx
.TxData
;
2067 pTxData
->Push
= TRUE
|| bUrgent
;
2068 pTxData
->Urgent
= bUrgent
;
2069 pTxData
->DataLength
= (UINT32
) BufferLength
;
2070 pTxData
->FragmentCount
= 1;
2071 pTxData
->FragmentTable
[0].FragmentLength
= (UINT32
) BufferLength
;
2072 pTxData
->FragmentTable
[0].FragmentBuffer
= &pPacket
->Op
.Tcp6Tx
.Buffer
[0];
2075 // Copy the data into the buffer
2077 CopyMem ( &pPacket
->Op
.Tcp6Tx
.Buffer
[0],
2082 // Synchronize with the socket layer
2084 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
2087 // Stop transmission after an error
2089 if ( !EFI_ERROR ( pSocket
->TxError
)) {
2091 // Display the request
2094 "Send %d %s bytes from 0x%08x\r\n",
2096 bUrgent
? L
"urgent" : L
"normal",
2100 // Queue the data for transmission
2102 pPacket
->pNext
= NULL
;
2103 pPreviousPacket
= *ppQueueTail
;
2104 if ( NULL
== pPreviousPacket
) {
2105 *ppQueueHead
= pPacket
;
2108 pPreviousPacket
->pNext
= pPacket
;
2110 *ppQueueTail
= pPacket
;
2112 "0x%08x: Packet on %s transmit list\r\n",
2114 bUrgentQueue
? L
"urgent" : L
"normal" ));
2117 // Account for the buffered data
2119 *pTxBytes
+= BufferLength
;
2120 *pDataLength
= BufferLength
;
2123 // Start the transmit engine if it is idle
2125 if ( NULL
!= *ppFree
) {
2126 EslSocketTxStart ( pPort
,
2135 // Previous transmit error
2136 // Stop transmission
2138 Status
= pSocket
->TxError
;
2139 pSocket
->errno
= EIO
;
2144 EslSocketPacketFree ( pPacket
, DEBUG_TX
);
2148 // Release the socket layer synchronization
2150 RESTORE_TPL ( TplPrevious
);
2154 // Packet allocation failed
2156 pSocket
->errno
= ENOMEM
;
2160 if ( !pPort
->bTxFlowControl
) {
2162 "0x%08x: pPort, TX flow control applied, Max bytes %d <= %d bufferred bytes\r\nTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\r\n",
2166 pPort
->bTxFlowControl
= TRUE
;
2169 // Not enough buffer space available
2171 pSocket
->errno
= EAGAIN
;
2172 Status
= EFI_NOT_READY
;
2178 // Return the operation status
2180 DBG_EXIT_STATUS ( Status
);
2186 Process the normal data transmit completion
2188 This routine use ::EslSocketTxComplete to perform the transmit
2189 completion processing for normal data.
2191 This routine is called by the TCPv6 network layer when a
2192 normal data transmit request completes.
2194 @param [in] Event The normal transmit completion event
2196 @param [in] pIo The ESL_IO_MGMT structure address
2202 IN ESL_IO_MGMT
* pIo
2205 UINT32 LengthInBytes
;
2206 ESL_PACKET
* pPacket
;
2208 ESL_SOCKET
* pSocket
;
2214 // Locate the active transmit packet
2216 pPacket
= pIo
->pPacket
;
2218 pSocket
= pPort
->pSocket
;
2221 // Get the transmit length and status
2223 LengthInBytes
= pPacket
->Op
.Tcp6Tx
.TxData
.DataLength
;
2224 pSocket
->TxBytes
-= LengthInBytes
;
2225 Status
= pIo
->Token
.Tcp6Tx
.CompletionToken
.Status
;
2228 // Complete the transmit operation
2230 EslSocketTxComplete ( pIo
,
2234 &pSocket
->pTxPacketListHead
,
2235 &pSocket
->pTxPacketListTail
,
2243 Process the urgent data transmit completion
2245 This routine use ::EslSocketTxComplete to perform the transmit
2246 completion processing for urgent data.
2248 This routine is called by the TCPv6 network layer when a
2249 urgent data transmit request completes.
2251 @param [in] Event The urgent transmit completion event
2253 @param [in] pIo The ESL_IO_MGMT structure address
2257 EslTcp6TxOobComplete (
2259 IN ESL_IO_MGMT
* pIo
2262 UINT32 LengthInBytes
;
2263 ESL_PACKET
* pPacket
;
2265 ESL_SOCKET
* pSocket
;
2271 // Locate the active transmit packet
2273 pPacket
= pIo
->pPacket
;
2275 pSocket
= pPort
->pSocket
;
2278 // Get the transmit length and status
2280 LengthInBytes
= pPacket
->Op
.Tcp6Tx
.TxData
.DataLength
;
2281 pSocket
->TxOobBytes
-= LengthInBytes
;
2282 Status
= pIo
->Token
.Tcp6Tx
.CompletionToken
.Status
;
2285 // Complete the transmit operation
2287 EslSocketTxComplete ( pIo
,
2291 &pSocket
->pTxOobPacketListHead
,
2292 &pSocket
->pTxOobPacketListTail
,
2293 &pPort
->pTxOobActive
,
2294 &pPort
->pTxOobFree
);
2300 Verify the adapter's IP address
2302 This support routine is called by EslSocketBindTest.
2304 @param [in] pPort Address of an ::ESL_PORT structure.
2305 @param [in] pConfigData Address of the configuration data
2307 @retval EFI_SUCCESS - The IP address is valid
2308 @retval EFI_NOT_STARTED - The IP address is invalid
2312 EslTcp6VerifyLocalIpAddress (
2313 IN ESL_PORT
* pPort
,
2314 IN EFI_TCP6_CONFIG_DATA
* pConfigData
2318 EFI_IP6_ADDRESS_INFO
* pAddressInfo
;
2320 EFI_TCP6_ACCESS_POINT
* pAccess
;
2321 EFI_IP6_CONFIG_INTERFACE_INFO
* pIpConfigData
;
2322 EFI_IP6_CONFIG_PROTOCOL
* pIpConfigProtocol
;
2323 ESL_SERVICE
* pService
;
2329 // Use break instead of goto
2331 pIpConfigData
= NULL
;
2334 // Determine if the IP address is specified
2336 pAccess
= &pConfigData
->AccessPoint
;
2337 DEBUG (( DEBUG_BIND
,
2338 "Requested IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
2339 pAccess
->StationAddress
.Addr
[0],
2340 pAccess
->StationAddress
.Addr
[1],
2341 pAccess
->StationAddress
.Addr
[2],
2342 pAccess
->StationAddress
.Addr
[3],
2343 pAccess
->StationAddress
.Addr
[4],
2344 pAccess
->StationAddress
.Addr
[5],
2345 pAccess
->StationAddress
.Addr
[6],
2346 pAccess
->StationAddress
.Addr
[7],
2347 pAccess
->StationAddress
.Addr
[8],
2348 pAccess
->StationAddress
.Addr
[9],
2349 pAccess
->StationAddress
.Addr
[10],
2350 pAccess
->StationAddress
.Addr
[11],
2351 pAccess
->StationAddress
.Addr
[12],
2352 pAccess
->StationAddress
.Addr
[13],
2353 pAccess
->StationAddress
.Addr
[14],
2354 pAccess
->StationAddress
.Addr
[15]));
2355 if (( 0 == pAccess
->StationAddress
.Addr
[ 0 ])
2356 && ( 0 == pAccess
->StationAddress
.Addr
[ 1 ])
2357 && ( 0 == pAccess
->StationAddress
.Addr
[ 2 ])
2358 && ( 0 == pAccess
->StationAddress
.Addr
[ 3 ])
2359 && ( 0 == pAccess
->StationAddress
.Addr
[ 4 ])
2360 && ( 0 == pAccess
->StationAddress
.Addr
[ 5 ])
2361 && ( 0 == pAccess
->StationAddress
.Addr
[ 6 ])
2362 && ( 0 == pAccess
->StationAddress
.Addr
[ 7 ])
2363 && ( 0 == pAccess
->StationAddress
.Addr
[ 8 ])
2364 && ( 0 == pAccess
->StationAddress
.Addr
[ 9 ])
2365 && ( 0 == pAccess
->StationAddress
.Addr
[ 10 ])
2366 && ( 0 == pAccess
->StationAddress
.Addr
[ 11 ])
2367 && ( 0 == pAccess
->StationAddress
.Addr
[ 12 ])
2368 && ( 0 == pAccess
->StationAddress
.Addr
[ 13 ])
2369 && ( 0 == pAccess
->StationAddress
.Addr
[ 14 ])
2370 && ( 0 == pAccess
->StationAddress
.Addr
[ 15 ]))
2372 Status
= EFI_SUCCESS
;
2377 // Open the configuration protocol
2379 pService
= pPort
->pService
;
2380 Status
= gBS
->OpenProtocol ( pService
->Controller
,
2381 &gEfiIp6ConfigProtocolGuid
,
2382 (VOID
**)&pIpConfigProtocol
,
2385 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
2386 if ( EFI_ERROR ( Status
)) {
2387 DEBUG (( DEBUG_ERROR
,
2388 "ERROR - IP Configuration Protocol not available, Status: %r\r\n",
2394 // Get the IP configuration data size
2397 Status
= pIpConfigProtocol
->GetData ( pIpConfigProtocol
,
2398 Ip6ConfigDataTypeInterfaceInfo
,
2401 if ( EFI_BUFFER_TOO_SMALL
!= Status
) {
2402 DEBUG (( DEBUG_ERROR
,
2403 "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",
2409 // Allocate the configuration data buffer
2411 pIpConfigData
= AllocatePool ( DataSize
);
2412 if ( NULL
== pIpConfigData
) {
2413 DEBUG (( DEBUG_ERROR
,
2414 "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));
2415 Status
= EFI_OUT_OF_RESOURCES
;
2420 // Get the IP configuration
2422 Status
= pIpConfigProtocol
->GetData ( pIpConfigProtocol
,
2423 Ip6ConfigDataTypeInterfaceInfo
,
2426 if ( EFI_ERROR ( Status
)) {
2427 DEBUG (( DEBUG_ERROR
,
2428 "ERROR - Failed to return IP Configuration data, Status: %r\r\n",
2434 // Display the current configuration
2436 DEBUG (( DEBUG_BIND
,
2437 "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
2438 pIpConfigData
->HwAddress
.Addr
[ 0 ],
2439 pIpConfigData
->HwAddress
.Addr
[ 1 ],
2440 pIpConfigData
->HwAddress
.Addr
[ 2 ],
2441 pIpConfigData
->HwAddress
.Addr
[ 3 ],
2442 pIpConfigData
->HwAddress
.Addr
[ 4 ],
2443 pIpConfigData
->HwAddress
.Addr
[ 5 ],
2444 pIpConfigData
->HwAddress
.Addr
[ 6 ],
2445 pIpConfigData
->HwAddress
.Addr
[ 7 ],
2446 pIpConfigData
->HwAddress
.Addr
[ 8 ],
2447 pIpConfigData
->HwAddress
.Addr
[ 9 ],
2448 pIpConfigData
->HwAddress
.Addr
[ 10 ],
2449 pIpConfigData
->HwAddress
.Addr
[ 11 ],
2450 pIpConfigData
->HwAddress
.Addr
[ 12 ],
2451 pIpConfigData
->HwAddress
.Addr
[ 13 ],
2452 pIpConfigData
->HwAddress
.Addr
[ 14 ],
2453 pIpConfigData
->HwAddress
.Addr
[ 15 ]));
2456 // Validate the hardware address
2458 Status
= EFI_SUCCESS
;
2459 if (( 16 == pIpConfigData
->HwAddressSize
)
2460 && ( pAccess
->StationAddress
.Addr
[ 0 ] == pIpConfigData
->HwAddress
.Addr
[ 0 ])
2461 && ( pAccess
->StationAddress
.Addr
[ 1 ] == pIpConfigData
->HwAddress
.Addr
[ 1 ])
2462 && ( pAccess
->StationAddress
.Addr
[ 2 ] == pIpConfigData
->HwAddress
.Addr
[ 2 ])
2463 && ( pAccess
->StationAddress
.Addr
[ 3 ] == pIpConfigData
->HwAddress
.Addr
[ 3 ])
2464 && ( pAccess
->StationAddress
.Addr
[ 4 ] == pIpConfigData
->HwAddress
.Addr
[ 4 ])
2465 && ( pAccess
->StationAddress
.Addr
[ 5 ] == pIpConfigData
->HwAddress
.Addr
[ 5 ])
2466 && ( pAccess
->StationAddress
.Addr
[ 6 ] == pIpConfigData
->HwAddress
.Addr
[ 6 ])
2467 && ( pAccess
->StationAddress
.Addr
[ 7 ] == pIpConfigData
->HwAddress
.Addr
[ 7 ])
2468 && ( pAccess
->StationAddress
.Addr
[ 8 ] == pIpConfigData
->HwAddress
.Addr
[ 8 ])
2469 && ( pAccess
->StationAddress
.Addr
[ 9 ] == pIpConfigData
->HwAddress
.Addr
[ 9 ])
2470 && ( pAccess
->StationAddress
.Addr
[ 10 ] == pIpConfigData
->HwAddress
.Addr
[ 10 ])
2471 && ( pAccess
->StationAddress
.Addr
[ 11 ] == pIpConfigData
->HwAddress
.Addr
[ 11 ])
2472 && ( pAccess
->StationAddress
.Addr
[ 12 ] == pIpConfigData
->HwAddress
.Addr
[ 12 ])
2473 && ( pAccess
->StationAddress
.Addr
[ 13 ] == pIpConfigData
->HwAddress
.Addr
[ 13 ])
2474 && ( pAccess
->StationAddress
.Addr
[ 14 ] == pIpConfigData
->HwAddress
.Addr
[ 14 ])
2475 && ( pAccess
->StationAddress
.Addr
[ 15 ] == pIpConfigData
->HwAddress
.Addr
[ 15 ])) {
2480 // Walk the list of other IP addresses assigned to this adapter
2482 for ( AddressCount
= 0; pIpConfigData
->AddressInfoCount
> AddressCount
; AddressCount
+= 1 ) {
2483 pAddressInfo
= &pIpConfigData
->AddressInfo
[ AddressCount
];
2486 // Display the IP address
2488 DEBUG (( DEBUG_BIND
,
2489 "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
2490 pAddressInfo
->Address
.Addr
[ 0 ],
2491 pAddressInfo
->Address
.Addr
[ 1 ],
2492 pAddressInfo
->Address
.Addr
[ 2 ],
2493 pAddressInfo
->Address
.Addr
[ 3 ],
2494 pAddressInfo
->Address
.Addr
[ 4 ],
2495 pAddressInfo
->Address
.Addr
[ 5 ],
2496 pAddressInfo
->Address
.Addr
[ 6 ],
2497 pAddressInfo
->Address
.Addr
[ 7 ],
2498 pAddressInfo
->Address
.Addr
[ 8 ],
2499 pAddressInfo
->Address
.Addr
[ 9 ],
2500 pAddressInfo
->Address
.Addr
[ 10 ],
2501 pAddressInfo
->Address
.Addr
[ 11 ],
2502 pAddressInfo
->Address
.Addr
[ 12 ],
2503 pAddressInfo
->Address
.Addr
[ 13 ],
2504 pAddressInfo
->Address
.Addr
[ 14 ],
2505 pAddressInfo
->Address
.Addr
[ 15 ]));
2508 // Validate the IP address
2510 if (( pAccess
->StationAddress
.Addr
[ 0 ] == pAddressInfo
->Address
.Addr
[ 0 ])
2511 && ( pAccess
->StationAddress
.Addr
[ 1 ] == pAddressInfo
->Address
.Addr
[ 1 ])
2512 && ( pAccess
->StationAddress
.Addr
[ 2 ] == pAddressInfo
->Address
.Addr
[ 2 ])
2513 && ( pAccess
->StationAddress
.Addr
[ 3 ] == pAddressInfo
->Address
.Addr
[ 3 ])
2514 && ( pAccess
->StationAddress
.Addr
[ 4 ] == pAddressInfo
->Address
.Addr
[ 4 ])
2515 && ( pAccess
->StationAddress
.Addr
[ 5 ] == pAddressInfo
->Address
.Addr
[ 5 ])
2516 && ( pAccess
->StationAddress
.Addr
[ 6 ] == pAddressInfo
->Address
.Addr
[ 6 ])
2517 && ( pAccess
->StationAddress
.Addr
[ 7 ] == pAddressInfo
->Address
.Addr
[ 7 ])
2518 && ( pAccess
->StationAddress
.Addr
[ 8 ] == pAddressInfo
->Address
.Addr
[ 8 ])
2519 && ( pAccess
->StationAddress
.Addr
[ 9 ] == pAddressInfo
->Address
.Addr
[ 9 ])
2520 && ( pAccess
->StationAddress
.Addr
[ 10 ] == pAddressInfo
->Address
.Addr
[ 10 ])
2521 && ( pAccess
->StationAddress
.Addr
[ 11 ] == pAddressInfo
->Address
.Addr
[ 11 ])
2522 && ( pAccess
->StationAddress
.Addr
[ 12 ] == pAddressInfo
->Address
.Addr
[ 12 ])
2523 && ( pAccess
->StationAddress
.Addr
[ 13 ] == pAddressInfo
->Address
.Addr
[ 13 ])
2524 && ( pAccess
->StationAddress
.Addr
[ 14 ] == pAddressInfo
->Address
.Addr
[ 14 ])
2525 && ( pAccess
->StationAddress
.Addr
[ 15 ] == pAddressInfo
->Address
.Addr
[ 15 ])) {
2529 if ( pIpConfigData
->AddressInfoCount
> AddressCount
) {
2534 // The IP address did not match
2536 Status
= EFI_NOT_STARTED
;
2541 // Free the buffer if necessary
2543 if ( NULL
!= pIpConfigData
) {
2544 FreePool ( pIpConfigData
);
2548 // Return the IP address status
2550 DBG_EXIT_STATUS ( Status
);
2556 Interface between the socket layer and the network specific
2557 code that supports SOCK_STREAM and SOCK_SEQPACKET sockets
2560 CONST ESL_PROTOCOL_API cEslTcp6Api
= {
2563 OFFSET_OF ( ESL_PORT
, Context
.Tcp6
.ConfigData
),
2564 OFFSET_OF ( ESL_LAYER
, pTcp6List
),
2565 sizeof ( struct sockaddr_in6
),
2566 sizeof ( struct sockaddr_in6
),
2568 sizeof (((ESL_PACKET
*)0 )->Op
.Tcp6Rx
),
2569 OFFSET_OF ( ESL_PACKET
, Op
.Tcp6Rx
.Buffer
) - OFFSET_OF ( ESL_PACKET
, Op
),
2570 OFFSET_OF ( ESL_IO_MGMT
, Token
.Tcp6Rx
.Packet
.RxData
),
2575 EslTcp6ConnectStart
,
2576 EslTcp6SocketIsConfigured
,
2577 EslTcp6LocalAddressGet
,
2578 EslTcp6LocalAddressSet
,
2583 EslTcp6PortAllocate
,
2588 EslTcp6RemoteAddressGet
,
2589 EslTcp6RemoteAddressSet
,
2594 EslTcp6TxOobComplete
,
2595 (PFN_API_VERIFY_LOCAL_IP_ADDRESS
)EslTcp6VerifyLocalIpAddress