2 Implement the IP4 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.
19 Get the local socket address
21 This routine returns the IPv4 address associated with the local
24 This routine is called by ::EslSocketGetLocalAddress to determine the
25 network address for the SOCK_RAW socket.
27 @param [in] pPort Address of an ::ESL_PORT structure.
29 @param [out] pAddress Network address to receive the local system address
33 EslIp4LocalAddressGet (
35 OUT
struct sockaddr
* pAddress
38 struct sockaddr_in
* pLocalAddress
;
39 ESL_IP4_CONTEXT
* pIp4
;
44 // Return the local address
46 pIp4
= &pPort
->Context
.Ip4
;
47 pLocalAddress
= (struct sockaddr_in
*)pAddress
;
48 pLocalAddress
->sin_family
= AF_INET
;
49 CopyMem ( &pLocalAddress
->sin_addr
,
50 &pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0],
51 sizeof ( pLocalAddress
->sin_addr
));
58 Set the local port address.
60 This routine sets the local port address.
62 This support routine is called by ::EslSocketPortAllocate.
64 @param [in] pPort Address of an ESL_PORT structure
65 @param [in] pSockAddr Address of a sockaddr structure that contains the
66 connection point on the local machine. An IPv4 address
67 of INADDR_ANY specifies that the connection is made to
68 all of the network stacks on the platform. Specifying a
69 specific IPv4 address restricts the connection to the
70 network stack supporting that address. Specifying zero
71 for the port causes the network layer to assign a port
72 number from the dynamic range. Specifying a specific
73 port number causes the network layer to use that port.
75 @param [in] bBindTest TRUE = run bind testing
77 @retval EFI_SUCCESS The operation was successful
81 EslIp4LocalAddressSet (
83 IN CONST
struct sockaddr
* pSockAddr
,
87 EFI_IP4_CONFIG_DATA
* pConfig
;
88 CONST
struct sockaddr_in
* pIpAddress
;
89 CONST UINT8
* pIpv4Address
;
95 // Validate the address
97 pIpAddress
= (struct sockaddr_in
*)pSockAddr
;
98 if ( INADDR_BROADCAST
== pIpAddress
->sin_addr
.s_addr
) {
100 // The local address must not be the broadcast address
102 Status
= EFI_INVALID_PARAMETER
;
103 pPort
->pSocket
->errno
= EADDRNOTAVAIL
;
106 Status
= EFI_SUCCESS
;
109 // Set the local address
111 pIpAddress
= (struct sockaddr_in
*)pSockAddr
;
112 pIpv4Address
= (UINT8
*)&pIpAddress
->sin_addr
.s_addr
;
113 pConfig
= &pPort
->Context
.Ip4
.ModeData
.ConfigData
;
114 pConfig
->StationAddress
.Addr
[0] = pIpv4Address
[0];
115 pConfig
->StationAddress
.Addr
[1] = pIpv4Address
[1];
116 pConfig
->StationAddress
.Addr
[2] = pIpv4Address
[2];
117 pConfig
->StationAddress
.Addr
[3] = pIpv4Address
[3];
120 // Determine if the default address is used
122 pConfig
->UseDefaultAddress
= (BOOLEAN
)( 0 == pIpAddress
->sin_addr
.s_addr
);
125 // Display the local address
128 "0x%08x: Port, Local IP4 Address: %d.%d.%d.%d\r\n",
130 pConfig
->StationAddress
.Addr
[0],
131 pConfig
->StationAddress
.Addr
[1],
132 pConfig
->StationAddress
.Addr
[2],
133 pConfig
->StationAddress
.Addr
[3]));
136 // Set the subnet mask
138 if ( pConfig
->UseDefaultAddress
) {
139 pConfig
->SubnetMask
.Addr
[0] = 0;
140 pConfig
->SubnetMask
.Addr
[1] = 0;
141 pConfig
->SubnetMask
.Addr
[2] = 0;
142 pConfig
->SubnetMask
.Addr
[3] = 0;
145 pConfig
->SubnetMask
.Addr
[0] = 0xff;
146 pConfig
->SubnetMask
.Addr
[1] = ( 128 <= pConfig
->StationAddress
.Addr
[0]) ? 0xff : 0;
147 pConfig
->SubnetMask
.Addr
[2] = ( 192 <= pConfig
->StationAddress
.Addr
[0]) ? 0xff : 0;
148 pConfig
->SubnetMask
.Addr
[3] = ( 224 <= pConfig
->StationAddress
.Addr
[0]) ? 0xff : 0;
153 // Return the operation status
155 DBG_EXIT_STATUS ( Status
);
163 This routine handles the IPv4 level options.
165 The ::EslSocketOptionGet routine calls this routine to retrieve
166 the IPv4 options one at a time by name.
168 @param [in] pSocket Address of an ::ESL_SOCKET structure
169 @param [in] OptionName Name of the option
170 @param [out] ppOptionData Buffer to receive address of option value
171 @param [out] pOptionLength Buffer to receive the option length
173 @retval EFI_SUCCESS - Socket data successfully received
178 IN ESL_SOCKET
* pSocket
,
180 OUT CONST
void ** __restrict ppOptionData
,
181 OUT socklen_t
* __restrict pOptionLength
192 Status
= EFI_SUCCESS
;
195 // Attempt to get the option
197 switch ( OptionName
) {
200 // Option not supported
202 pSocket
->errno
= ENOPROTOOPT
;
203 Status
= EFI_INVALID_PARAMETER
;
207 *ppOptionData
= (void *)&pSocket
->bIncludeHeader
;
208 *pOptionLength
= sizeof ( pSocket
->bIncludeHeader
);
213 // Return the operation status
215 DBG_EXIT_STATUS ( Status
);
223 This routine handles the IPv4 level options.
225 The ::EslSocketOptionSet routine calls this routine to adjust
226 the IPv4 options one at a time by name.
228 @param [in] pSocket Address of an ::ESL_SOCKET structure
229 @param [in] OptionName Name of the option
230 @param [in] pOptionValue Buffer containing the option value
231 @param [in] OptionLength Length of the buffer in bytes
233 @retval EFI_SUCCESS - Option successfully set
238 IN ESL_SOCKET
* pSocket
,
240 IN CONST
void * pOptionValue
,
241 IN socklen_t OptionLength
245 socklen_t LengthInBytes
;
255 Status
= EFI_SUCCESS
;
258 // Determine if the option protocol matches
262 switch ( OptionName
) {
265 // Protocol level not supported
267 DEBUG (( DEBUG_INFO
| DEBUG_OPTION
, "ERROR - Invalid protocol option\r\n" ));
268 pSocket
->errno
= ENOTSUP
;
269 Status
= EFI_UNSUPPORTED
;
275 // Validate the option length
277 if ( sizeof ( UINT32
) == OptionLength
) {
279 // Restrict the input to TRUE or FALSE
282 if ( 0 == *(UINT32
*)pOptionValue
) {
285 pOptionValue
= &bTrueFalse
;
288 // Set the option value
290 pOptionData
= (UINT8
*)&pSocket
->bIncludeHeader
;
291 LengthInBytes
= sizeof ( pSocket
->bIncludeHeader
);
297 // Return the operation status
299 DBG_EXIT_STATUS ( Status
);
305 Free a receive packet
307 This routine performs the network specific operations necessary
308 to free a receive packet.
310 This routine is called by ::EslSocketPortCloseTxDone to free a
313 @param [in] pPacket Address of an ::ESL_PACKET structure.
314 @param [in, out] pRxBytes Address of the count of RX bytes
319 IN ESL_PACKET
* pPacket
,
320 IN OUT
size_t * pRxBytes
323 EFI_IP4_RECEIVE_DATA
* pRxData
;
327 // Account for the receive bytes
329 pRxData
= pPacket
->Op
.Ip4Rx
.pRxData
;
330 *pRxBytes
-= pRxData
->HeaderLength
+ pRxData
->DataLength
;
333 // Disconnect the buffer from the packet
335 pPacket
->Op
.Ip4Rx
.pRxData
= NULL
;
338 // Return the buffer to the IP4 driver
340 gBS
->SignalEvent ( pRxData
->RecycleSignal
);
346 Initialize the network specific portions of an ::ESL_PORT structure.
348 This routine initializes the network specific portions of an
349 ::ESL_PORT structure for use by the socket.
351 This support routine is called by ::EslSocketPortAllocate
352 to connect the socket with the underlying network adapter
353 running the IPv4 protocol.
355 @param [in] pPort Address of an ESL_PORT structure
356 @param [in] DebugFlags Flags for debug messages
358 @retval EFI_SUCCESS - Socket successfully created
367 EFI_IP4_CONFIG_DATA
* pConfig
;
368 ESL_SOCKET
* pSocket
;
374 // Initialize the port
376 pSocket
= pPort
->pSocket
;
377 pSocket
->TxPacketOffset
= OFFSET_OF ( ESL_PACKET
, Op
.Ip4Tx
.TxData
);
378 pSocket
->TxTokenEventOffset
= OFFSET_OF ( ESL_IO_MGMT
, Token
.Ip4Tx
.Event
);
379 pSocket
->TxTokenOffset
= OFFSET_OF ( EFI_IP4_COMPLETION_TOKEN
, Packet
.TxData
);
382 // Save the cancel, receive and transmit addresses
384 pPort
->pfnConfigure
= (PFN_NET_CONFIGURE
)pPort
->pProtocol
.IPv4
->Configure
;
385 pPort
->pfnRxCancel
= (PFN_NET_IO_START
)pPort
->pProtocol
.IPv4
->Cancel
;
386 pPort
->pfnRxPoll
= (PFN_NET_POLL
)pPort
->pProtocol
.IPv4
->Poll
;
387 pPort
->pfnRxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.IPv4
->Receive
;
388 pPort
->pfnTxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.IPv4
->Transmit
;
391 // Set the configuration flags
393 pConfig
= &pPort
->Context
.Ip4
.ModeData
.ConfigData
;
394 pConfig
->AcceptIcmpErrors
= FALSE
;
395 pConfig
->AcceptBroadcast
= FALSE
;
396 pConfig
->AcceptPromiscuous
= FALSE
;
397 pConfig
->TypeOfService
= 0;
398 pConfig
->TimeToLive
= 255;
399 pConfig
->DoNotFragment
= FALSE
;
400 pConfig
->RawData
= FALSE
;
401 pConfig
->ReceiveTimeout
= 0;
402 pConfig
->TransmitTimeout
= 0;
405 // Set the default protocol
407 pConfig
->DefaultProtocol
= (UINT8
)pSocket
->Protocol
;
408 pConfig
->AcceptAnyProtocol
= (BOOLEAN
)( 0 == pConfig
->DefaultProtocol
);
409 Status
= EFI_SUCCESS
;
412 // Return the operation status
414 DBG_EXIT_STATUS ( Status
);
420 Receive data from a network connection.
422 This routine attempts to return buffered data to the caller. The
423 data is removed from the urgent queue if the message flag MSG_OOB
424 is specified, otherwise data is removed from the normal queue.
425 See the \ref ReceiveEngine section.
427 This routine is called by ::EslSocketReceive to handle the network
428 specific receive operation to support SOCK_RAW sockets.
430 @param [in] pPort Address of an ::ESL_PORT structure.
432 @param [in] pPacket Address of an ::ESL_PACKET structure.
434 @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
436 @param [in] BufferLength Length of the the buffer
438 @param [in] pBuffer Address of a buffer to receive the data.
440 @param [in] pDataLength Number of received data bytes in the buffer.
442 @param [out] pAddress Network address to receive the remote system address
444 @param [out] pSkipBytes Address to receive the number of bytes skipped
446 @return Returns the address of the next free byte in the buffer.
452 IN ESL_PACKET
* pPacket
,
453 IN BOOLEAN
* pbConsumePacket
,
454 IN
size_t BufferLength
,
456 OUT
size_t * pDataLength
,
457 OUT
struct sockaddr
* pAddress
,
458 OUT
size_t * pSkipBytes
463 size_t LengthInBytes
;
464 struct sockaddr_in
* pRemoteAddress
;
465 EFI_IP4_RECEIVE_DATA
* pRxData
;
470 // Return the remote system address if requested
472 pRxData
= pPacket
->Op
.Ip4Rx
.pRxData
;
473 if ( NULL
!= pAddress
) {
475 // Build the remote address
478 "Getting packet remote address: %d.%d.%d.%d\r\n",
479 pRxData
->Header
->SourceAddress
.Addr
[0],
480 pRxData
->Header
->SourceAddress
.Addr
[1],
481 pRxData
->Header
->SourceAddress
.Addr
[2],
482 pRxData
->Header
->SourceAddress
.Addr
[3]));
483 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
484 CopyMem ( &pRemoteAddress
->sin_addr
,
485 &pRxData
->Header
->SourceAddress
.Addr
[0],
486 sizeof ( pRemoteAddress
->sin_addr
));
490 // Copy the IP header
492 HeaderBytes
= pRxData
->HeaderLength
;
493 if ( HeaderBytes
> BufferLength
) {
494 HeaderBytes
= BufferLength
;
497 "0x%08x --> 0x%08x: Copy header 0x%08x bytes\r\n",
501 CopyMem ( pBuffer
, pRxData
->Header
, HeaderBytes
);
502 pBuffer
+= HeaderBytes
;
503 LengthInBytes
= HeaderBytes
;
506 // Copy the received data
508 if ( 0 < ( BufferLength
- LengthInBytes
)) {
509 pBuffer
= EslSocketCopyFragmentedBuffer ( pRxData
->FragmentCount
,
510 &pRxData
->FragmentTable
[0],
511 BufferLength
- LengthInBytes
,
514 LengthInBytes
+= DataBytes
;
518 // Determine if the data is being read
520 if ( *pbConsumePacket
) {
522 // Display for the bytes consumed
525 "0x%08x: Port account for 0x%08x bytes\r\n",
530 // Account for any discarded data
532 *pSkipBytes
= pRxData
->HeaderLength
+ pRxData
->DataLength
- LengthInBytes
;
536 // Return the data length and the buffer address
538 *pDataLength
= LengthInBytes
;
539 DBG_EXIT_HEX ( pBuffer
);
545 Get the remote socket address
547 This routine returns the address of the remote connection point
548 associated with the SOCK_RAW socket.
550 This routine is called by ::EslSocketGetPeerAddress to detemine
551 the IPv4 address associated with the network adapter.
553 @param [in] pPort Address of an ::ESL_PORT structure.
555 @param [out] pAddress Network address to receive the remote system address
559 EslIp4RemoteAddressGet (
561 OUT
struct sockaddr
* pAddress
564 struct sockaddr_in
* pRemoteAddress
;
565 ESL_IP4_CONTEXT
* pIp4
;
570 // Return the remote address
572 pIp4
= &pPort
->Context
.Ip4
;
573 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
574 pRemoteAddress
->sin_family
= AF_INET
;
575 CopyMem ( &pRemoteAddress
->sin_addr
,
576 &pIp4
->DestinationAddress
.Addr
[0],
577 sizeof ( pRemoteAddress
->sin_addr
));
584 Set the remote address
586 This routine sets the remote address in the port.
588 This routine is called by ::EslSocketConnect to specify the
589 remote network address.
591 @param [in] pPort Address of an ::ESL_PORT structure.
593 @param [in] pSockAddr Network address of the remote system.
595 @param [in] SockAddrLength Length in bytes of the network address.
597 @retval EFI_SUCCESS The operation was successful
601 EslIp4RemoteAddressSet (
603 IN CONST
struct sockaddr
* pSockAddr
,
604 IN socklen_t SockAddrLength
607 ESL_IP4_CONTEXT
* pIp4
;
608 CONST
struct sockaddr_in
* pRemoteAddress
;
614 // Set the remote address
616 pIp4
= &pPort
->Context
.Ip4
;
617 pRemoteAddress
= (struct sockaddr_in
*)pSockAddr
;
618 pIp4
->DestinationAddress
.Addr
[0] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
);
619 pIp4
->DestinationAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
620 pIp4
->DestinationAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
621 pIp4
->DestinationAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
622 pPort
->pSocket
->bAddressSet
= TRUE
;
623 Status
= EFI_SUCCESS
;
626 // Return the operation status
628 DBG_EXIT_STATUS ( Status
);
634 Process the receive completion
636 This routine keeps the IPv4 driver's buffer and queues it in
637 in FIFO order to the data queue. The IP4 driver's buffer will
638 be returned by either ::EslIp4Receive or ::EslSocketPortCloseTxDone.
639 See the \ref ReceiveEngine section.
641 This routine is called by the IPv4 driver when data is
644 @param [in] Event The receive completion event
646 @param [in] pIo The address of an ::ESL_IO_MGMT structure
655 size_t LengthInBytes
;
656 ESL_PACKET
* pPacket
;
657 EFI_IP4_RECEIVE_DATA
* pRxData
;
663 // Get the operation status.
665 Status
= pIo
->Token
.Ip4Rx
.Status
;
668 // Get the packet length
670 pRxData
= pIo
->Token
.Ip4Rx
.Packet
.RxData
;
671 LengthInBytes
= pRxData
->HeaderLength
+ pRxData
->DataLength
;
674 // +--------------------+ +----------------------+
675 // | ESL_IO_MGMT | | Data Buffer |
676 // | | | (Driver owned) |
677 // | +---------------+ +----------------------+
680 // | | | +----------------------+
681 // | | RxData --> | EFI_IP4_RECEIVE_DATA |
682 // +----+---------------+ | (Driver owned) |
683 // +----------------------+
684 // +--------------------+ ^
687 // | +---------------+ .
688 // | | pRxData --> NULL .......
689 // +----+---------------+
692 // Save the data in the packet
694 pPacket
= pIo
->pPacket
;
695 pPacket
->Op
.Ip4Rx
.pRxData
= pRxData
;
698 // Complete this request
700 EslSocketRxComplete ( pIo
, Status
, LengthInBytes
, FALSE
);
706 Determine if the socket is configured.
708 This routine uses the flag ESL_SOCKET::bConfigured to determine
709 if the network layer's configuration routine has been called.
710 This routine calls the ::EslSocketBind and configuration routines
711 if they were not already called. After the port is configured,
712 the \ref ReceiveEngine is started.
714 This routine is called by EslSocketIsConfigured to verify
715 that the socket is configured.
717 @param [in] pSocket Address of an ::ESL_SOCKET structure
719 @retval EFI_SUCCESS - The port is connected
720 @retval EFI_NOT_STARTED - The port is not connected
724 EslIp4SocketIsConfigured (
725 IN ESL_SOCKET
* pSocket
730 ESL_PORT
* pNextPort
;
731 ESL_IP4_CONTEXT
* pIp4
;
732 EFI_IP4_PROTOCOL
* pIp4Protocol
;
734 struct sockaddr_in LocalAddress
;
741 Status
= EFI_SUCCESS
;
744 // Configure the port if necessary
746 if ( !pSocket
->bConfigured
) {
748 // Fill in the port list if necessary
750 pSocket
->errno
= ENETDOWN
;
751 if ( NULL
== pSocket
->pPortList
) {
752 LocalAddress
.sin_len
= sizeof ( LocalAddress
);
753 LocalAddress
.sin_family
= AF_INET
;
754 LocalAddress
.sin_addr
.s_addr
= 0;
755 LocalAddress
.sin_port
= 0;
756 Status
= EslSocketBind ( &pSocket
->SocketProtocol
,
757 (struct sockaddr
*)&LocalAddress
,
758 LocalAddress
.sin_len
,
763 // Walk the port list
765 pPort
= pSocket
->pPortList
;
766 while ( NULL
!= pPort
) {
768 // Update the raw setting
770 pIp4
= &pPort
->Context
.Ip4
;
771 if ( pSocket
->bIncludeHeader
) {
773 // IP header will be included with the data on transmit
775 pIp4
->ModeData
.ConfigData
.RawData
= TRUE
;
779 // Attempt to configure the port
781 pNextPort
= pPort
->pLinkSocket
;
782 pIp4Protocol
= pPort
->pProtocol
.IPv4
;
784 "0x%08x: pPort Configuring for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
786 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0],
787 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[1],
788 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[2],
789 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[3],
790 pIp4
->DestinationAddress
.Addr
[0],
791 pIp4
->DestinationAddress
.Addr
[1],
792 pIp4
->DestinationAddress
.Addr
[2],
793 pIp4
->DestinationAddress
.Addr
[3]));
794 Status
= pIp4Protocol
->Configure ( pIp4Protocol
,
795 &pIp4
->ModeData
.ConfigData
);
796 if ( !EFI_ERROR ( Status
)) {
798 // Update the configuration data
800 Status
= pIp4Protocol
->GetModeData ( pIp4Protocol
,
805 if ( EFI_ERROR ( Status
)) {
806 if ( !pSocket
->bConfigured
) {
807 DEBUG (( DEBUG_LISTEN
,
808 "ERROR - Failed to configure the Ip4 port, Status: %r\r\n",
811 case EFI_ACCESS_DENIED
:
812 pSocket
->errno
= EACCES
;
816 case EFI_DEVICE_ERROR
:
817 pSocket
->errno
= EIO
;
820 case EFI_INVALID_PARAMETER
:
821 pSocket
->errno
= EADDRNOTAVAIL
;
825 pSocket
->errno
= EAFNOSUPPORT
;
828 case EFI_OUT_OF_RESOURCES
:
829 pSocket
->errno
= ENOBUFS
;
832 case EFI_UNSUPPORTED
:
833 pSocket
->errno
= EOPNOTSUPP
;
840 "0x%08x: pPort Configured for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
842 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0],
843 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[1],
844 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[2],
845 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[3],
846 pIp4
->DestinationAddress
.Addr
[0],
847 pIp4
->DestinationAddress
.Addr
[1],
848 pIp4
->DestinationAddress
.Addr
[2],
849 pIp4
->DestinationAddress
.Addr
[3]));
851 "Subnet Mask: %d.%d.%d.%d\r\n",
852 pIp4
->ModeData
.ConfigData
.SubnetMask
.Addr
[0],
853 pIp4
->ModeData
.ConfigData
.SubnetMask
.Addr
[1],
854 pIp4
->ModeData
.ConfigData
.SubnetMask
.Addr
[2],
855 pIp4
->ModeData
.ConfigData
.SubnetMask
.Addr
[3]));
857 "Route Count: %d\r\n",
858 pIp4
->ModeData
.RouteCount
));
859 for ( Index
= 0; pIp4
->ModeData
.RouteCount
> Index
; Index
++ ) {
861 DEBUG (( DEBUG_TX
, "Route Table:\r\n" ));
864 "%5d: %d.%d.%d.%d, %d.%d.%d.%d ==> %d.%d.%d.%d\r\n",
866 pIp4
->ModeData
.RouteTable
[Index
].SubnetAddress
.Addr
[0],
867 pIp4
->ModeData
.RouteTable
[Index
].SubnetAddress
.Addr
[1],
868 pIp4
->ModeData
.RouteTable
[Index
].SubnetAddress
.Addr
[2],
869 pIp4
->ModeData
.RouteTable
[Index
].SubnetAddress
.Addr
[3],
870 pIp4
->ModeData
.RouteTable
[Index
].SubnetMask
.Addr
[0],
871 pIp4
->ModeData
.RouteTable
[Index
].SubnetMask
.Addr
[1],
872 pIp4
->ModeData
.RouteTable
[Index
].SubnetMask
.Addr
[2],
873 pIp4
->ModeData
.RouteTable
[Index
].SubnetMask
.Addr
[3],
874 pIp4
->ModeData
.RouteTable
[Index
].GatewayAddress
.Addr
[0],
875 pIp4
->ModeData
.RouteTable
[Index
].GatewayAddress
.Addr
[1],
876 pIp4
->ModeData
.RouteTable
[Index
].GatewayAddress
.Addr
[2],
877 pIp4
->ModeData
.RouteTable
[Index
].GatewayAddress
.Addr
[3]));
879 pPort
->bConfigured
= TRUE
;
880 pSocket
->bConfigured
= TRUE
;
883 // Start the first read on the port
885 EslSocketRxStart ( pPort
);
888 // The socket is connected
890 pSocket
->State
= SOCKET_STATE_CONNECTED
;
902 // Determine the socket configuration status
904 Status
= pSocket
->bConfigured
? EFI_SUCCESS
: EFI_NOT_STARTED
;
907 // Return the port connected state.
909 DBG_EXIT_STATUS ( Status
);
915 Buffer data for transmission over a network connection.
917 This routine buffers data for the transmit engine in the normal
918 data queue. When the \ref TransmitEngine has resources, this
919 routine will start the transmission of the next buffer on the
922 This routine is called by ::EslSocketTransmit to buffer
923 data for transmission. The data is copied into a local buffer
924 freeing the application buffer for reuse upon return. When
925 necessary, this routine starts the transmit engine that
926 performs the data transmission on the network connection. The
927 transmit engine transmits the data a packet at a time over the
930 Transmission errors are returned during the next transmission or
931 during the close operation. Only buffering errors are returned
932 during the current transmission attempt.
934 @param [in] pSocket Address of an ::ESL_SOCKET structure
936 @param [in] Flags Message control flags
938 @param [in] BufferLength Length of the the buffer
940 @param [in] pBuffer Address of a buffer to receive the data.
942 @param [in] pDataLength Number of received data bytes in the buffer.
944 @param [in] pAddress Network address of the remote system address
946 @param [in] AddressLength Length of the remote network address structure
948 @retval EFI_SUCCESS - Socket data successfully buffered
953 IN ESL_SOCKET
* pSocket
,
955 IN
size_t BufferLength
,
956 IN CONST UINT8
* pBuffer
,
957 OUT
size_t * pDataLength
,
958 IN
const struct sockaddr
* pAddress
,
959 IN socklen_t AddressLength
962 ESL_PACKET
* pPacket
;
963 ESL_PACKET
* pPreviousPacket
;
965 const struct sockaddr_in
* pRemoteAddress
;
966 ESL_IP4_CONTEXT
* pIp4
;
968 ESL_IP4_TX_DATA
* pTxData
;
977 Status
= EFI_UNSUPPORTED
;
978 pSocket
->errno
= ENOTCONN
;
982 // Verify that the socket is connected
984 if ( SOCKET_STATE_CONNECTED
== pSocket
->State
) {
986 // Verify that there is enough room to buffer another
987 // transmit operation
989 pTxBytes
= &pSocket
->TxBytes
;
990 if ( pSocket
->MaxTxBuf
> *pTxBytes
) {
994 pPort
= pSocket
->pPortList
;
995 while ( NULL
!= pPort
) {
997 // Determine the queue head
999 pIp4
= &pPort
->Context
.Ip4
;
1002 // Attempt to allocate the packet
1004 Status
= EslSocketPacketAllocate ( &pPacket
,
1005 sizeof ( pPacket
->Op
.Ip4Tx
)
1006 - sizeof ( pPacket
->Op
.Ip4Tx
.Buffer
)
1010 if ( !EFI_ERROR ( Status
)) {
1012 // Initialize the transmit operation
1014 pTxData
= &pPacket
->Op
.Ip4Tx
;
1015 pTxData
->TxData
.DestinationAddress
.Addr
[0] = pIp4
->DestinationAddress
.Addr
[0];
1016 pTxData
->TxData
.DestinationAddress
.Addr
[1] = pIp4
->DestinationAddress
.Addr
[1];
1017 pTxData
->TxData
.DestinationAddress
.Addr
[2] = pIp4
->DestinationAddress
.Addr
[2];
1018 pTxData
->TxData
.DestinationAddress
.Addr
[3] = pIp4
->DestinationAddress
.Addr
[3];
1019 pTxData
->TxData
.OverrideData
= NULL
;
1020 pTxData
->TxData
.OptionsLength
= 0;
1021 pTxData
->TxData
.OptionsBuffer
= NULL
;
1022 pTxData
->TxData
.TotalDataLength
= (UINT32
) BufferLength
;
1023 pTxData
->TxData
.FragmentCount
= 1;
1024 pTxData
->TxData
.FragmentTable
[0].FragmentLength
= (UINT32
) BufferLength
;
1025 pTxData
->TxData
.FragmentTable
[0].FragmentBuffer
= &pPacket
->Op
.Ip4Tx
.Buffer
[0];
1028 // Set the remote system address if necessary
1030 if ( NULL
!= pAddress
) {
1031 pRemoteAddress
= (const struct sockaddr_in
*)pAddress
;
1032 pTxData
->Override
.SourceAddress
.Addr
[0] = pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0];
1033 pTxData
->Override
.SourceAddress
.Addr
[1] = pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[1];
1034 pTxData
->Override
.SourceAddress
.Addr
[2] = pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[2];
1035 pTxData
->Override
.SourceAddress
.Addr
[3] = pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[3];
1036 pTxData
->TxData
.DestinationAddress
.Addr
[0] = (UINT8
)pRemoteAddress
->sin_addr
.s_addr
;
1037 pTxData
->TxData
.DestinationAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
1038 pTxData
->TxData
.DestinationAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
1039 pTxData
->TxData
.DestinationAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
1040 pTxData
->Override
.GatewayAddress
.Addr
[0] = 0;
1041 pTxData
->Override
.GatewayAddress
.Addr
[1] = 0;
1042 pTxData
->Override
.GatewayAddress
.Addr
[2] = 0;
1043 pTxData
->Override
.GatewayAddress
.Addr
[3] = 0;
1044 pTxData
->Override
.Protocol
= (UINT8
)pSocket
->Protocol
;
1045 pTxData
->Override
.TypeOfService
= 0;
1046 pTxData
->Override
.TimeToLive
= 255;
1047 pTxData
->Override
.DoNotFragment
= FALSE
;
1050 // Use the remote system address when sending this packet
1052 pTxData
->TxData
.OverrideData
= &pTxData
->Override
;
1056 // Copy the data into the buffer
1058 CopyMem ( &pPacket
->Op
.Ip4Tx
.Buffer
[0],
1063 // Synchronize with the socket layer
1065 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
1068 // Display the request
1071 "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
1074 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0],
1075 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[1],
1076 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[2],
1077 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[3],
1078 pTxData
->TxData
.DestinationAddress
.Addr
[0],
1079 pTxData
->TxData
.DestinationAddress
.Addr
[1],
1080 pTxData
->TxData
.DestinationAddress
.Addr
[2],
1081 pTxData
->TxData
.DestinationAddress
.Addr
[3]));
1084 // Queue the data for transmission
1086 pPacket
->pNext
= NULL
;
1087 pPreviousPacket
= pSocket
->pTxPacketListTail
;
1088 if ( NULL
== pPreviousPacket
) {
1089 pSocket
->pTxPacketListHead
= pPacket
;
1092 pPreviousPacket
->pNext
= pPacket
;
1094 pSocket
->pTxPacketListTail
= pPacket
;
1096 "0x%08x: Packet on transmit list\r\n",
1100 // Account for the buffered data
1102 *pTxBytes
+= BufferLength
;
1103 *pDataLength
= BufferLength
;
1106 // Start the transmit engine if it is idle
1108 if ( NULL
!= pPort
->pTxFree
) {
1109 EslSocketTxStart ( pPort
,
1110 &pSocket
->pTxPacketListHead
,
1111 &pSocket
->pTxPacketListTail
,
1116 // Ignore any transmit error
1118 if ( EFI_ERROR ( pSocket
->TxError
)) {
1120 "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",
1123 pSocket
->TxError
));
1125 pSocket
->TxError
= EFI_SUCCESS
;
1129 // Release the socket layer synchronization
1131 RESTORE_TPL ( TplPrevious
);
1135 // Packet allocation failed
1137 pSocket
->errno
= ENOMEM
;
1142 // Set the next port
1144 pPort
= pPort
->pLinkSocket
;
1149 // Not enough buffer space available
1151 pSocket
->errno
= EAGAIN
;
1152 Status
= EFI_NOT_READY
;
1157 // Return the operation status
1159 DBG_EXIT_STATUS ( Status
);
1165 Process the transmit completion
1167 This routine use ::EslSocketTxComplete to perform the transmit
1168 completion processing for data packets.
1170 This routine is called by the IPv4 network layer when a data
1171 transmit request completes.
1173 @param [in] Event The normal transmit completion event
1175 @param [in] pIo The address of an ::ESL_IO_MGMT structure
1181 IN ESL_IO_MGMT
* pIo
1184 UINT32 LengthInBytes
;
1186 ESL_PACKET
* pPacket
;
1187 ESL_SOCKET
* pSocket
;
1193 // Locate the active transmit packet
1195 pPacket
= pIo
->pPacket
;
1197 pSocket
= pPort
->pSocket
;
1200 // Get the transmit length and status
1202 LengthInBytes
= pPacket
->Op
.Ip4Tx
.TxData
.TotalDataLength
;
1203 pSocket
->TxBytes
-= LengthInBytes
;
1204 Status
= pIo
->Token
.Ip4Tx
.Status
;
1207 // Ignore the transmit error
1209 if ( EFI_ERROR ( Status
)) {
1211 "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",
1215 Status
= EFI_SUCCESS
;
1219 // Complete the transmit operation
1221 EslSocketTxComplete ( pIo
,
1225 &pSocket
->pTxPacketListHead
,
1226 &pSocket
->pTxPacketListTail
,
1234 Verify the adapter's IP address
1236 This support routine is called by EslSocketBindTest.
1238 @param [in] pPort Address of an ::ESL_PORT structure.
1239 @param [in] pConfigData Address of the configuration data
1241 @retval EFI_SUCCESS - The IP address is valid
1242 @retval EFI_NOT_STARTED - The IP address is invalid
1246 EslIp4VerifyLocalIpAddress (
1247 IN ESL_PORT
* pPort
,
1248 IN EFI_IP4_CONFIG_DATA
* pConfigData
1252 EFI_IP4_IPCONFIG_DATA
* pIpConfigData
;
1253 EFI_IP4_CONFIG_PROTOCOL
* pIpConfigProtocol
;
1254 ESL_SERVICE
* pService
;
1260 // Use break instead of goto
1262 pIpConfigData
= NULL
;
1265 // Determine if the IP address is specified
1267 DEBUG (( DEBUG_BIND
,
1268 "UseDefaultAddress: %s\r\n",
1269 pConfigData
->UseDefaultAddress
? L
"TRUE" : L
"FALSE" ));
1270 DEBUG (( DEBUG_BIND
,
1271 "Requested IP address: %d.%d.%d.%d\r\n",
1272 pConfigData
->StationAddress
.Addr
[ 0 ],
1273 pConfigData
->StationAddress
.Addr
[ 1 ],
1274 pConfigData
->StationAddress
.Addr
[ 2 ],
1275 pConfigData
->StationAddress
.Addr
[ 3 ]));
1276 if ( pConfigData
->UseDefaultAddress
1277 || (( 0 == pConfigData
->StationAddress
.Addr
[ 0 ])
1278 && ( 0 == pConfigData
->StationAddress
.Addr
[ 1 ])
1279 && ( 0 == pConfigData
->StationAddress
.Addr
[ 2 ])
1280 && ( 0 == pConfigData
->StationAddress
.Addr
[ 3 ])))
1282 Status
= EFI_SUCCESS
;
1287 // Open the configuration protocol
1289 pService
= pPort
->pService
;
1290 Status
= gBS
->OpenProtocol ( pService
->Controller
,
1291 &gEfiIp4ConfigProtocolGuid
,
1292 (VOID
**)&pIpConfigProtocol
,
1295 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
1296 if ( EFI_ERROR ( Status
)) {
1297 DEBUG (( DEBUG_ERROR
,
1298 "ERROR - IP Configuration Protocol not available, Status: %r\r\n",
1304 // Get the IP configuration data size
1307 Status
= pIpConfigProtocol
->GetData ( pIpConfigProtocol
,
1310 if ( EFI_BUFFER_TOO_SMALL
!= Status
) {
1311 DEBUG (( DEBUG_ERROR
,
1312 "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",
1318 // Allocate the configuration data buffer
1320 pIpConfigData
= AllocatePool ( DataSize
);
1321 if ( NULL
== pIpConfigData
) {
1322 DEBUG (( DEBUG_ERROR
,
1323 "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));
1324 Status
= EFI_OUT_OF_RESOURCES
;
1329 // Get the IP configuration
1331 Status
= pIpConfigProtocol
->GetData ( pIpConfigProtocol
,
1334 if ( EFI_ERROR ( Status
)) {
1335 DEBUG (( DEBUG_ERROR
,
1336 "ERROR - Failed to return IP Configuration data, Status: %r\r\n",
1342 // Display the current configuration
1344 DEBUG (( DEBUG_BIND
,
1345 "Actual adapter IP address: %d.%d.%d.%d\r\n",
1346 pIpConfigData
->StationAddress
.Addr
[ 0 ],
1347 pIpConfigData
->StationAddress
.Addr
[ 1 ],
1348 pIpConfigData
->StationAddress
.Addr
[ 2 ],
1349 pIpConfigData
->StationAddress
.Addr
[ 3 ]));
1352 // Assume the port is not configured
1354 Status
= EFI_SUCCESS
;
1355 if (( pConfigData
->StationAddress
.Addr
[ 0 ] == pIpConfigData
->StationAddress
.Addr
[ 0 ])
1356 && ( pConfigData
->StationAddress
.Addr
[ 1 ] == pIpConfigData
->StationAddress
.Addr
[ 1 ])
1357 && ( pConfigData
->StationAddress
.Addr
[ 2 ] == pIpConfigData
->StationAddress
.Addr
[ 2 ])
1358 && ( pConfigData
->StationAddress
.Addr
[ 3 ] == pIpConfigData
->StationAddress
.Addr
[ 3 ])) {
1363 // The IP address did not match
1365 Status
= EFI_NOT_STARTED
;
1370 // Free the buffer if necessary
1372 if ( NULL
!= pIpConfigData
) {
1373 FreePool ( pIpConfigData
);
1377 // Return the IP address status
1379 DBG_EXIT_STATUS ( Status
);
1385 Interface between the socket layer and the network specific
1386 code that supports SOCK_RAW sockets over IPv4.
1388 CONST ESL_PROTOCOL_API cEslIp4Api
= {
1391 OFFSET_OF ( ESL_PORT
, Context
.Ip4
.ModeData
.ConfigData
),
1392 OFFSET_OF ( ESL_LAYER
, pIp4List
),
1393 OFFSET_OF ( struct sockaddr_in
, sin_zero
),
1394 sizeof ( struct sockaddr_in
),
1396 sizeof (((ESL_PACKET
*)0 )->Op
.Ip4Rx
),
1397 sizeof (((ESL_PACKET
*)0 )->Op
.Ip4Rx
),
1398 OFFSET_OF ( ESL_IO_MGMT
, Token
.Ip4Rx
.Packet
.RxData
),
1402 NULL
, // ConnectPoll
1403 NULL
, // ConnectStart
1404 EslIp4SocketIsConfigured
,
1405 EslIp4LocalAddressGet
,
1406 EslIp4LocalAddressSet
,
1413 NULL
, // PortCloseOp
1416 EslIp4RemoteAddressGet
,
1417 EslIp4RemoteAddressSet
,
1422 NULL
, // TxOobComplete
1423 (PFN_API_VERIFY_LOCAL_IP_ADDRESS
)EslIp4VerifyLocalIpAddress