2 Implement the UDP4 driver support for the socket layer.
4 Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
13 Get the local socket address
15 This routine returns the IPv4 address and UDP port number associated
16 with the local socket.
18 This routine is called by ::EslSocketGetLocalAddress to determine the
19 network address for the SOCK_DGRAM socket.
21 @param [in] pPort Address of an ::ESL_PORT structure.
23 @param [out] pSockAddr Network address to receive the local system address
27 EslUdp4LocalAddressGet (
29 OUT
struct sockaddr
* pSockAddr
32 struct sockaddr_in
* pLocalAddress
;
33 ESL_UDP4_CONTEXT
* pUdp4
;
38 // Return the local address
40 pUdp4
= &pPort
->Context
.Udp4
;
41 pLocalAddress
= (struct sockaddr_in
*)pSockAddr
;
42 pLocalAddress
->sin_family
= AF_INET
;
43 pLocalAddress
->sin_port
= SwapBytes16 ( pUdp4
->ConfigData
.StationPort
);
44 CopyMem ( &pLocalAddress
->sin_addr
,
45 &pUdp4
->ConfigData
.StationAddress
.Addr
[0],
46 sizeof ( pLocalAddress
->sin_addr
));
53 Set the local port address.
55 This routine sets the local port address.
57 This support routine is called by ::EslSocketPortAllocate.
59 @param [in] pPort Address of an ESL_PORT structure
60 @param [in] pSockAddr Address of a sockaddr structure that contains the
61 connection point on the local machine. An IPv4 address
62 of INADDR_ANY specifies that the connection is made to
63 all of the network stacks on the platform. Specifying a
64 specific IPv4 address restricts the connection to the
65 network stack supporting that address. Specifying zero
66 for the port causes the network layer to assign a port
67 number from the dynamic range. Specifying a specific
68 port number causes the network layer to use that port.
70 @param [in] bBindTest TRUE = run bind testing
72 @retval EFI_SUCCESS The operation was successful
76 EslUdp4LocalAddressSet (
78 IN CONST
struct sockaddr
* pSockAddr
,
82 EFI_UDP4_CONFIG_DATA
* pConfig
;
83 CONST
struct sockaddr_in
* pIpAddress
;
84 CONST UINT8
* pIpv4Address
;
90 // Validate the address
92 pIpAddress
= (struct sockaddr_in
*)pSockAddr
;
93 if ( INADDR_BROADCAST
== pIpAddress
->sin_addr
.s_addr
) {
95 // The local address must not be the broadcast address
97 Status
= EFI_INVALID_PARAMETER
;
98 pPort
->pSocket
->errno
= EADDRNOTAVAIL
;
102 // Set the local address
104 pIpAddress
= (struct sockaddr_in
*)pSockAddr
;
105 pIpv4Address
= (UINT8
*)&pIpAddress
->sin_addr
.s_addr
;
106 pConfig
= &pPort
->Context
.Udp4
.ConfigData
;
107 pConfig
->StationAddress
.Addr
[0] = pIpv4Address
[0];
108 pConfig
->StationAddress
.Addr
[1] = pIpv4Address
[1];
109 pConfig
->StationAddress
.Addr
[2] = pIpv4Address
[2];
110 pConfig
->StationAddress
.Addr
[3] = pIpv4Address
[3];
113 // Determine if the default address is used
115 pConfig
->UseDefaultAddress
= (BOOLEAN
)( 0 == pIpAddress
->sin_addr
.s_addr
);
118 // Set the subnet mask
120 if ( pConfig
->UseDefaultAddress
) {
121 pConfig
->SubnetMask
.Addr
[0] = 0;
122 pConfig
->SubnetMask
.Addr
[1] = 0;
123 pConfig
->SubnetMask
.Addr
[2] = 0;
124 pConfig
->SubnetMask
.Addr
[3] = 0;
127 pConfig
->SubnetMask
.Addr
[0] = 0xff;
128 pConfig
->SubnetMask
.Addr
[1] = ( 128 <= pConfig
->StationAddress
.Addr
[0]) ? 0xff : 0;
129 pConfig
->SubnetMask
.Addr
[2] = ( 192 <= pConfig
->StationAddress
.Addr
[0]) ? 0xff : 0;
130 pConfig
->SubnetMask
.Addr
[3] = ( 224 <= pConfig
->StationAddress
.Addr
[0]) ? 0xff : 0;
134 // Validate the IP address
136 pConfig
->StationPort
= 0;
137 Status
= bBindTest
? EslSocketBindTest ( pPort
, EADDRNOTAVAIL
)
139 if ( !EFI_ERROR ( Status
)) {
141 // Set the port number
143 pConfig
->StationPort
= SwapBytes16 ( pIpAddress
->sin_port
);
146 // Display the local address
149 "0x%08x: Port, Local UDP4 Address: %d.%d.%d.%d:%d\r\n",
151 pConfig
->StationAddress
.Addr
[0],
152 pConfig
->StationAddress
.Addr
[1],
153 pConfig
->StationAddress
.Addr
[2],
154 pConfig
->StationAddress
.Addr
[3],
155 pConfig
->StationPort
));
160 // Return the operation status
162 DBG_EXIT_STATUS ( Status
);
168 Free a receive packet
170 This routine performs the network specific operations necessary
171 to free a receive packet.
173 This routine is called by ::EslSocketPortCloseTxDone to free a
176 @param [in] pPacket Address of an ::ESL_PACKET structure.
177 @param [in, out] pRxBytes Address of the count of RX bytes
182 IN ESL_PACKET
* pPacket
,
183 IN OUT
size_t * pRxBytes
186 EFI_UDP4_RECEIVE_DATA
* pRxData
;
191 // Account for the receive bytes
193 pRxData
= pPacket
->Op
.Udp4Rx
.pRxData
;
194 *pRxBytes
-= pRxData
->DataLength
;
197 // Disconnect the buffer from the packet
199 pPacket
->Op
.Udp4Rx
.pRxData
= NULL
;
202 // Return the buffer to the UDP4 driver
204 gBS
->SignalEvent ( pRxData
->RecycleSignal
);
210 Initialize the network specific portions of an ::ESL_PORT structure.
212 This routine initializes the network specific portions of an
213 ::ESL_PORT structure for use by the socket.
215 This support routine is called by ::EslSocketPortAllocate
216 to connect the socket with the underlying network adapter
217 running the UDPv4 protocol.
219 @param [in] pPort Address of an ESL_PORT structure
220 @param [in] DebugFlags Flags for debug messages
222 @retval EFI_SUCCESS - Socket successfully created
226 EslUdp4PortAllocate (
231 EFI_UDP4_CONFIG_DATA
* pConfig
;
232 ESL_SOCKET
* pSocket
;
238 // Initialize the port
240 pSocket
= pPort
->pSocket
;
241 pSocket
->TxPacketOffset
= OFFSET_OF ( ESL_PACKET
, Op
.Udp4Tx
.TxData
);
242 pSocket
->TxTokenEventOffset
= OFFSET_OF ( ESL_IO_MGMT
, Token
.Udp4Tx
.Event
);
243 pSocket
->TxTokenOffset
= OFFSET_OF ( EFI_UDP4_COMPLETION_TOKEN
, Packet
.TxData
);
246 // Save the cancel, receive and transmit addresses
248 pPort
->pfnConfigure
= (PFN_NET_CONFIGURE
)pPort
->pProtocol
.UDPv4
->Configure
;
249 pPort
->pfnRxCancel
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv4
->Cancel
;
250 pPort
->pfnRxPoll
= (PFN_NET_POLL
)pPort
->pProtocol
.UDPv4
->Poll
;
251 pPort
->pfnRxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv4
->Receive
;
252 pPort
->pfnTxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv4
->Transmit
;
255 // Set the configuration flags
257 pConfig
= &pPort
->Context
.Udp4
.ConfigData
;
258 pConfig
->TimeToLive
= 255;
259 pConfig
->AcceptAnyPort
= FALSE
;
260 pConfig
->AcceptBroadcast
= FALSE
;
261 pConfig
->AcceptPromiscuous
= FALSE
;
262 pConfig
->AllowDuplicatePort
= TRUE
;
263 pConfig
->DoNotFragment
= FALSE
;
264 Status
= EFI_SUCCESS
;
267 // Return the operation status
269 DBG_EXIT_STATUS ( Status
);
275 Receive data from a network connection.
277 This routine attempts to return buffered data to the caller. The
278 data is removed from the urgent queue if the message flag MSG_OOB
279 is specified, otherwise data is removed from the normal queue.
280 See the \ref ReceiveEngine section.
282 This routine is called by ::EslSocketReceive to handle the network
283 specific receive operation to support SOCK_DGRAM sockets.
285 @param [in] pPort Address of an ::ESL_PORT structure.
287 @param [in] pPacket Address of an ::ESL_PACKET structure.
289 @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
291 @param [in] BufferLength Length of the the buffer
293 @param [in] pBuffer Address of a buffer to receive the data.
295 @param [in] pDataLength Number of received data bytes in the buffer.
297 @param [out] pAddress Network address to receive the remote system address
299 @param [out] pSkipBytes Address to receive the number of bytes skipped
301 @return Returns the address of the next free byte in the buffer.
307 IN ESL_PACKET
* pPacket
,
308 IN BOOLEAN
* pbConsumePacket
,
309 IN
size_t BufferLength
,
311 OUT
size_t * pDataLength
,
312 OUT
struct sockaddr
* pAddress
,
313 OUT
size_t * pSkipBytes
317 struct sockaddr_in
* pRemoteAddress
;
318 EFI_UDP4_RECEIVE_DATA
* pRxData
;
322 pRxData
= pPacket
->Op
.Udp4Rx
.pRxData
;
324 // Return the remote system address if requested
326 if ( NULL
!= pAddress
) {
328 // Build the remote address
331 "Getting packet remote address: %d.%d.%d.%d:%d\r\n",
332 pRxData
->UdpSession
.SourceAddress
.Addr
[0],
333 pRxData
->UdpSession
.SourceAddress
.Addr
[1],
334 pRxData
->UdpSession
.SourceAddress
.Addr
[2],
335 pRxData
->UdpSession
.SourceAddress
.Addr
[3],
336 pRxData
->UdpSession
.SourcePort
));
337 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
338 CopyMem ( &pRemoteAddress
->sin_addr
,
339 &pRxData
->UdpSession
.SourceAddress
.Addr
[0],
340 sizeof ( pRemoteAddress
->sin_addr
));
341 pRemoteAddress
->sin_port
= SwapBytes16 ( pRxData
->UdpSession
.SourcePort
);
345 // Copy the received data
347 pBuffer
= EslSocketCopyFragmentedBuffer ( pRxData
->FragmentCount
,
348 (EFI_IP4_FRAGMENT_DATA
*)&pRxData
->FragmentTable
[0],
354 // Determine if the data is being read
356 if ( *pbConsumePacket
) {
358 // Display for the bytes consumed
361 "0x%08x: Port account for 0x%08x bytes\r\n",
366 // Account for any discarded data
368 *pSkipBytes
= pRxData
->DataLength
- DataBytes
;
372 // Return the data length and the buffer address
374 *pDataLength
= DataBytes
;
375 DBG_EXIT_HEX ( pBuffer
);
381 Get the remote socket address
383 This routine returns the address of the remote connection point
384 associated with the SOCK_DGRAM socket.
386 This routine is called by ::EslSocketGetPeerAddress to detemine
387 the UDPv4 address and port number associated with the network adapter.
389 @param [in] pPort Address of an ::ESL_PORT structure.
391 @param [out] pAddress Network address to receive the remote system address
395 EslUdp4RemoteAddressGet (
397 OUT
struct sockaddr
* pAddress
400 struct sockaddr_in
* pRemoteAddress
;
401 ESL_UDP4_CONTEXT
* pUdp4
;
406 // Return the remote address
408 pUdp4
= &pPort
->Context
.Udp4
;
409 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
410 pRemoteAddress
->sin_family
= AF_INET
;
411 pRemoteAddress
->sin_port
= SwapBytes16 ( pUdp4
->ConfigData
.RemotePort
);
412 CopyMem ( &pRemoteAddress
->sin_addr
,
413 &pUdp4
->ConfigData
.RemoteAddress
.Addr
[0],
414 sizeof ( pRemoteAddress
->sin_addr
));
421 Set the remote address
423 This routine sets the remote address in the port.
425 This routine is called by ::EslSocketConnect to specify the
426 remote network address.
428 @param [in] pPort Address of an ::ESL_PORT structure.
430 @param [in] pSockAddr Network address of the remote system.
432 @param [in] SockAddrLength Length in bytes of the network address.
434 @retval EFI_SUCCESS The operation was successful
438 EslUdp4RemoteAddressSet (
440 IN CONST
struct sockaddr
* pSockAddr
,
441 IN socklen_t SockAddrLength
444 CONST
struct sockaddr_in
* pRemoteAddress
;
445 ESL_UDP4_CONTEXT
* pUdp4
;
451 // Set the remote address
453 pUdp4
= &pPort
->Context
.Udp4
;
454 pRemoteAddress
= (struct sockaddr_in
*)pSockAddr
;
455 pUdp4
->ConfigData
.RemoteAddress
.Addr
[0] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
);
456 pUdp4
->ConfigData
.RemoteAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
457 pUdp4
->ConfigData
.RemoteAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
458 pUdp4
->ConfigData
.RemoteAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
459 pUdp4
->ConfigData
.RemotePort
= SwapBytes16 ( pRemoteAddress
->sin_port
);
460 pPort
->pSocket
->bAddressSet
= TRUE
;
461 Status
= EFI_SUCCESS
;
464 // Return the operation status
466 DBG_EXIT_STATUS ( Status
);
472 Process the receive completion
474 This routine keeps the UDPv4 driver's buffer and queues it in
475 in FIFO order to the data queue. The UDP4 driver's buffer will
476 be returned by either ::EslUdp4Receive or ::EslSocketPortCloseTxDone.
477 See the \ref ReceiveEngine section.
479 This routine is called by the UDPv4 driver when data is
482 @param [in] Event The receive completion event
484 @param [in] pIo Address of an ::ESL_IO_MGMT structure
493 size_t LengthInBytes
;
494 ESL_PACKET
* pPacket
;
495 EFI_UDP4_RECEIVE_DATA
* pRxData
;
501 // Get the operation status.
503 Status
= pIo
->Token
.Udp4Rx
.Status
;
506 // Get the packet length
508 pRxData
= pIo
->Token
.Udp4Rx
.Packet
.RxData
;
509 LengthInBytes
= pRxData
->DataLength
;
512 // +--------------------+ +-----------------------+
513 // | ESL_IO_MGMT | | Data Buffer |
514 // | | | (Driver owned) |
515 // | +---------------+ +-----------------------+
518 // | | | +-----------------------+
519 // | | RxData --> | EFI_UDP4_RECEIVE_DATA |
520 // +----+---------------+ | (Driver owned) |
521 // +-----------------------+
522 // +--------------------+ ^
525 // | +---------------+ .
526 // | | pRxData --> NULL .......
527 // +----+---------------+
530 // Save the data in the packet
532 pPacket
= pIo
->pPacket
;
533 pPacket
->Op
.Udp4Rx
.pRxData
= pRxData
;
536 // Complete this request
538 EslSocketRxComplete ( pIo
, Status
, LengthInBytes
, FALSE
);
544 Determine if the socket is configured.
546 This routine uses the flag ESL_SOCKET::bConfigured to determine
547 if the network layer's configuration routine has been called.
548 This routine calls the bind and configuration routines if they
549 were not already called. After the port is configured, the
550 \ref ReceiveEngine is started.
552 This routine is called by EslSocketIsConfigured to verify
553 that the socket is configured.
555 @param [in] pSocket Address of an ::ESL_SOCKET structure
557 @retval EFI_SUCCESS - The port is connected
558 @retval EFI_NOT_STARTED - The port is not connected
562 EslUdp4SocketIsConfigured (
563 IN ESL_SOCKET
* pSocket
566 EFI_UDP4_CONFIG_DATA
* pConfigData
;
568 ESL_PORT
* pNextPort
;
569 ESL_UDP4_CONTEXT
* pUdp4
;
570 EFI_UDP4_PROTOCOL
* pUdp4Protocol
;
572 struct sockaddr_in LocalAddress
;
579 Status
= EFI_SUCCESS
;
582 // Configure the port if necessary
584 if ( !pSocket
->bConfigured
) {
586 // Fill in the port list if necessary
588 pSocket
->errno
= ENETDOWN
;
589 if ( NULL
== pSocket
->pPortList
) {
590 LocalAddress
.sin_len
= sizeof ( LocalAddress
);
591 LocalAddress
.sin_family
= AF_INET
;
592 LocalAddress
.sin_addr
.s_addr
= 0;
593 LocalAddress
.sin_port
= 0;
594 Status
= EslSocketBind ( &pSocket
->SocketProtocol
,
595 (struct sockaddr
*)&LocalAddress
,
596 LocalAddress
.sin_len
,
601 // Walk the port list
603 pPort
= pSocket
->pPortList
;
604 while ( NULL
!= pPort
) {
606 // Attempt to configure the port
608 pNextPort
= pPort
->pLinkSocket
;
609 pUdp4
= &pPort
->Context
.Udp4
;
610 pUdp4Protocol
= pPort
->pProtocol
.UDPv4
;
611 pConfigData
= &pUdp4
->ConfigData
;
613 "0x%08x: pPort Configuring for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n",
615 pConfigData
->StationAddress
.Addr
[0],
616 pConfigData
->StationAddress
.Addr
[1],
617 pConfigData
->StationAddress
.Addr
[2],
618 pConfigData
->StationAddress
.Addr
[3],
619 pConfigData
->StationPort
,
620 pConfigData
->RemoteAddress
.Addr
[0],
621 pConfigData
->RemoteAddress
.Addr
[1],
622 pConfigData
->RemoteAddress
.Addr
[2],
623 pConfigData
->RemoteAddress
.Addr
[3],
624 pConfigData
->RemotePort
));
625 Status
= pUdp4Protocol
->Configure ( pUdp4Protocol
,
627 if ( !EFI_ERROR ( Status
)) {
629 // Update the configuration data
631 Status
= pUdp4Protocol
->GetModeData ( pUdp4Protocol
,
637 if ( EFI_ERROR ( Status
)) {
638 if ( !pSocket
->bConfigured
) {
639 DEBUG (( DEBUG_LISTEN
,
640 "ERROR - Failed to configure the Udp4 port, Status: %r\r\n",
643 case EFI_ACCESS_DENIED
:
644 pSocket
->errno
= EACCES
;
648 case EFI_DEVICE_ERROR
:
649 pSocket
->errno
= EIO
;
652 case EFI_INVALID_PARAMETER
:
653 pSocket
->errno
= EADDRNOTAVAIL
;
657 pSocket
->errno
= EAFNOSUPPORT
;
660 case EFI_OUT_OF_RESOURCES
:
661 pSocket
->errno
= ENOBUFS
;
664 case EFI_UNSUPPORTED
:
665 pSocket
->errno
= EOPNOTSUPP
;
672 "0x%08x: pPort Configured for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n",
674 pConfigData
->StationAddress
.Addr
[0],
675 pConfigData
->StationAddress
.Addr
[1],
676 pConfigData
->StationAddress
.Addr
[2],
677 pConfigData
->StationAddress
.Addr
[3],
678 pConfigData
->StationPort
,
679 pConfigData
->RemoteAddress
.Addr
[0],
680 pConfigData
->RemoteAddress
.Addr
[1],
681 pConfigData
->RemoteAddress
.Addr
[2],
682 pConfigData
->RemoteAddress
.Addr
[3],
683 pConfigData
->RemotePort
));
684 pPort
->bConfigured
= TRUE
;
685 pSocket
->bConfigured
= TRUE
;
688 // Start the first read on the port
690 EslSocketRxStart ( pPort
);
693 // The socket is connected
695 pSocket
->State
= SOCKET_STATE_CONNECTED
;
707 // Determine the socket configuration status
709 Status
= pSocket
->bConfigured
? EFI_SUCCESS
: EFI_NOT_STARTED
;
712 // Return the port connected state.
714 DBG_EXIT_STATUS ( Status
);
720 Buffer data for transmission over a network connection.
722 This routine buffers data for the transmit engine in the normal
723 data queue. When the \ref TransmitEngine has resources, this
724 routine will start the transmission of the next buffer on the
727 This routine is called by ::EslSocketTransmit to buffer
728 data for transmission. The data is copied into a local buffer
729 freeing the application buffer for reuse upon return. When
730 necessary, this routine starts the transmit engine that
731 performs the data transmission on the network connection. The
732 transmit engine transmits the data a packet at a time over the
735 Transmission errors are returned during the next transmission or
736 during the close operation. Only buffering errors are returned
737 during the current transmission attempt.
739 @param [in] pSocket Address of an ::ESL_SOCKET structure
741 @param [in] Flags Message control flags
743 @param [in] BufferLength Length of the the buffer
745 @param [in] pBuffer Address of a buffer to receive the data.
747 @param [in] pDataLength Number of received data bytes in the buffer.
749 @param [in] pAddress Network address of the remote system address
751 @param [in] AddressLength Length of the remote network address structure
753 @retval EFI_SUCCESS - Socket data successfully buffered
758 IN ESL_SOCKET
* pSocket
,
760 IN
size_t BufferLength
,
761 IN CONST UINT8
* pBuffer
,
762 OUT
size_t * pDataLength
,
763 IN
const struct sockaddr
* pAddress
,
764 IN socklen_t AddressLength
767 ESL_PACKET
* pPacket
;
768 ESL_PACKET
* pPreviousPacket
;
770 const struct sockaddr_in
* pRemoteAddress
;
771 ESL_UDP4_CONTEXT
* pUdp4
;
773 ESL_UDP4_TX_DATA
* pTxData
;
782 Status
= EFI_UNSUPPORTED
;
783 pSocket
->errno
= ENOTCONN
;
787 // Verify that the socket is connected
789 if ( SOCKET_STATE_CONNECTED
== pSocket
->State
) {
791 // Verify that there is enough room to buffer another
792 // transmit operation
794 pTxBytes
= &pSocket
->TxBytes
;
795 if ( pSocket
->MaxTxBuf
> *pTxBytes
) {
799 pPort
= pSocket
->pPortList
;
800 while ( NULL
!= pPort
) {
802 // Determine the queue head
804 pUdp4
= &pPort
->Context
.Udp4
;
807 // Attempt to allocate the packet
809 Status
= EslSocketPacketAllocate ( &pPacket
,
810 sizeof ( pPacket
->Op
.Udp4Tx
)
811 - sizeof ( pPacket
->Op
.Udp4Tx
.Buffer
)
815 if ( !EFI_ERROR ( Status
)) {
817 // Initialize the transmit operation
819 pTxData
= &pPacket
->Op
.Udp4Tx
;
820 pTxData
->TxData
.GatewayAddress
= NULL
;
821 pTxData
->TxData
.UdpSessionData
= NULL
;
822 pTxData
->TxData
.DataLength
= (UINT32
) BufferLength
;
823 pTxData
->TxData
.FragmentCount
= 1;
824 pTxData
->TxData
.FragmentTable
[0].FragmentLength
= (UINT32
) BufferLength
;
825 pTxData
->TxData
.FragmentTable
[0].FragmentBuffer
= &pPacket
->Op
.Udp4Tx
.Buffer
[0];
826 pTxData
->RetransmitCount
= 0;
829 // Set the remote system address if necessary
831 pTxData
->TxData
.UdpSessionData
= NULL
;
832 if ( NULL
!= pAddress
) {
833 pRemoteAddress
= (const struct sockaddr_in
*)pAddress
;
834 pTxData
->Session
.SourceAddress
.Addr
[0] = pUdp4
->ConfigData
.StationAddress
.Addr
[0];
835 pTxData
->Session
.SourceAddress
.Addr
[1] = pUdp4
->ConfigData
.StationAddress
.Addr
[1];
836 pTxData
->Session
.SourceAddress
.Addr
[2] = pUdp4
->ConfigData
.StationAddress
.Addr
[2];
837 pTxData
->Session
.SourceAddress
.Addr
[3] = pUdp4
->ConfigData
.StationAddress
.Addr
[3];
838 pTxData
->Session
.SourcePort
= 0;
839 pTxData
->Session
.DestinationAddress
.Addr
[0] = (UINT8
)pRemoteAddress
->sin_addr
.s_addr
;
840 pTxData
->Session
.DestinationAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
841 pTxData
->Session
.DestinationAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
842 pTxData
->Session
.DestinationAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
843 pTxData
->Session
.DestinationPort
= SwapBytes16 ( pRemoteAddress
->sin_port
);
846 // Use the remote system address when sending this packet
848 pTxData
->TxData
.UdpSessionData
= &pTxData
->Session
;
852 // Copy the data into the buffer
854 CopyMem ( &pPacket
->Op
.Udp4Tx
.Buffer
[0],
859 // Synchronize with the socket layer
861 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
864 // Display the request
867 "Send %d bytes from 0x%08x to %d.%d.%d.%d:%d\r\n",
870 pTxData
->Session
.DestinationAddress
.Addr
[0],
871 pTxData
->Session
.DestinationAddress
.Addr
[1],
872 pTxData
->Session
.DestinationAddress
.Addr
[2],
873 pTxData
->Session
.DestinationAddress
.Addr
[3],
874 pTxData
->Session
.DestinationPort
));
877 // Queue the data for transmission
879 pPacket
->pNext
= NULL
;
880 pPreviousPacket
= pSocket
->pTxPacketListTail
;
881 if ( NULL
== pPreviousPacket
) {
882 pSocket
->pTxPacketListHead
= pPacket
;
885 pPreviousPacket
->pNext
= pPacket
;
887 pSocket
->pTxPacketListTail
= pPacket
;
889 "0x%08x: Packet on transmit list\r\n",
893 // Account for the buffered data
895 *pTxBytes
+= BufferLength
;
896 *pDataLength
= BufferLength
;
899 // Start the transmit engine if it is idle
901 if ( NULL
!= pPort
->pTxFree
) {
902 pPacket
= pSocket
->pTxPacketListHead
;
903 EslSocketTxStart ( pPort
,
904 &pSocket
->pTxPacketListHead
,
905 &pSocket
->pTxPacketListTail
,
910 // Ignore any transmit error
912 if ( EFI_ERROR ( pSocket
->TxError
)) {
914 "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",
919 pSocket
->TxError
= EFI_SUCCESS
;
923 // Release the socket layer synchronization
925 RESTORE_TPL ( TplPrevious
);
929 // Packet allocation failed
931 pSocket
->errno
= ENOMEM
;
938 pPort
= pPort
->pLinkSocket
;
943 // Not enough buffer space available
945 pSocket
->errno
= EAGAIN
;
946 Status
= EFI_NOT_READY
;
951 // Return the operation status
953 DBG_EXIT_STATUS ( Status
);
959 Process the transmit completion
961 This routine use ::EslSocketTxComplete to perform the transmit
962 completion processing for data packets.
964 This routine is called by the UDPv4 network layer when a data
965 transmit request completes.
967 @param [in] Event The normal transmit completion event
969 @param [in] pIo Address of an ::ESL_IO_MGMT structure
978 UINT32 LengthInBytes
;
980 ESL_PACKET
* pPacket
;
981 ESL_SOCKET
* pSocket
;
987 // Locate the active transmit packet
989 pPacket
= pIo
->pPacket
;
991 pSocket
= pPort
->pSocket
;
994 // Get the transmit length and status
996 LengthInBytes
= pPacket
->Op
.Udp4Tx
.TxData
.DataLength
;
997 pSocket
->TxBytes
-= LengthInBytes
;
998 Status
= pIo
->Token
.Udp4Tx
.Status
;
1001 // Ignore the transmit error
1003 if ( EFI_ERROR ( Status
)) {
1005 "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",
1009 Status
= EFI_SUCCESS
;
1013 // Complete the transmit operation
1015 EslSocketTxComplete ( pIo
,
1019 &pSocket
->pTxPacketListHead
,
1020 &pSocket
->pTxPacketListTail
,
1028 Verify the adapter's IP address
1030 This support routine is called by EslSocketBindTest.
1032 @param [in] pPort Address of an ::ESL_PORT structure.
1033 @param [in] pConfigData Address of the configuration data
1035 @retval EFI_SUCCESS - The IP address is valid
1036 @retval EFI_NOT_STARTED - The IP address is invalid
1040 EslUdp4VerifyLocalIpAddress (
1041 IN ESL_PORT
* pPort
,
1042 IN EFI_UDP4_CONFIG_DATA
* pConfigData
1046 EFI_IP4_CONFIG2_INTERFACE_INFO
* pIfInfo
;
1047 EFI_IP4_CONFIG2_PROTOCOL
* pIpConfig2Protocol
;
1048 ESL_SERVICE
* pService
;
1054 // Use break instead of goto
1059 // Determine if the IP address is specified
1061 DEBUG (( DEBUG_BIND
,
1062 "UseDefaultAddress: %s\r\n",
1063 pConfigData
->UseDefaultAddress
? L
"TRUE" : L
"FALSE" ));
1064 DEBUG (( DEBUG_BIND
,
1065 "Requested IP address: %d.%d.%d.%d\r\n",
1066 pConfigData
->StationAddress
.Addr
[ 0 ],
1067 pConfigData
->StationAddress
.Addr
[ 1 ],
1068 pConfigData
->StationAddress
.Addr
[ 2 ],
1069 pConfigData
->StationAddress
.Addr
[ 3 ]));
1070 if ( pConfigData
->UseDefaultAddress
1071 || (( 0 == pConfigData
->StationAddress
.Addr
[ 0 ])
1072 && ( 0 == pConfigData
->StationAddress
.Addr
[ 1 ])
1073 && ( 0 == pConfigData
->StationAddress
.Addr
[ 2 ])
1074 && ( 0 == pConfigData
->StationAddress
.Addr
[ 3 ])))
1076 Status
= EFI_SUCCESS
;
1081 // Open the configuration protocol
1083 pService
= pPort
->pService
;
1084 Status
= gBS
->OpenProtocol (
1085 pService
->Controller
,
1086 &gEfiIp4Config2ProtocolGuid
,
1087 (VOID
**)&pIpConfig2Protocol
,
1090 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1092 if ( EFI_ERROR ( Status
)) {
1093 DEBUG (( DEBUG_ERROR
,
1094 "ERROR - IP Configuration Protocol not available, Status: %r\r\n",
1100 // Get the interface information size
1103 Status
= pIpConfig2Protocol
->GetData (
1105 Ip4Config2DataTypeInterfaceInfo
,
1109 if ( EFI_BUFFER_TOO_SMALL
!= Status
) {
1110 DEBUG (( DEBUG_ERROR
,
1111 "ERROR - Failed to get the interface information size, Status: %r\r\n",
1117 // Allocate the interface information buffer
1119 pIfInfo
= AllocatePool ( DataSize
);
1120 if ( NULL
== pIfInfo
) {
1121 DEBUG (( DEBUG_ERROR
,
1122 "ERROR - Not enough memory to allocate the interface information buffer!\r\n" ));
1123 Status
= EFI_OUT_OF_RESOURCES
;
1128 // Get the interface info.
1130 Status
= pIpConfig2Protocol
->GetData (
1132 Ip4Config2DataTypeInterfaceInfo
,
1136 if ( EFI_ERROR ( Status
)) {
1137 DEBUG (( DEBUG_ERROR
,
1138 "ERROR - Failed to return the interface info, Status: %r\r\n",
1144 // Display the current configuration
1146 DEBUG (( DEBUG_BIND
,
1147 "Actual adapter IP address: %d.%d.%d.%d\r\n",
1148 pIfInfo
->StationAddress
.Addr
[ 0 ],
1149 pIfInfo
->StationAddress
.Addr
[ 1 ],
1150 pIfInfo
->StationAddress
.Addr
[ 2 ],
1151 pIfInfo
->StationAddress
.Addr
[ 3 ]));
1154 // Assume the port is not configured
1156 Status
= EFI_SUCCESS
;
1157 if (( pConfigData
->StationAddress
.Addr
[ 0 ] == pIfInfo
->StationAddress
.Addr
[ 0 ])
1158 && ( pConfigData
->StationAddress
.Addr
[ 1 ] == pIfInfo
->StationAddress
.Addr
[ 1 ])
1159 && ( pConfigData
->StationAddress
.Addr
[ 2 ] == pIfInfo
->StationAddress
.Addr
[ 2 ])
1160 && ( pConfigData
->StationAddress
.Addr
[ 3 ] == pIfInfo
->StationAddress
.Addr
[ 3 ])) {
1165 // The IP address did not match
1167 Status
= EFI_NOT_STARTED
;
1172 // Free the buffer if necessary
1174 if ( NULL
!= pIfInfo
) {
1175 FreePool ( pIfInfo
);
1179 // Return the IP address status
1181 DBG_EXIT_STATUS ( Status
);
1187 Interface between the socket layer and the network specific
1188 code that supports SOCK_DGRAM sockets over UDPv4.
1190 CONST ESL_PROTOCOL_API cEslUdp4Api
= {
1193 OFFSET_OF ( ESL_PORT
, Context
.Udp4
.ConfigData
),
1194 OFFSET_OF ( ESL_LAYER
, pUdp4List
),
1195 OFFSET_OF ( struct sockaddr_in
, sin_zero
),
1196 sizeof ( struct sockaddr_in
),
1198 sizeof (((ESL_PACKET
*)0 )->Op
.Udp4Rx
),
1199 sizeof (((ESL_PACKET
*)0 )->Op
.Udp4Rx
),
1200 OFFSET_OF ( ESL_IO_MGMT
, Token
.Udp4Rx
.Packet
.RxData
),
1204 NULL
, // ConnectPoll
1205 NULL
, // ConnectStart
1206 EslUdp4SocketIsConfigured
,
1207 EslUdp4LocalAddressGet
,
1208 EslUdp4LocalAddressSet
,
1213 EslUdp4PortAllocate
,
1215 NULL
, // PortCloseOp
1218 EslUdp4RemoteAddressGet
,
1219 EslUdp4RemoteAddressSet
,
1224 NULL
, // TxOobComplete
1225 (PFN_API_VERIFY_LOCAL_IP_ADDRESS
)EslUdp4VerifyLocalIpAddress