2 Implement the IP4 driver support for the socket layer.
4 Copyright (c) 2011, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this 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] = 0xff;
147 pConfig
->SubnetMask
.Addr
[2] = 0xff;
148 pConfig
->SubnetMask
.Addr
[3] = 0xff;
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
->pfnRxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.IPv4
->Receive
;
387 pPort
->pfnTxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.IPv4
->Transmit
;
390 // Set the configuration flags
392 pConfig
= &pPort
->Context
.Ip4
.ModeData
.ConfigData
;
393 pConfig
->AcceptIcmpErrors
= FALSE
;
394 pConfig
->AcceptBroadcast
= FALSE
;
395 pConfig
->AcceptPromiscuous
= FALSE
;
396 pConfig
->TypeOfService
= 0;
397 pConfig
->TimeToLive
= 255;
398 pConfig
->DoNotFragment
= FALSE
;
399 pConfig
->RawData
= FALSE
;
400 pConfig
->ReceiveTimeout
= 0;
401 pConfig
->TransmitTimeout
= 0;
404 // Set the default protocol
406 pConfig
->DefaultProtocol
= (UINT8
)pSocket
->Protocol
;
407 pConfig
->AcceptAnyProtocol
= (BOOLEAN
)( 0 == pConfig
->DefaultProtocol
);
408 Status
= EFI_SUCCESS
;
411 // Return the operation status
413 DBG_EXIT_STATUS ( Status
);
419 Receive data from a network connection.
421 This routine attempts to return buffered data to the caller. The
422 data is removed from the urgent queue if the message flag MSG_OOB
423 is specified, otherwise data is removed from the normal queue.
424 See the \ref ReceiveEngine section.
426 This routine is called by ::EslSocketReceive to handle the network
427 specific receive operation to support SOCK_RAW sockets.
429 @param [in] pPort Address of an ::ESL_PORT structure.
431 @param [in] pPacket Address of an ::ESL_PACKET structure.
433 @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
435 @param [in] BufferLength Length of the the buffer
437 @param [in] pBuffer Address of a buffer to receive the data.
439 @param [in] pDataLength Number of received data bytes in the buffer.
441 @param [out] pAddress Network address to receive the remote system address
443 @param [out] pSkipBytes Address to receive the number of bytes skipped
445 @return Returns the address of the next free byte in the buffer.
451 IN ESL_PACKET
* pPacket
,
452 IN BOOLEAN
* pbConsumePacket
,
453 IN
size_t BufferLength
,
455 OUT
size_t * pDataLength
,
456 OUT
struct sockaddr
* pAddress
,
457 OUT
size_t * pSkipBytes
462 size_t LengthInBytes
;
463 struct sockaddr_in
* pRemoteAddress
;
464 EFI_IP4_RECEIVE_DATA
* pRxData
;
469 // Return the remote system address if requested
471 pRxData
= pPacket
->Op
.Ip4Rx
.pRxData
;
472 if ( NULL
!= pAddress
) {
474 // Build the remote address
477 "Getting packet remote address: %d.%d.%d.%d\r\n",
478 pRxData
->Header
->SourceAddress
.Addr
[0],
479 pRxData
->Header
->SourceAddress
.Addr
[1],
480 pRxData
->Header
->SourceAddress
.Addr
[2],
481 pRxData
->Header
->SourceAddress
.Addr
[3]));
482 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
483 CopyMem ( &pRemoteAddress
->sin_addr
,
484 &pRxData
->Header
->SourceAddress
.Addr
[0],
485 sizeof ( pRemoteAddress
->sin_addr
));
489 // Copy the IP header
491 HeaderBytes
= pRxData
->HeaderLength
;
492 if ( HeaderBytes
> BufferLength
) {
493 HeaderBytes
= BufferLength
;
496 "0x%08x --> 0x%08x: Copy header 0x%08x bytes\r\n",
500 CopyMem ( pBuffer
, pRxData
->Header
, HeaderBytes
);
501 pBuffer
+= HeaderBytes
;
502 LengthInBytes
= HeaderBytes
;
505 // Copy the received data
507 if ( 0 < ( BufferLength
- LengthInBytes
)) {
508 pBuffer
= EslSocketCopyFragmentedBuffer ( pRxData
->FragmentCount
,
509 &pRxData
->FragmentTable
[0],
510 BufferLength
- LengthInBytes
,
513 LengthInBytes
+= DataBytes
;
517 // Determine if the data is being read
519 if ( *pbConsumePacket
) {
521 // Display for the bytes consumed
524 "0x%08x: Port account for 0x%08x bytes\r\n",
529 // Account for any discarded data
531 *pSkipBytes
= pRxData
->HeaderLength
+ pRxData
->DataLength
- LengthInBytes
;
535 // Return the data length and the buffer address
537 *pDataLength
= LengthInBytes
;
538 DBG_EXIT_HEX ( pBuffer
);
544 Get the remote socket address
546 This routine returns the address of the remote connection point
547 associated with the SOCK_RAW socket.
549 This routine is called by ::EslSocketGetPeerAddress to detemine
550 the IPv4 address associated with the network adapter.
552 @param [in] pPort Address of an ::ESL_PORT structure.
554 @param [out] pAddress Network address to receive the remote system address
558 EslIp4RemoteAddressGet (
560 OUT
struct sockaddr
* pAddress
563 struct sockaddr_in
* pRemoteAddress
;
564 ESL_IP4_CONTEXT
* pIp4
;
569 // Return the remote address
571 pIp4
= &pPort
->Context
.Ip4
;
572 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
573 pRemoteAddress
->sin_family
= AF_INET
;
574 CopyMem ( &pRemoteAddress
->sin_addr
,
575 &pIp4
->DestinationAddress
.Addr
[0],
576 sizeof ( pRemoteAddress
->sin_addr
));
583 Set the remote address
585 This routine sets the remote address in the port.
587 This routine is called by ::EslSocketConnect to specify the
588 remote network address.
590 @param [in] pPort Address of an ::ESL_PORT structure.
592 @param [in] pSockAddr Network address of the remote system.
594 @param [in] SockAddrLength Length in bytes of the network address.
596 @retval EFI_SUCCESS The operation was successful
600 EslIp4RemoteAddressSet (
602 IN CONST
struct sockaddr
* pSockAddr
,
603 IN socklen_t SockAddrLength
606 ESL_IP4_CONTEXT
* pIp4
;
607 CONST
struct sockaddr_in
* pRemoteAddress
;
613 // Set the remote address
615 pIp4
= &pPort
->Context
.Ip4
;
616 pRemoteAddress
= (struct sockaddr_in
*)pSockAddr
;
617 pIp4
->DestinationAddress
.Addr
[0] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
);
618 pIp4
->DestinationAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
619 pIp4
->DestinationAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
620 pIp4
->DestinationAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
621 Status
= EFI_SUCCESS
;
624 // Return the operation status
626 DBG_EXIT_STATUS ( Status
);
632 Process the receive completion
634 This routine keeps the IPv4 driver's buffer and queues it in
635 in FIFO order to the data queue. The IP4 driver's buffer will
636 be returned by either ::EslIp4Receive or ::EslSocketPortCloseTxDone.
637 See the \ref ReceiveEngine section.
639 This routine is called by the IPv4 driver when data is
642 @param [in] Event The receive completion event
644 @param [in] pIo The address of an ::ESL_IO_MGMT structure
653 size_t LengthInBytes
;
655 ESL_PACKET
* pPacket
;
656 EFI_IP4_RECEIVE_DATA
* pRxData
;
662 // 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 if ( NULL
== pSocket
->pPortList
) {
751 LocalAddress
.sin_len
= sizeof ( LocalAddress
);
752 LocalAddress
.sin_family
= AF_INET
;
753 LocalAddress
.sin_addr
.s_addr
= 0;
754 LocalAddress
.sin_port
= 0;
755 Status
= EslSocketBind ( &pSocket
->SocketProtocol
,
756 (struct sockaddr
*)&LocalAddress
,
757 LocalAddress
.sin_len
,
762 // Walk the port list
764 pPort
= pSocket
->pPortList
;
765 while ( NULL
!= pPort
) {
767 // Update the raw setting
769 pIp4
= &pPort
->Context
.Ip4
;
770 if ( pSocket
->bIncludeHeader
) {
772 // IP header will be included with the data on transmit
774 pIp4
->ModeData
.ConfigData
.RawData
= TRUE
;
778 // Attempt to configure the port
780 pNextPort
= pPort
->pLinkSocket
;
781 pIp4Protocol
= pPort
->pProtocol
.IPv4
;
783 "0x%08x: pPort Configuring for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
785 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0],
786 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[1],
787 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[2],
788 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[3],
789 pIp4
->DestinationAddress
.Addr
[0],
790 pIp4
->DestinationAddress
.Addr
[1],
791 pIp4
->DestinationAddress
.Addr
[2],
792 pIp4
->DestinationAddress
.Addr
[3]));
793 Status
= pIp4Protocol
->Configure ( pIp4Protocol
,
794 &pIp4
->ModeData
.ConfigData
);
795 if ( !EFI_ERROR ( Status
)) {
797 // Update the configuration data
799 Status
= pIp4Protocol
->GetModeData ( pIp4Protocol
,
804 if ( EFI_ERROR ( Status
)) {
805 DEBUG (( DEBUG_LISTEN
,
806 "ERROR - Failed to configure the Ip4 port, Status: %r\r\n",
809 case EFI_ACCESS_DENIED
:
810 pSocket
->errno
= EACCES
;
814 case EFI_DEVICE_ERROR
:
815 pSocket
->errno
= EIO
;
818 case EFI_INVALID_PARAMETER
:
819 pSocket
->errno
= EADDRNOTAVAIL
;
823 pSocket
->errno
= EAFNOSUPPORT
;
826 case EFI_OUT_OF_RESOURCES
:
827 pSocket
->errno
= ENOBUFS
;
830 case EFI_UNSUPPORTED
:
831 pSocket
->errno
= EOPNOTSUPP
;
837 "0x%08x: pPort Configured for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
839 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0],
840 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[1],
841 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[2],
842 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[3],
843 pIp4
->DestinationAddress
.Addr
[0],
844 pIp4
->DestinationAddress
.Addr
[1],
845 pIp4
->DestinationAddress
.Addr
[2],
846 pIp4
->DestinationAddress
.Addr
[3]));
848 "Subnet Mask: %d.%d.%d.%d\r\n",
849 pIp4
->ModeData
.ConfigData
.SubnetMask
.Addr
[0],
850 pIp4
->ModeData
.ConfigData
.SubnetMask
.Addr
[1],
851 pIp4
->ModeData
.ConfigData
.SubnetMask
.Addr
[2],
852 pIp4
->ModeData
.ConfigData
.SubnetMask
.Addr
[3]));
854 "Route Count: %d\r\n",
855 pIp4
->ModeData
.RouteCount
));
856 for ( Index
= 0; pIp4
->ModeData
.RouteCount
> Index
; Index
++ ) {
858 DEBUG (( DEBUG_TX
, "Route Table:\r\n" ));
861 "%5d: %d.%d.%d.%d, %d.%d.%d.%d ==> %d.%d.%d.%d\r\n",
863 pIp4
->ModeData
.RouteTable
[Index
].SubnetAddress
.Addr
[0],
864 pIp4
->ModeData
.RouteTable
[Index
].SubnetAddress
.Addr
[1],
865 pIp4
->ModeData
.RouteTable
[Index
].SubnetAddress
.Addr
[2],
866 pIp4
->ModeData
.RouteTable
[Index
].SubnetAddress
.Addr
[3],
867 pIp4
->ModeData
.RouteTable
[Index
].SubnetMask
.Addr
[0],
868 pIp4
->ModeData
.RouteTable
[Index
].SubnetMask
.Addr
[1],
869 pIp4
->ModeData
.RouteTable
[Index
].SubnetMask
.Addr
[2],
870 pIp4
->ModeData
.RouteTable
[Index
].SubnetMask
.Addr
[3],
871 pIp4
->ModeData
.RouteTable
[Index
].GatewayAddress
.Addr
[0],
872 pIp4
->ModeData
.RouteTable
[Index
].GatewayAddress
.Addr
[1],
873 pIp4
->ModeData
.RouteTable
[Index
].GatewayAddress
.Addr
[2],
874 pIp4
->ModeData
.RouteTable
[Index
].GatewayAddress
.Addr
[3]));
876 pPort
->bConfigured
= TRUE
;
879 // Start the first read on the port
881 EslSocketRxStart ( pPort
);
884 // The socket is connected
886 pSocket
->State
= SOCKET_STATE_CONNECTED
;
896 // Determine the configuration status
898 if ( NULL
!= pSocket
->pPortList
) {
899 pSocket
->bConfigured
= TRUE
;
904 // Determine the socket configuration status
906 if ( !EFI_ERROR ( Status
)) {
907 Status
= pSocket
->bConfigured
? EFI_SUCCESS
: EFI_NOT_STARTED
;
911 // Return the port connected state.
913 DBG_EXIT_STATUS ( Status
);
919 Buffer data for transmission over a network connection.
921 This routine buffers data for the transmit engine in the normal
922 data queue. When the \ref TransmitEngine has resources, this
923 routine will start the transmission of the next buffer on the
926 This routine is called by ::EslSocketTransmit to buffer
927 data for transmission. The data is copied into a local buffer
928 freeing the application buffer for reuse upon return. When
929 necessary, this routine starts the transmit engine that
930 performs the data transmission on the network connection. The
931 transmit engine transmits the data a packet at a time over the
934 Transmission errors are returned during the next transmission or
935 during the close operation. Only buffering errors are returned
936 during the current transmission attempt.
938 @param [in] pSocket Address of an ::ESL_SOCKET structure
940 @param [in] Flags Message control flags
942 @param [in] BufferLength Length of the the buffer
944 @param [in] pBuffer Address of a buffer to receive the data.
946 @param [in] pDataLength Number of received data bytes in the buffer.
948 @param [in] pAddress Network address of the remote system address
950 @param [in] AddressLength Length of the remote network address structure
952 @retval EFI_SUCCESS - Socket data successfully buffered
957 IN ESL_SOCKET
* pSocket
,
959 IN
size_t BufferLength
,
960 IN CONST UINT8
* pBuffer
,
961 OUT
size_t * pDataLength
,
962 IN
const struct sockaddr
* pAddress
,
963 IN socklen_t AddressLength
966 ESL_PACKET
* pPacket
;
967 ESL_PACKET
* pPreviousPacket
;
969 const struct sockaddr_in
* pRemoteAddress
;
970 ESL_IP4_CONTEXT
* pIp4
;
972 ESL_IP4_TX_DATA
* pTxData
;
981 Status
= EFI_UNSUPPORTED
;
982 pSocket
->errno
= ENOTCONN
;
986 // Verify that the socket is connected
988 if ( SOCKET_STATE_CONNECTED
== pSocket
->State
) {
992 pPort
= pSocket
->pPortList
;
993 if ( NULL
!= pPort
) {
995 // Determine the queue head
997 pIp4
= &pPort
->Context
.Ip4
;
998 pTxBytes
= &pSocket
->TxBytes
;
1001 // Verify that there is enough room to buffer another
1002 // transmit operation
1004 if ( pSocket
->MaxTxBuf
> *pTxBytes
) {
1006 // Attempt to allocate the packet
1008 Status
= EslSocketPacketAllocate ( &pPacket
,
1009 sizeof ( pPacket
->Op
.Ip4Tx
)
1010 - sizeof ( pPacket
->Op
.Ip4Tx
.Buffer
)
1014 if ( !EFI_ERROR ( Status
)) {
1016 // Initialize the transmit operation
1018 pTxData
= &pPacket
->Op
.Ip4Tx
;
1019 pTxData
->TxData
.DestinationAddress
.Addr
[0] = pIp4
->DestinationAddress
.Addr
[0];
1020 pTxData
->TxData
.DestinationAddress
.Addr
[1] = pIp4
->DestinationAddress
.Addr
[1];
1021 pTxData
->TxData
.DestinationAddress
.Addr
[2] = pIp4
->DestinationAddress
.Addr
[2];
1022 pTxData
->TxData
.DestinationAddress
.Addr
[3] = pIp4
->DestinationAddress
.Addr
[3];
1023 pTxData
->TxData
.OverrideData
= NULL
;
1024 pTxData
->TxData
.OptionsLength
= 0;
1025 pTxData
->TxData
.OptionsBuffer
= NULL
;
1026 pTxData
->TxData
.TotalDataLength
= (UINT32
) BufferLength
;
1027 pTxData
->TxData
.FragmentCount
= 1;
1028 pTxData
->TxData
.FragmentTable
[0].FragmentLength
= (UINT32
) BufferLength
;
1029 pTxData
->TxData
.FragmentTable
[0].FragmentBuffer
= &pPacket
->Op
.Ip4Tx
.Buffer
[0];
1032 // Set the remote system address if necessary
1034 if ( NULL
!= pAddress
) {
1035 pRemoteAddress
= (const struct sockaddr_in
*)pAddress
;
1036 pTxData
->Override
.SourceAddress
.Addr
[0] = pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0];
1037 pTxData
->Override
.SourceAddress
.Addr
[1] = pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[1];
1038 pTxData
->Override
.SourceAddress
.Addr
[2] = pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[2];
1039 pTxData
->Override
.SourceAddress
.Addr
[3] = pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[3];
1040 pTxData
->TxData
.DestinationAddress
.Addr
[0] = (UINT8
)pRemoteAddress
->sin_addr
.s_addr
;
1041 pTxData
->TxData
.DestinationAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
1042 pTxData
->TxData
.DestinationAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
1043 pTxData
->TxData
.DestinationAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
1044 pTxData
->Override
.GatewayAddress
.Addr
[0] = 0;
1045 pTxData
->Override
.GatewayAddress
.Addr
[1] = 0;
1046 pTxData
->Override
.GatewayAddress
.Addr
[2] = 0;
1047 pTxData
->Override
.GatewayAddress
.Addr
[3] = 0;
1048 pTxData
->Override
.Protocol
= (UINT8
)pSocket
->Protocol
;
1049 pTxData
->Override
.TypeOfService
= 0;
1050 pTxData
->Override
.TimeToLive
= 255;
1051 pTxData
->Override
.DoNotFragment
= FALSE
;
1054 // Use the remote system address when sending this packet
1056 pTxData
->TxData
.OverrideData
= &pTxData
->Override
;
1060 // Copy the data into the buffer
1062 CopyMem ( &pPacket
->Op
.Ip4Tx
.Buffer
[0],
1067 // Synchronize with the socket layer
1069 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
1072 // Stop transmission after an error
1074 if ( !EFI_ERROR ( pSocket
->TxError
)) {
1076 // Display the request
1079 "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n",
1082 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[0],
1083 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[1],
1084 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[2],
1085 pIp4
->ModeData
.ConfigData
.StationAddress
.Addr
[3],
1086 pTxData
->TxData
.DestinationAddress
.Addr
[0],
1087 pTxData
->TxData
.DestinationAddress
.Addr
[1],
1088 pTxData
->TxData
.DestinationAddress
.Addr
[2],
1089 pTxData
->TxData
.DestinationAddress
.Addr
[3]));
1092 // Queue the data for transmission
1094 pPacket
->pNext
= NULL
;
1095 pPreviousPacket
= pSocket
->pTxPacketListTail
;
1096 if ( NULL
== pPreviousPacket
) {
1097 pSocket
->pTxPacketListHead
= pPacket
;
1100 pPreviousPacket
->pNext
= pPacket
;
1102 pSocket
->pTxPacketListTail
= pPacket
;
1104 "0x%08x: Packet on transmit list\r\n",
1108 // Account for the buffered data
1110 *pTxBytes
+= BufferLength
;
1111 *pDataLength
= BufferLength
;
1114 // Start the transmit engine if it is idle
1116 if ( NULL
!= pPort
->pTxFree
) {
1117 EslSocketTxStart ( pPort
,
1118 &pSocket
->pTxPacketListHead
,
1119 &pSocket
->pTxPacketListTail
,
1126 // Previous transmit error
1127 // Stop transmission
1129 Status
= pSocket
->TxError
;
1130 pSocket
->errno
= EIO
;
1135 EslSocketPacketFree ( pPacket
, DEBUG_TX
);
1139 // Release the socket layer synchronization
1141 RESTORE_TPL ( TplPrevious
);
1145 // Packet allocation failed
1147 pSocket
->errno
= ENOMEM
;
1152 // Not enough buffer space available
1154 pSocket
->errno
= EAGAIN
;
1155 Status
= EFI_NOT_READY
;
1161 // Return the operation status
1163 DBG_EXIT_STATUS ( Status
);
1169 Process the transmit completion
1171 This routine use ::EslSocketTxComplete to perform the transmit
1172 completion processing for data packets.
1174 This routine is called by the IPv4 network layer when a data
1175 transmit request completes.
1177 @param [in] Event The normal transmit completion event
1179 @param [in] pIo The address of an ::ESL_IO_MGMT structure
1185 IN ESL_IO_MGMT
* pIo
1188 UINT32 LengthInBytes
;
1190 ESL_PACKET
* pPacket
;
1191 ESL_SOCKET
* pSocket
;
1197 // Locate the active transmit packet
1199 pPacket
= pIo
->pPacket
;
1201 pSocket
= pPort
->pSocket
;
1204 // Get the transmit length and status
1206 LengthInBytes
= pPacket
->Op
.Ip4Tx
.TxData
.TotalDataLength
;
1207 pSocket
->TxBytes
-= LengthInBytes
;
1208 Status
= pIo
->Token
.Ip4Tx
.Status
;
1211 // Complete the transmit operation
1213 EslSocketTxComplete ( pIo
,
1217 &pSocket
->pTxPacketListHead
,
1218 &pSocket
->pTxPacketListTail
,
1226 Interface between the socket layer and the network specific
1227 code that supports SOCK_RAW sockets over IPv4.
1229 CONST ESL_PROTOCOL_API cEslIp4Api
= {
1232 OFFSET_OF ( ESL_PORT
, Context
.Ip4
.ModeData
.ConfigData
),
1233 OFFSET_OF ( ESL_LAYER
, pIp4List
),
1234 OFFSET_OF ( struct sockaddr_in
, sin_zero
),
1235 sizeof ( struct sockaddr_in
),
1237 sizeof (((ESL_PACKET
*)0 )->Op
.Ip4Rx
),
1238 sizeof (((ESL_PACKET
*)0 )->Op
.Ip4Rx
),
1239 OFFSET_OF ( ESL_IO_MGMT
, Token
.Ip4Rx
.Packet
.RxData
),
1243 NULL
, // ConnectPoll
1244 NULL
, // ConnectStart
1245 EslIp4SocketIsConfigured
,
1246 EslIp4LocalAddressGet
,
1247 EslIp4LocalAddressSet
,
1254 NULL
, // PortCloseOp
1257 EslIp4RemoteAddressGet
,
1258 EslIp4RemoteAddressSet
,
1263 NULL
// TxOobComplete