2 Implement the IP4 driver support for the socket layer.
4 Copyright (c) 2011 - 2015, 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.
16 /** Get the local socket address.
18 This routine returns the IPv4 address associated with the local
21 This routine is called by ::EslSocketGetLocalAddress to determine the
22 network address for the SOCK_RAW socket.
24 @param [in] pPort Address of an ::ESL_PORT structure.
25 @param [out] pAddress Network address to receive the local system address
28 EslIp4LocalAddressGet (
30 OUT
struct sockaddr
* pAddress
33 struct sockaddr_in
* pLocalAddress
;
34 ESL_IP4_CONTEXT
* pIp4
;
38 // Return the local address
39 pIp4
= &pPort
->Context
.Ip4
;
40 pLocalAddress
= (struct sockaddr_in
*)pAddress
;
41 pLocalAddress
->sin_family
= AF_INET
;
42 CopyMem ( &pLocalAddress
->sin_addr
,
43 &pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0],
44 sizeof ( pLocalAddress
->sin_addr
));
50 /** Set the local port address.
52 This routine sets the local port address.
54 This support routine is called by ::EslSocketPortAllocate.
56 @param [in] pPort Address of an ESL_PORT structure
57 @param [in] pSockAddr Address of a sockaddr structure that contains the
58 connection point on the local machine. An IPv4 address
59 of INADDR_ANY specifies that the connection is made to
60 all of the network stacks on the platform. Specifying a
61 specific IPv4 address restricts the connection to the
62 network stack supporting that address. Specifying zero
63 for the port causes the network layer to assign a port
64 number from the dynamic range. Specifying a specific
65 port number causes the network layer to use that port.
67 @param [in] bBindTest TRUE = run bind testing
69 @retval EFI_SUCCESS The operation was successful
72 EslIp4LocalAddressSet (
74 IN CONST
struct sockaddr
* pSockAddr
,
78 EFI_IP4_CONFIG_DATA
* pConfig
;
79 CONST
struct sockaddr_in
* pIpAddress
;
80 CONST UINT8
* pIpv4Address
;
85 // Validate the address
86 pIpAddress
= (struct sockaddr_in
*)pSockAddr
;
87 if ( INADDR_BROADCAST
== pIpAddress
->sin_addr
.s_addr
) {
88 // The local address must not be the broadcast address
89 Status
= EFI_INVALID_PARAMETER
;
90 pPort
->pSocket
->errno
= EADDRNOTAVAIL
;
95 // Set the local address
96 pIpAddress
= (struct sockaddr_in
*)pSockAddr
;
97 pIpv4Address
= (UINT8
*)&pIpAddress
->sin_addr
.s_addr
;
98 pConfig
= &pPort
->Context
.Ip4
.ModeData
.ConfigData
;
99 pConfig
->StationAddress
.Addr
[0] = pIpv4Address
[0];
100 pConfig
->StationAddress
.Addr
[1] = pIpv4Address
[1];
101 pConfig
->StationAddress
.Addr
[2] = pIpv4Address
[2];
102 pConfig
->StationAddress
.Addr
[3] = pIpv4Address
[3];
104 // Determine if the default address is used
105 pConfig
->UseDefaultAddress
= (BOOLEAN
)( 0 == pIpAddress
->sin_addr
.s_addr
);
107 // Display the local address
109 "0x%08x: Port, Local IP4 Address: %d.%d.%d.%d\r\n",
111 pConfig
->StationAddress
.Addr
[0],
112 pConfig
->StationAddress
.Addr
[1],
113 pConfig
->StationAddress
.Addr
[2],
114 pConfig
->StationAddress
.Addr
[3]));
116 // Set the subnet mask
117 if ( pConfig
->UseDefaultAddress
) {
118 pConfig
->SubnetMask
.Addr
[0] = 0;
119 pConfig
->SubnetMask
.Addr
[1] = 0;
120 pConfig
->SubnetMask
.Addr
[2] = 0;
121 pConfig
->SubnetMask
.Addr
[3] = 0;
124 pConfig
->SubnetMask
.Addr
[0] = 0xff;
125 pConfig
->SubnetMask
.Addr
[1] = ( 128 <= pConfig
->StationAddress
.Addr
[0]) ? 0xff : 0;
126 pConfig
->SubnetMask
.Addr
[2] = ( 192 <= pConfig
->StationAddress
.Addr
[0]) ? 0xff : 0;
127 pConfig
->SubnetMask
.Addr
[3] = ( 224 <= pConfig
->StationAddress
.Addr
[0]) ? 0xff : 0;
130 // Return the operation status
131 DBG_EXIT_STATUS ( Status
);
136 /** Get the option value.
138 This routine handles the IPv4 level options.
140 The ::EslSocketOptionGet routine calls this routine to retrieve
141 the IPv4 options one at a time by name.
143 @param [in] pSocket Address of an ::ESL_SOCKET structure
144 @param [in] OptionName Name of the option
145 @param [out] ppOptionData Buffer to receive address of option value
146 @param [out] pOptionLength Buffer to receive the option length
148 @retval EFI_SUCCESS - Socket data successfully received
152 IN ESL_SOCKET
* pSocket
,
154 OUT CONST
void ** __restrict ppOptionData
,
155 OUT socklen_t
* __restrict pOptionLength
164 Status
= EFI_SUCCESS
;
166 // Attempt to get the option
167 switch ( OptionName
) {
169 // Option not supported
170 pSocket
->errno
= ENOPROTOOPT
;
171 Status
= EFI_INVALID_PARAMETER
;
175 *ppOptionData
= (void *)&pSocket
->bIncludeHeader
;
176 *pOptionLength
= sizeof ( pSocket
->bIncludeHeader
);
179 // Return the operation status
180 DBG_EXIT_STATUS ( Status
);
185 /** Set the option value.
187 This routine handles the IPv4 level options.
189 The ::EslSocketOptionSet routine calls this routine to adjust
190 the IPv4 options one at a time by name.
192 @param [in] pSocket Address of an ::ESL_SOCKET structure
193 @param [in] OptionName Name of the option
194 @param [in] pOptionValue Buffer containing the option value
195 @param [in] OptionLength Length of the buffer in bytes
197 @retval EFI_SUCCESS - Option successfully set
201 IN ESL_SOCKET
* pSocket
,
203 IN CONST
void * pOptionValue
,
204 IN socklen_t OptionLength
208 //socklen_t LengthInBytes;
209 //UINT8 * pOptionData;
216 Status
= EFI_SUCCESS
;
218 // Determine if the option protocol matches
220 //pOptionData = NULL;
221 switch ( OptionName
) {
223 // Protocol level not supported
224 DEBUG (( DEBUG_INFO
| DEBUG_OPTION
, "ERROR - Invalid protocol option\r\n" ));
225 pSocket
->errno
= ENOTSUP
;
226 Status
= EFI_UNSUPPORTED
;
231 // Validate the option length
232 if ( sizeof ( UINT32
) == OptionLength
) {
233 // Restrict the input to TRUE or FALSE
235 if ( 0 == *(UINT32
*)pOptionValue
) {
238 pOptionValue
= &bTrueFalse
;
240 // Set the option value
241 //pOptionData = (UINT8 *)&pSocket->bIncludeHeader;
242 //LengthInBytes = sizeof ( pSocket->bIncludeHeader );
246 // Return the operation status
247 DBG_EXIT_STATUS ( Status
);
253 Free a receive packet
255 This routine performs the network specific operations necessary
256 to free a receive packet.
258 This routine is called by ::EslSocketPortCloseTxDone to free a
261 @param [in] pPacket Address of an ::ESL_PACKET structure.
262 @param [in, out] pRxBytes Address of the count of RX bytes
267 IN ESL_PACKET
* pPacket
,
268 IN OUT
size_t * pRxBytes
271 EFI_IP4_RECEIVE_DATA
* pRxData
;
275 // Account for the receive bytes
277 pRxData
= pPacket
->Op
.Ip4Rx
.pRxData
;
278 *pRxBytes
-= pRxData
->HeaderLength
+ pRxData
->DataLength
;
281 // Disconnect the buffer from the packet
283 pPacket
->Op
.Ip4Rx
.pRxData
= NULL
;
286 // Return the buffer to the IP4 driver
288 gBS
->SignalEvent ( pRxData
->RecycleSignal
);
294 Initialize the network specific portions of an ::ESL_PORT structure.
296 This routine initializes the network specific portions of an
297 ::ESL_PORT structure for use by the socket.
299 This support routine is called by ::EslSocketPortAllocate
300 to connect the socket with the underlying network adapter
301 running the IPv4 protocol.
303 @param [in] pPort Address of an ESL_PORT structure
304 @param [in] DebugFlags Flags for debug messages
306 @retval EFI_SUCCESS - Socket successfully created
315 EFI_IP4_CONFIG_DATA
* pConfig
;
316 ESL_SOCKET
* pSocket
;
322 // Initialize the port
324 pSocket
= pPort
->pSocket
;
325 pSocket
->TxPacketOffset
= OFFSET_OF ( ESL_PACKET
, Op
.Ip4Tx
.TxData
);
326 pSocket
->TxTokenEventOffset
= OFFSET_OF ( ESL_IO_MGMT
, Token
.Ip4Tx
.Event
);
327 pSocket
->TxTokenOffset
= OFFSET_OF ( EFI_IP4_COMPLETION_TOKEN
, Packet
.TxData
);
330 // Save the cancel, receive and transmit addresses
332 pPort
->pfnConfigure
= (PFN_NET_CONFIGURE
)pPort
->pProtocol
.IPv4
->Configure
;
333 pPort
->pfnRxCancel
= (PFN_NET_IO_START
)pPort
->pProtocol
.IPv4
->Cancel
;
334 pPort
->pfnRxPoll
= (PFN_NET_POLL
)pPort
->pProtocol
.IPv4
->Poll
;
335 pPort
->pfnRxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.IPv4
->Receive
;
336 pPort
->pfnTxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.IPv4
->Transmit
;
339 // Set the configuration flags
341 pConfig
= &pPort
->Context
.Ip4
.ModeData
.ConfigData
;
342 pConfig
->AcceptIcmpErrors
= FALSE
;
343 pConfig
->AcceptBroadcast
= FALSE
;
344 pConfig
->AcceptPromiscuous
= FALSE
;
345 pConfig
->TypeOfService
= 0;
346 pConfig
->TimeToLive
= 255;
347 pConfig
->DoNotFragment
= FALSE
;
348 pConfig
->RawData
= FALSE
;
349 pConfig
->ReceiveTimeout
= 0;
350 pConfig
->TransmitTimeout
= 0;
353 // Set the default protocol
355 pConfig
->DefaultProtocol
= (UINT8
)pSocket
->Protocol
;
356 pConfig
->AcceptAnyProtocol
= (BOOLEAN
)( 0 == pConfig
->DefaultProtocol
);
357 Status
= EFI_SUCCESS
;
360 // Return the operation status
362 DBG_EXIT_STATUS ( Status
);
368 Receive data from a network connection.
370 This routine attempts to return buffered data to the caller. The
371 data is removed from the urgent queue if the message flag MSG_OOB
372 is specified, otherwise data is removed from the normal queue.
373 See the \ref ReceiveEngine section.
375 This routine is called by ::EslSocketReceive to handle the network
376 specific receive operation to support SOCK_RAW sockets.
378 @param [in] pPort Address of an ::ESL_PORT structure.
380 @param [in] pPacket Address of an ::ESL_PACKET structure.
382 @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
384 @param [in] BufferLength Length of the the buffer
386 @param [in] pBuffer Address of a buffer to receive the data.
388 @param [in] pDataLength Number of received data bytes in the buffer.
390 @param [out] pAddress Network address to receive the remote system address
392 @param [out] pSkipBytes Address to receive the number of bytes skipped
394 @return Returns the address of the next free byte in the buffer.
400 IN ESL_PACKET
* pPacket
,
401 IN BOOLEAN
* pbConsumePacket
,
402 IN
size_t BufferLength
,
404 OUT
size_t * pDataLength
,
405 OUT
struct sockaddr
* pAddress
,
406 OUT
size_t * pSkipBytes
411 size_t LengthInBytes
;
412 struct sockaddr_in
* pRemoteAddress
;
413 EFI_IP4_RECEIVE_DATA
* pRxData
;
418 // Return the remote system address if requested
420 pRxData
= pPacket
->Op
.Ip4Rx
.pRxData
;
421 if ( NULL
!= pAddress
) {
423 // Build the remote address
426 "Getting packet remote address: %d.%d.%d.%d\r\n",
427 pRxData
->Header
->SourceAddress
.Addr
[0],
428 pRxData
->Header
->SourceAddress
.Addr
[1],
429 pRxData
->Header
->SourceAddress
.Addr
[2],
430 pRxData
->Header
->SourceAddress
.Addr
[3]));
431 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
432 CopyMem ( &pRemoteAddress
->sin_addr
,
433 &pRxData
->Header
->SourceAddress
.Addr
[0],
434 sizeof ( pRemoteAddress
->sin_addr
));
438 // Copy the IP header
440 HeaderBytes
= pRxData
->HeaderLength
;
441 if ( HeaderBytes
> BufferLength
) {
442 HeaderBytes
= BufferLength
;
445 "0x%08x --> 0x%08x: Copy header 0x%08x bytes\r\n",
449 CopyMem ( pBuffer
, pRxData
->Header
, HeaderBytes
);
450 pBuffer
+= HeaderBytes
;
451 LengthInBytes
= HeaderBytes
;
454 // Copy the received data
456 if ( 0 < ( BufferLength
- LengthInBytes
)) {
457 pBuffer
= EslSocketCopyFragmentedBuffer ( pRxData
->FragmentCount
,
458 &pRxData
->FragmentTable
[0],
459 BufferLength
- LengthInBytes
,
462 LengthInBytes
+= DataBytes
;
466 // Determine if the data is being read
468 if ( *pbConsumePacket
) {
470 // Display for the bytes consumed
473 "0x%08x: Port account for 0x%08x bytes\r\n",
478 // Account for any discarded data
480 *pSkipBytes
= pRxData
->HeaderLength
+ pRxData
->DataLength
- LengthInBytes
;
484 // Return the data length and the buffer address
486 *pDataLength
= LengthInBytes
;
487 DBG_EXIT_HEX ( pBuffer
);
493 Get the remote socket address
495 This routine returns the address of the remote connection point
496 associated with the SOCK_RAW socket.
498 This routine is called by ::EslSocketGetPeerAddress to detemine
499 the IPv4 address associated with the network adapter.
501 @param [in] pPort Address of an ::ESL_PORT structure.
503 @param [out] pAddress Network address to receive the remote system address
507 EslIp4RemoteAddressGet (
509 OUT
struct sockaddr
* pAddress
512 struct sockaddr_in
* pRemoteAddress
;
513 ESL_IP4_CONTEXT
* pIp4
;
518 // Return the remote address
520 pIp4
= &pPort
->Context
.Ip4
;
521 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
522 pRemoteAddress
->sin_family
= AF_INET
;
523 CopyMem ( &pRemoteAddress
->sin_addr
,
524 &pIp4
->DestinationAddress
.Addr
[0],
525 sizeof ( pRemoteAddress
->sin_addr
));
532 Set the remote address
534 This routine sets the remote address in the port.
536 This routine is called by ::EslSocketConnect to specify the
537 remote network address.
539 @param [in] pPort Address of an ::ESL_PORT structure.
541 @param [in] pSockAddr Network address of the remote system.
543 @param [in] SockAddrLength Length in bytes of the network address.
545 @retval EFI_SUCCESS The operation was successful
549 EslIp4RemoteAddressSet (
551 IN CONST
struct sockaddr
* pSockAddr
,
552 IN socklen_t SockAddrLength
555 ESL_IP4_CONTEXT
* pIp4
;
556 CONST
struct sockaddr_in
* pRemoteAddress
;
562 // Set the remote address
564 pIp4
= &pPort
->Context
.Ip4
;
565 pRemoteAddress
= (struct sockaddr_in
*)pSockAddr
;
566 pIp4
->DestinationAddress
.Addr
[0] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
);
567 pIp4
->DestinationAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
568 pIp4
->DestinationAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
569 pIp4
->DestinationAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
570 pPort
->pSocket
->bAddressSet
= TRUE
;
571 Status
= EFI_SUCCESS
;
574 // Return the operation status
576 DBG_EXIT_STATUS ( Status
);
582 Process the receive completion
584 This routine keeps the IPv4 driver's buffer and queues it in
585 in FIFO order to the data queue. The IP4 driver's buffer will
586 be returned by either ::EslIp4Receive or ::EslSocketPortCloseTxDone.
587 See the \ref ReceiveEngine section.
589 This routine is called by the IPv4 driver when data is
592 @param [in] Event The receive completion event
594 @param [in] pIo The address of an ::ESL_IO_MGMT structure
603 size_t LengthInBytes
;
604 ESL_PACKET
* pPacket
;
605 EFI_IP4_RECEIVE_DATA
* pRxData
;
611 // Get the operation status.
613 Status
= pIo
->Token
.Ip4Rx
.Status
;
616 // Get the packet length
618 pRxData
= pIo
->Token
.Ip4Rx
.Packet
.RxData
;
619 LengthInBytes
= pRxData
->HeaderLength
+ pRxData
->DataLength
;
622 // +--------------------+ +----------------------+
623 // | ESL_IO_MGMT | | Data Buffer |
624 // | | | (Driver owned) |
625 // | +---------------+ +----------------------+
628 // | | | +----------------------+
629 // | | RxData --> | EFI_IP4_RECEIVE_DATA |
630 // +----+---------------+ | (Driver owned) |
631 // +----------------------+
632 // +--------------------+ ^
635 // | +---------------+ .
636 // | | pRxData --> NULL .......
637 // +----+---------------+
640 // Save the data in the packet
642 pPacket
= pIo
->pPacket
;
643 pPacket
->Op
.Ip4Rx
.pRxData
= pRxData
;
646 // Complete this request
648 EslSocketRxComplete ( pIo
, Status
, LengthInBytes
, FALSE
);
654 Determine if the socket is configured.
656 This routine uses the flag ESL_SOCKET::bConfigured to determine
657 if the network layer's configuration routine has been called.
658 This routine calls the ::EslSocketBind and configuration routines
659 if they were not already called. After the port is configured,
660 the \ref ReceiveEngine is started.
662 This routine is called by EslSocketIsConfigured to verify
663 that the socket is configured.
665 @param [in] pSocket Address of an ::ESL_SOCKET structure
667 @retval EFI_SUCCESS - The port is connected
668 @retval EFI_NOT_STARTED - The port is not connected
672 EslIp4SocketIsConfigured (
673 IN ESL_SOCKET
* pSocket
678 ESL_PORT
* pNextPort
;
679 ESL_IP4_CONTEXT
* pIp4
;
680 EFI_IP4_PROTOCOL
* pIp4Protocol
;
682 struct sockaddr_in LocalAddress
;
689 Status
= EFI_SUCCESS
;
692 // Configure the port if necessary
694 if ( !pSocket
->bConfigured
) {
696 // Fill in the port list if necessary
698 pSocket
->errno
= ENETDOWN
;
699 if ( NULL
== pSocket
->pPortList
) {
700 LocalAddress
.sin_len
= sizeof ( LocalAddress
);
701 LocalAddress
.sin_family
= AF_INET
;
702 LocalAddress
.sin_addr
.s_addr
= 0;
703 LocalAddress
.sin_port
= 0;
704 Status
= EslSocketBind ( &pSocket
->SocketProtocol
,
705 (struct sockaddr
*)&LocalAddress
,
706 LocalAddress
.sin_len
,
711 // Walk the port list
713 pPort
= pSocket
->pPortList
;
714 while ( NULL
!= pPort
) {
716 // Update the raw setting
718 pIp4
= &pPort
->Context
.Ip4
;
719 if ( pSocket
->bIncludeHeader
) {
721 // IP header will be included with the data on transmit
723 pIp4
->ModeData
.ConfigData
.RawData
= TRUE
;
727 // Attempt to configure the port
729 pNextPort
= pPort
->pLinkSocket
;
730 pIp4Protocol
= pPort
->pProtocol
.IPv4
;
732 "0x%08x: pPort Configuring for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
734 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0],
735 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[1],
736 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[2],
737 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[3],
738 pIp4
->DestinationAddress
.Addr
[0],
739 pIp4
->DestinationAddress
.Addr
[1],
740 pIp4
->DestinationAddress
.Addr
[2],
741 pIp4
->DestinationAddress
.Addr
[3]));
742 Status
= pIp4Protocol
->Configure ( pIp4Protocol
,
743 &pIp4
->ModeData
.ConfigData
);
744 if ( !EFI_ERROR ( Status
)) {
746 // Update the configuration data
748 Status
= pIp4Protocol
->GetModeData ( pIp4Protocol
,
753 if ( EFI_ERROR ( Status
)) {
754 if ( !pSocket
->bConfigured
) {
755 DEBUG (( DEBUG_LISTEN
,
756 "ERROR - Failed to configure the Ip4 port, Status: %r\r\n",
759 case EFI_ACCESS_DENIED
:
760 pSocket
->errno
= EACCES
;
764 case EFI_DEVICE_ERROR
:
765 pSocket
->errno
= EIO
;
768 case EFI_INVALID_PARAMETER
:
769 pSocket
->errno
= EADDRNOTAVAIL
;
773 pSocket
->errno
= EAFNOSUPPORT
;
776 case EFI_OUT_OF_RESOURCES
:
777 pSocket
->errno
= ENOBUFS
;
780 case EFI_UNSUPPORTED
:
781 pSocket
->errno
= EOPNOTSUPP
;
788 "0x%08x: pPort Configured for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
790 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0],
791 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[1],
792 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[2],
793 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[3],
794 pIp4
->DestinationAddress
.Addr
[0],
795 pIp4
->DestinationAddress
.Addr
[1],
796 pIp4
->DestinationAddress
.Addr
[2],
797 pIp4
->DestinationAddress
.Addr
[3]));
799 "Subnet Mask: %d.%d.%d.%d\r\n",
800 pIp4
->ModeData
.ConfigData
.SubnetMask
.Addr
[0],
801 pIp4
->ModeData
.ConfigData
.SubnetMask
.Addr
[1],
802 pIp4
->ModeData
.ConfigData
.SubnetMask
.Addr
[2],
803 pIp4
->ModeData
.ConfigData
.SubnetMask
.Addr
[3]));
805 "Route Count: %d\r\n",
806 pIp4
->ModeData
.RouteCount
));
807 for ( Index
= 0; pIp4
->ModeData
.RouteCount
> Index
; Index
++ ) {
809 DEBUG (( DEBUG_TX
, "Route Table:\r\n" ));
812 "%5d: %d.%d.%d.%d, %d.%d.%d.%d ==> %d.%d.%d.%d\r\n",
814 pIp4
->ModeData
.RouteTable
[Index
].SubnetAddress
.Addr
[0],
815 pIp4
->ModeData
.RouteTable
[Index
].SubnetAddress
.Addr
[1],
816 pIp4
->ModeData
.RouteTable
[Index
].SubnetAddress
.Addr
[2],
817 pIp4
->ModeData
.RouteTable
[Index
].SubnetAddress
.Addr
[3],
818 pIp4
->ModeData
.RouteTable
[Index
].SubnetMask
.Addr
[0],
819 pIp4
->ModeData
.RouteTable
[Index
].SubnetMask
.Addr
[1],
820 pIp4
->ModeData
.RouteTable
[Index
].SubnetMask
.Addr
[2],
821 pIp4
->ModeData
.RouteTable
[Index
].SubnetMask
.Addr
[3],
822 pIp4
->ModeData
.RouteTable
[Index
].GatewayAddress
.Addr
[0],
823 pIp4
->ModeData
.RouteTable
[Index
].GatewayAddress
.Addr
[1],
824 pIp4
->ModeData
.RouteTable
[Index
].GatewayAddress
.Addr
[2],
825 pIp4
->ModeData
.RouteTable
[Index
].GatewayAddress
.Addr
[3]));
827 pPort
->bConfigured
= TRUE
;
828 pSocket
->bConfigured
= TRUE
;
831 // Start the first read on the port
833 EslSocketRxStart ( pPort
);
836 // The socket is connected
838 pSocket
->State
= SOCKET_STATE_CONNECTED
;
850 // Determine the socket configuration status
852 Status
= pSocket
->bConfigured
? EFI_SUCCESS
: EFI_NOT_STARTED
;
855 // Return the port connected state.
857 DBG_EXIT_STATUS ( Status
);
863 Buffer data for transmission over a network connection.
865 This routine buffers data for the transmit engine in the normal
866 data queue. When the \ref TransmitEngine has resources, this
867 routine will start the transmission of the next buffer on the
870 This routine is called by ::EslSocketTransmit to buffer
871 data for transmission. The data is copied into a local buffer
872 freeing the application buffer for reuse upon return. When
873 necessary, this routine starts the transmit engine that
874 performs the data transmission on the network connection. The
875 transmit engine transmits the data a packet at a time over the
878 Transmission errors are returned during the next transmission or
879 during the close operation. Only buffering errors are returned
880 during the current transmission attempt.
882 @param [in] pSocket Address of an ::ESL_SOCKET structure
884 @param [in] Flags Message control flags
886 @param [in] BufferLength Length of the the buffer
888 @param [in] pBuffer Address of a buffer to receive the data.
890 @param [in] pDataLength Number of received data bytes in the buffer.
892 @param [in] pAddress Network address of the remote system address
894 @param [in] AddressLength Length of the remote network address structure
896 @retval EFI_SUCCESS - Socket data successfully buffered
901 IN ESL_SOCKET
* pSocket
,
903 IN
size_t BufferLength
,
904 IN CONST UINT8
* pBuffer
,
905 OUT
size_t * pDataLength
,
906 IN
const struct sockaddr
* pAddress
,
907 IN socklen_t AddressLength
910 ESL_PACKET
* pPacket
;
911 ESL_PACKET
* pPreviousPacket
;
913 const struct sockaddr_in
* pRemoteAddress
;
914 ESL_IP4_CONTEXT
* pIp4
;
916 ESL_IP4_TX_DATA
* pTxData
;
925 Status
= EFI_UNSUPPORTED
;
926 pSocket
->errno
= ENOTCONN
;
930 // Verify that the socket is connected
932 if ( SOCKET_STATE_CONNECTED
== pSocket
->State
) {
934 // Verify that there is enough room to buffer another
935 // transmit operation
937 pTxBytes
= &pSocket
->TxBytes
;
938 if ( pSocket
->MaxTxBuf
> *pTxBytes
) {
942 pPort
= pSocket
->pPortList
;
943 while ( NULL
!= pPort
) {
945 // Determine the queue head
947 pIp4
= &pPort
->Context
.Ip4
;
950 // Attempt to allocate the packet
952 Status
= EslSocketPacketAllocate ( &pPacket
,
953 sizeof ( pPacket
->Op
.Ip4Tx
)
954 - sizeof ( pPacket
->Op
.Ip4Tx
.Buffer
)
958 if ( !EFI_ERROR ( Status
)) {
960 // Initialize the transmit operation
962 pTxData
= &pPacket
->Op
.Ip4Tx
;
963 pTxData
->TxData
.DestinationAddress
.Addr
[0] = pIp4
->DestinationAddress
.Addr
[0];
964 pTxData
->TxData
.DestinationAddress
.Addr
[1] = pIp4
->DestinationAddress
.Addr
[1];
965 pTxData
->TxData
.DestinationAddress
.Addr
[2] = pIp4
->DestinationAddress
.Addr
[2];
966 pTxData
->TxData
.DestinationAddress
.Addr
[3] = pIp4
->DestinationAddress
.Addr
[3];
967 pTxData
->TxData
.OverrideData
= NULL
;
968 pTxData
->TxData
.OptionsLength
= 0;
969 pTxData
->TxData
.OptionsBuffer
= NULL
;
970 pTxData
->TxData
.TotalDataLength
= (UINT32
) BufferLength
;
971 pTxData
->TxData
.FragmentCount
= 1;
972 pTxData
->TxData
.FragmentTable
[0].FragmentLength
= (UINT32
) BufferLength
;
973 pTxData
->TxData
.FragmentTable
[0].FragmentBuffer
= &pPacket
->Op
.Ip4Tx
.Buffer
[0];
976 // Set the remote system address if necessary
978 if ( NULL
!= pAddress
) {
979 pRemoteAddress
= (const struct sockaddr_in
*)pAddress
;
980 pTxData
->Override
.SourceAddress
.Addr
[0] = pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0];
981 pTxData
->Override
.SourceAddress
.Addr
[1] = pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[1];
982 pTxData
->Override
.SourceAddress
.Addr
[2] = pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[2];
983 pTxData
->Override
.SourceAddress
.Addr
[3] = pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[3];
984 pTxData
->TxData
.DestinationAddress
.Addr
[0] = (UINT8
)pRemoteAddress
->sin_addr
.s_addr
;
985 pTxData
->TxData
.DestinationAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
986 pTxData
->TxData
.DestinationAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
987 pTxData
->TxData
.DestinationAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
988 pTxData
->Override
.GatewayAddress
.Addr
[0] = 0;
989 pTxData
->Override
.GatewayAddress
.Addr
[1] = 0;
990 pTxData
->Override
.GatewayAddress
.Addr
[2] = 0;
991 pTxData
->Override
.GatewayAddress
.Addr
[3] = 0;
992 pTxData
->Override
.Protocol
= (UINT8
)pSocket
->Protocol
;
993 pTxData
->Override
.TypeOfService
= 0;
994 pTxData
->Override
.TimeToLive
= 255;
995 pTxData
->Override
.DoNotFragment
= FALSE
;
998 // Use the remote system address when sending this packet
1000 pTxData
->TxData
.OverrideData
= &pTxData
->Override
;
1004 // Copy the data into the buffer
1006 CopyMem ( &pPacket
->Op
.Ip4Tx
.Buffer
[0],
1011 // Synchronize with the socket layer
1013 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
1016 // Display the request
1019 "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
1022 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0],
1023 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[1],
1024 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[2],
1025 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[3],
1026 pTxData
->TxData
.DestinationAddress
.Addr
[0],
1027 pTxData
->TxData
.DestinationAddress
.Addr
[1],
1028 pTxData
->TxData
.DestinationAddress
.Addr
[2],
1029 pTxData
->TxData
.DestinationAddress
.Addr
[3]));
1032 // Queue the data for transmission
1034 pPacket
->pNext
= NULL
;
1035 pPreviousPacket
= pSocket
->pTxPacketListTail
;
1036 if ( NULL
== pPreviousPacket
) {
1037 pSocket
->pTxPacketListHead
= pPacket
;
1040 pPreviousPacket
->pNext
= pPacket
;
1042 pSocket
->pTxPacketListTail
= pPacket
;
1044 "0x%08x: Packet on transmit list\r\n",
1048 // Account for the buffered data
1050 *pTxBytes
+= BufferLength
;
1051 *pDataLength
= BufferLength
;
1054 // Start the transmit engine if it is idle
1056 if ( NULL
!= pPort
->pTxFree
) {
1057 EslSocketTxStart ( pPort
,
1058 &pSocket
->pTxPacketListHead
,
1059 &pSocket
->pTxPacketListTail
,
1064 // Ignore any transmit error
1066 if ( EFI_ERROR ( pSocket
->TxError
)) {
1068 "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",
1071 pSocket
->TxError
));
1073 pSocket
->TxError
= EFI_SUCCESS
;
1077 // Release the socket layer synchronization
1079 RESTORE_TPL ( TplPrevious
);
1083 // Packet allocation failed
1085 pSocket
->errno
= ENOMEM
;
1090 // Set the next port
1092 pPort
= pPort
->pLinkSocket
;
1097 // Not enough buffer space available
1099 pSocket
->errno
= EAGAIN
;
1100 Status
= EFI_NOT_READY
;
1105 // Return the operation status
1107 DBG_EXIT_STATUS ( Status
);
1113 Process the transmit completion
1115 This routine use ::EslSocketTxComplete to perform the transmit
1116 completion processing for data packets.
1118 This routine is called by the IPv4 network layer when a data
1119 transmit request completes.
1121 @param [in] Event The normal transmit completion event
1123 @param [in] pIo The address of an ::ESL_IO_MGMT structure
1129 IN ESL_IO_MGMT
* pIo
1132 UINT32 LengthInBytes
;
1134 ESL_PACKET
* pPacket
;
1135 ESL_SOCKET
* pSocket
;
1141 // Locate the active transmit packet
1143 pPacket
= pIo
->pPacket
;
1145 pSocket
= pPort
->pSocket
;
1148 // Get the transmit length and status
1150 LengthInBytes
= pPacket
->Op
.Ip4Tx
.TxData
.TotalDataLength
;
1151 pSocket
->TxBytes
-= LengthInBytes
;
1152 Status
= pIo
->Token
.Ip4Tx
.Status
;
1155 // Ignore the transmit error
1157 if ( EFI_ERROR ( Status
)) {
1159 "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",
1163 Status
= EFI_SUCCESS
;
1167 // Complete the transmit operation
1169 EslSocketTxComplete ( pIo
,
1173 &pSocket
->pTxPacketListHead
,
1174 &pSocket
->pTxPacketListTail
,
1182 Verify the adapter's IP address
1184 This support routine is called by EslSocketBindTest.
1186 @param [in] pPort Address of an ::ESL_PORT structure.
1187 @param [in] pConfigData Address of the configuration data
1189 @retval EFI_SUCCESS - The IP address is valid
1190 @retval EFI_NOT_STARTED - The IP address is invalid
1194 EslIp4VerifyLocalIpAddress (
1195 IN ESL_PORT
* pPort
,
1196 IN EFI_IP4_CONFIG_DATA
* pConfigData
1200 EFI_IP4_CONFIG2_INTERFACE_INFO
* pIfInfo
;
1201 EFI_IP4_CONFIG2_PROTOCOL
* pIpConfig2Protocol
;
1202 ESL_SERVICE
* pService
;
1208 // Use break instead of goto
1213 // Determine if the IP address is specified
1215 DEBUG (( DEBUG_BIND
,
1216 "UseDefaultAddress: %s\r\n",
1217 pConfigData
->UseDefaultAddress
? L
"TRUE" : L
"FALSE" ));
1218 DEBUG (( DEBUG_BIND
,
1219 "Requested IP address: %d.%d.%d.%d\r\n",
1220 pConfigData
->StationAddress
.Addr
[ 0 ],
1221 pConfigData
->StationAddress
.Addr
[ 1 ],
1222 pConfigData
->StationAddress
.Addr
[ 2 ],
1223 pConfigData
->StationAddress
.Addr
[ 3 ]));
1224 if ( pConfigData
->UseDefaultAddress
1225 || (( 0 == pConfigData
->StationAddress
.Addr
[ 0 ])
1226 && ( 0 == pConfigData
->StationAddress
.Addr
[ 1 ])
1227 && ( 0 == pConfigData
->StationAddress
.Addr
[ 2 ])
1228 && ( 0 == pConfigData
->StationAddress
.Addr
[ 3 ])))
1230 Status
= EFI_SUCCESS
;
1235 // Open the configuration protocol
1237 pService
= pPort
->pService
;
1238 Status
= gBS
->OpenProtocol (
1239 pService
->Controller
,
1240 &gEfiIp4Config2ProtocolGuid
,
1241 (VOID
**)&pIpConfig2Protocol
,
1244 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1246 if ( EFI_ERROR ( Status
)) {
1247 DEBUG (( DEBUG_ERROR
,
1248 "ERROR - IP Configuration Protocol not available, Status: %r\r\n",
1254 // Get the interface information size.
1257 Status
= pIpConfig2Protocol
->GetData (
1259 Ip4Config2DataTypeInterfaceInfo
,
1263 if ( EFI_BUFFER_TOO_SMALL
!= Status
) {
1264 DEBUG (( DEBUG_ERROR
,
1265 "ERROR - Failed to get the interface information size, Status: %r\r\n",
1271 // Allocate the interface information buffer
1273 pIfInfo
= AllocatePool ( DataSize
);
1274 if ( NULL
== pIfInfo
) {
1275 DEBUG (( DEBUG_ERROR
,
1276 "ERROR - Not enough memory to allocate the interface information buffer!\r\n" ));
1277 Status
= EFI_OUT_OF_RESOURCES
;
1282 // Get the interface info.
1284 Status
= pIpConfig2Protocol
->GetData (
1286 Ip4Config2DataTypeInterfaceInfo
,
1290 if ( EFI_ERROR ( Status
)) {
1291 DEBUG (( DEBUG_ERROR
,
1292 "ERROR - Failed to return the interface info, Status: %r\r\n",
1298 // Display the current configuration
1300 DEBUG (( DEBUG_BIND
,
1301 "Actual adapter IP address: %d.%d.%d.%d\r\n",
1302 pIfInfo
->StationAddress
.Addr
[ 0 ],
1303 pIfInfo
->StationAddress
.Addr
[ 1 ],
1304 pIfInfo
->StationAddress
.Addr
[ 2 ],
1305 pIfInfo
->StationAddress
.Addr
[ 3 ]));
1308 // Assume the port is not configured
1310 Status
= EFI_SUCCESS
;
1311 if (( pConfigData
->StationAddress
.Addr
[ 0 ] == pIfInfo
->StationAddress
.Addr
[ 0 ])
1312 && ( pConfigData
->StationAddress
.Addr
[ 1 ] == pIfInfo
->StationAddress
.Addr
[ 1 ])
1313 && ( pConfigData
->StationAddress
.Addr
[ 2 ] == pIfInfo
->StationAddress
.Addr
[ 2 ])
1314 && ( pConfigData
->StationAddress
.Addr
[ 3 ] == pIfInfo
->StationAddress
.Addr
[ 3 ])) {
1319 // The IP address did not match
1321 Status
= EFI_NOT_STARTED
;
1326 // Free the buffer if necessary
1328 if ( NULL
!= pIfInfo
) {
1329 FreePool ( pIfInfo
);
1333 // Return the IP address status
1335 DBG_EXIT_STATUS ( Status
);
1341 Interface between the socket layer and the network specific
1342 code that supports SOCK_RAW sockets over IPv4.
1344 CONST ESL_PROTOCOL_API cEslIp4Api
= {
1347 OFFSET_OF ( ESL_PORT
, Context
.Ip4
.ModeData
.ConfigData
),
1348 OFFSET_OF ( ESL_LAYER
, pIp4List
),
1349 OFFSET_OF ( struct sockaddr_in
, sin_zero
),
1350 sizeof ( struct sockaddr_in
),
1352 sizeof (((ESL_PACKET
*)0 )->Op
.Ip4Rx
),
1353 sizeof (((ESL_PACKET
*)0 )->Op
.Ip4Rx
),
1354 OFFSET_OF ( ESL_IO_MGMT
, Token
.Ip4Rx
.Packet
.RxData
),
1358 NULL
, // ConnectPoll
1359 NULL
, // ConnectStart
1360 EslIp4SocketIsConfigured
,
1361 EslIp4LocalAddressGet
,
1362 EslIp4LocalAddressSet
,
1369 NULL
, // PortCloseOp
1372 EslIp4RemoteAddressGet
,
1373 EslIp4RemoteAddressSet
,
1378 NULL
, // TxOobComplete
1379 (PFN_API_VERIFY_LOCAL_IP_ADDRESS
)EslIp4VerifyLocalIpAddress