2 Implement the UDP4 driver support for the socket layer.
4 Copyright (c) 2011, Intel Corporation. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
13 Get the local socket address
15 This routine returns the IPv6 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 EslUdp6LocalAddressGet (
29 OUT
struct sockaddr
* pSockAddr
32 struct sockaddr_in6
* pLocalAddress
;
33 ESL_UDP6_CONTEXT
* pUdp6
;
38 // Return the local address
40 pUdp6
= &pPort
->Context
.Udp6
;
41 pLocalAddress
= (struct sockaddr_in6
*)pSockAddr
;
42 pLocalAddress
->sin6_family
= AF_INET6
;
43 pLocalAddress
->sin6_port
= SwapBytes16 ( pUdp6
->ConfigData
.StationPort
);
44 CopyMem ( &pLocalAddress
->sin6_addr
,
45 &pUdp6
->ConfigData
.StationAddress
.Addr
[0],
46 sizeof ( pLocalAddress
->sin6_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 IPv6 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 IPv6 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 EslUdp6LocalAddressSet (
78 IN CONST
struct sockaddr
* pSockAddr
,
82 EFI_UDP6_CONFIG_DATA
* pConfig
;
83 CONST
struct sockaddr_in6
* pIpAddress
;
84 CONST UINT8
* pIPv6Address
;
90 // Set the local address
92 pIpAddress
= (struct sockaddr_in6
*)pSockAddr
;
93 pIPv6Address
= (UINT8
*)&pIpAddress
->sin6_addr
;
94 pConfig
= &pPort
->Context
.Udp6
.ConfigData
;
95 CopyMem ( &pConfig
->StationAddress
,
97 sizeof ( pConfig
->StationAddress
));
100 // Validate the IP address
102 pConfig
->StationPort
= 0;
103 Status
= bBindTest
? EslSocketBindTest ( pPort
, EADDRNOTAVAIL
)
105 if ( !EFI_ERROR ( Status
)) {
107 // Set the port number
109 pConfig
->StationPort
= SwapBytes16 ( pIpAddress
->sin6_port
);
110 pPort
->pSocket
->bAddressSet
= TRUE
;
113 // Display the local address
116 "0x%08x: Port, Local UDP6 Address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
118 pConfig
->StationAddress
.Addr
[0],
119 pConfig
->StationAddress
.Addr
[1],
120 pConfig
->StationAddress
.Addr
[2],
121 pConfig
->StationAddress
.Addr
[3],
122 pConfig
->StationAddress
.Addr
[4],
123 pConfig
->StationAddress
.Addr
[5],
124 pConfig
->StationAddress
.Addr
[6],
125 pConfig
->StationAddress
.Addr
[7],
126 pConfig
->StationAddress
.Addr
[8],
127 pConfig
->StationAddress
.Addr
[9],
128 pConfig
->StationAddress
.Addr
[10],
129 pConfig
->StationAddress
.Addr
[11],
130 pConfig
->StationAddress
.Addr
[12],
131 pConfig
->StationAddress
.Addr
[13],
132 pConfig
->StationAddress
.Addr
[14],
133 pConfig
->StationAddress
.Addr
[15],
134 pConfig
->StationPort
));
138 // Return the operation status
140 DBG_EXIT_STATUS ( Status
);
146 Free a receive packet
148 This routine performs the network specific operations necessary
149 to free a receive packet.
151 This routine is called by ::EslSocketPortCloseTxDone to free a
154 @param [in] pPacket Address of an ::ESL_PACKET structure.
155 @param [in, out] pRxBytes Address of the count of RX bytes
160 IN ESL_PACKET
* pPacket
,
161 IN OUT
size_t * pRxBytes
164 EFI_UDP6_RECEIVE_DATA
* pRxData
;
169 // Account for the receive bytes
171 pRxData
= pPacket
->Op
.Udp6Rx
.pRxData
;
172 *pRxBytes
-= pRxData
->DataLength
;
175 // Disconnect the buffer from the packet
177 pPacket
->Op
.Udp6Rx
.pRxData
= NULL
;
180 // Return the buffer to the UDP6 driver
182 gBS
->SignalEvent ( pRxData
->RecycleSignal
);
188 Initialize the network specific portions of an ::ESL_PORT structure.
190 This routine initializes the network specific portions of an
191 ::ESL_PORT structure for use by the socket.
193 This support routine is called by ::EslSocketPortAllocate
194 to connect the socket with the underlying network adapter
195 running the UDPv4 protocol.
197 @param [in] pPort Address of an ESL_PORT structure
198 @param [in] DebugFlags Flags for debug messages
200 @retval EFI_SUCCESS - Socket successfully created
204 EslUdp6PortAllocate (
209 EFI_UDP6_CONFIG_DATA
* pConfig
;
210 ESL_SOCKET
* pSocket
;
216 // Initialize the port
218 pSocket
= pPort
->pSocket
;
219 pSocket
->TxPacketOffset
= OFFSET_OF ( ESL_PACKET
, Op
.Udp6Tx
.TxData
);
220 pSocket
->TxTokenEventOffset
= OFFSET_OF ( ESL_IO_MGMT
, Token
.Udp6Tx
.Event
);
221 pSocket
->TxTokenOffset
= OFFSET_OF ( EFI_UDP6_COMPLETION_TOKEN
, Packet
.TxData
);
224 // Save the cancel, receive and transmit addresses
226 pPort
->pfnConfigure
= (PFN_NET_CONFIGURE
)pPort
->pProtocol
.UDPv6
->Configure
;
227 pPort
->pfnRxCancel
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv6
->Cancel
;
228 pPort
->pfnRxPoll
= (PFN_NET_POLL
)pPort
->pProtocol
.UDPv6
->Poll
;
229 pPort
->pfnRxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv6
->Receive
;
230 pPort
->pfnTxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv6
->Transmit
;
233 // Do not drop packets
235 pConfig
= &pPort
->Context
.Udp6
.ConfigData
;
236 pConfig
->ReceiveTimeout
= 0;
237 pConfig
->ReceiveTimeout
= pConfig
->ReceiveTimeout
;
240 // Set the configuration flags
242 pConfig
->AllowDuplicatePort
= TRUE
;
243 pConfig
->AcceptAnyPort
= FALSE
;
244 pConfig
->AcceptPromiscuous
= FALSE
;
245 pConfig
->HopLimit
= 255;
246 pConfig
->TrafficClass
= 0;
248 Status
= EFI_SUCCESS
;
251 // Return the operation status
253 DBG_EXIT_STATUS ( Status
);
259 Receive data from a network connection.
261 This routine attempts to return buffered data to the caller. The
262 data is removed from the urgent queue if the message flag MSG_OOB
263 is specified, otherwise data is removed from the normal queue.
264 See the \ref ReceiveEngine section.
266 This routine is called by ::EslSocketReceive to handle the network
267 specific receive operation to support SOCK_DGRAM sockets.
269 @param [in] pPort Address of an ::ESL_PORT structure.
271 @param [in] pPacket Address of an ::ESL_PACKET structure.
273 @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
275 @param [in] BufferLength Length of the the buffer
277 @param [in] pBuffer Address of a buffer to receive the data.
279 @param [in] pDataLength Number of received data bytes in the buffer.
281 @param [out] pAddress Network address to receive the remote system address
283 @param [out] pSkipBytes Address to receive the number of bytes skipped
285 @return Returns the address of the next free byte in the buffer.
291 IN ESL_PACKET
* pPacket
,
292 IN BOOLEAN
* pbConsumePacket
,
293 IN
size_t BufferLength
,
295 OUT
size_t * pDataLength
,
296 OUT
struct sockaddr
* pAddress
,
297 OUT
size_t * pSkipBytes
301 struct sockaddr_in6
* pRemoteAddress
;
302 EFI_UDP6_RECEIVE_DATA
* pRxData
;
306 pRxData
= pPacket
->Op
.Udp6Rx
.pRxData
;
308 // Return the remote system address if requested
310 if ( NULL
!= pAddress
) {
312 // Build the remote address
315 "Getting packet remote address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
316 pRxData
->UdpSession
.SourceAddress
.Addr
[0],
317 pRxData
->UdpSession
.SourceAddress
.Addr
[1],
318 pRxData
->UdpSession
.SourceAddress
.Addr
[2],
319 pRxData
->UdpSession
.SourceAddress
.Addr
[3],
320 pRxData
->UdpSession
.SourceAddress
.Addr
[4],
321 pRxData
->UdpSession
.SourceAddress
.Addr
[5],
322 pRxData
->UdpSession
.SourceAddress
.Addr
[6],
323 pRxData
->UdpSession
.SourceAddress
.Addr
[7],
324 pRxData
->UdpSession
.SourceAddress
.Addr
[8],
325 pRxData
->UdpSession
.SourceAddress
.Addr
[9],
326 pRxData
->UdpSession
.SourceAddress
.Addr
[10],
327 pRxData
->UdpSession
.SourceAddress
.Addr
[11],
328 pRxData
->UdpSession
.SourceAddress
.Addr
[12],
329 pRxData
->UdpSession
.SourceAddress
.Addr
[13],
330 pRxData
->UdpSession
.SourceAddress
.Addr
[14],
331 pRxData
->UdpSession
.SourceAddress
.Addr
[15],
332 pRxData
->UdpSession
.SourcePort
));
333 pRemoteAddress
= (struct sockaddr_in6
*)pAddress
;
334 CopyMem ( &pRemoteAddress
->sin6_addr
,
335 &pRxData
->UdpSession
.SourceAddress
.Addr
[0],
336 sizeof ( pRemoteAddress
->sin6_addr
));
337 pRemoteAddress
->sin6_port
= SwapBytes16 ( pRxData
->UdpSession
.SourcePort
);
341 // Copy the received data
343 pBuffer
= EslSocketCopyFragmentedBuffer ( pRxData
->FragmentCount
,
344 (EFI_IP4_FRAGMENT_DATA
*)&pRxData
->FragmentTable
[0],
350 // Determine if the data is being read
352 if ( *pbConsumePacket
) {
354 // Display for the bytes consumed
357 "0x%08x: Port account for 0x%08x bytes\r\n",
362 // Account for any discarded data
364 *pSkipBytes
= pRxData
->DataLength
- DataBytes
;
368 // Return the data length and the buffer address
370 *pDataLength
= DataBytes
;
371 DBG_EXIT_HEX ( pBuffer
);
377 Get the remote socket address
379 This routine returns the address of the remote connection point
380 associated with the SOCK_DGRAM socket.
382 This routine is called by ::EslSocketGetPeerAddress to detemine
383 the UDPv4 address and port number associated with the network adapter.
385 @param [in] pPort Address of an ::ESL_PORT structure.
387 @param [out] pAddress Network address to receive the remote system address
391 EslUdp6RemoteAddressGet (
393 OUT
struct sockaddr
* pAddress
396 struct sockaddr_in6
* pRemoteAddress
;
397 ESL_UDP6_CONTEXT
* pUdp6
;
402 // Return the remote address
404 pUdp6
= &pPort
->Context
.Udp6
;
405 pRemoteAddress
= (struct sockaddr_in6
*)pAddress
;
406 pRemoteAddress
->sin6_family
= AF_INET6
;
407 pRemoteAddress
->sin6_port
= SwapBytes16 ( pUdp6
->ConfigData
.RemotePort
);
408 CopyMem ( &pRemoteAddress
->sin6_addr
,
409 &pUdp6
->ConfigData
.RemoteAddress
.Addr
[0],
410 sizeof ( pRemoteAddress
->sin6_addr
));
417 Set the remote address
419 This routine sets the remote address in the port.
421 This routine is called by ::EslSocketConnect to specify the
422 remote network address.
424 @param [in] pPort Address of an ::ESL_PORT structure.
426 @param [in] pSockAddr Network address of the remote system.
428 @param [in] SockAddrLength Length in bytes of the network address.
430 @retval EFI_SUCCESS The operation was successful
434 EslUdp6RemoteAddressSet (
436 IN CONST
struct sockaddr
* pSockAddr
,
437 IN socklen_t SockAddrLength
440 CONST
struct sockaddr_in6
* pRemoteAddress
;
441 ESL_UDP6_CONTEXT
* pUdp6
;
447 // Set the remote address
449 pUdp6
= &pPort
->Context
.Udp6
;
450 pRemoteAddress
= (struct sockaddr_in6
*)pSockAddr
;
451 CopyMem ( &pUdp6
->ConfigData
.RemoteAddress
,
452 &pRemoteAddress
->sin6_addr
,
453 sizeof ( pUdp6
->ConfigData
.RemoteAddress
));
454 pUdp6
->ConfigData
.RemotePort
= SwapBytes16 ( pRemoteAddress
->sin6_port
);
455 Status
= EFI_SUCCESS
;
458 // Return the operation status
460 DBG_EXIT_STATUS ( Status
);
466 Process the receive completion
468 This routine keeps the UDPv4 driver's buffer and queues it in
469 in FIFO order to the data queue. The UDP6 driver's buffer will
470 be returned by either ::EslUdp6Receive or ::EslSocketPortCloseTxDone.
471 See the \ref ReceiveEngine section.
473 This routine is called by the UDPv4 driver when data is
476 @param [in] Event The receive completion event
478 @param [in] pIo Address of an ::ESL_IO_MGMT structure
487 size_t LengthInBytes
;
488 ESL_PACKET
* pPacket
;
489 EFI_UDP6_RECEIVE_DATA
* pRxData
;
495 // Get the operation status.
497 Status
= pIo
->Token
.Udp6Rx
.Status
;
500 // Get the packet length
502 pRxData
= pIo
->Token
.Udp6Rx
.Packet
.RxData
;
503 LengthInBytes
= pRxData
->DataLength
;
506 // +--------------------+ +-----------------------+
507 // | ESL_IO_MGMT | | Data Buffer |
508 // | | | (Driver owned) |
509 // | +---------------+ +-----------------------+
512 // | | | +-----------------------+
513 // | | RxData --> | EFI_UDP6_RECEIVE_DATA |
514 // +----+---------------+ | (Driver owned) |
515 // +-----------------------+
516 // +--------------------+ ^
519 // | +---------------+ .
520 // | | pRxData --> NULL .......
521 // +----+---------------+
524 // Save the data in the packet
526 pPacket
= pIo
->pPacket
;
527 pPacket
->Op
.Udp6Rx
.pRxData
= pRxData
;
530 // Complete this request
532 EslSocketRxComplete ( pIo
, Status
, LengthInBytes
, FALSE
);
538 Determine if the socket is configured.
540 This routine uses the flag ESL_SOCKET::bConfigured to determine
541 if the network layer's configuration routine has been called.
542 This routine calls the bind and configuration routines if they
543 were not already called. After the port is configured, the
544 \ref ReceiveEngine is started.
546 This routine is called by EslSocketIsConfigured to verify
547 that the socket is configured.
549 @param [in] pSocket Address of an ::ESL_SOCKET structure
551 @retval EFI_SUCCESS - The port is connected
552 @retval EFI_NOT_STARTED - The port is not connected
556 EslUdp6SocketIsConfigured (
557 IN ESL_SOCKET
* pSocket
560 EFI_UDP6_CONFIG_DATA
* pConfigData
;
562 ESL_PORT
* pNextPort
;
563 ESL_UDP6_CONTEXT
* pUdp6
;
564 EFI_UDP6_PROTOCOL
* pUdp6Protocol
;
566 struct sockaddr_in6 LocalAddress
;
573 Status
= EFI_SUCCESS
;
576 // Configure the port if necessary
578 if ( !pSocket
->bConfigured
) {
580 // Fill in the port list if necessary
582 pSocket
->errno
= ENETDOWN
;
583 if ( NULL
== pSocket
->pPortList
) {
584 ZeroMem ( &LocalAddress
, sizeof ( LocalAddress
));
585 LocalAddress
.sin6_len
= sizeof ( LocalAddress
);
586 LocalAddress
.sin6_family
= AF_INET6
;
587 Status
= EslSocketBind ( &pSocket
->SocketProtocol
,
588 (struct sockaddr
*)&LocalAddress
,
589 LocalAddress
.sin6_len
,
594 // Walk the port list
596 pPort
= pSocket
->pPortList
;
597 while ( NULL
!= pPort
) {
599 // Attempt to configure the port
601 pNextPort
= pPort
->pLinkSocket
;
602 pUdp6
= &pPort
->Context
.Udp6
;
603 pUdp6Protocol
= pPort
->pProtocol
.UDPv6
;
604 pConfigData
= &pUdp6
->ConfigData
;
606 "0x%08x: pPort Configuring for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> ",
608 pConfigData
->StationAddress
.Addr
[0],
609 pConfigData
->StationAddress
.Addr
[1],
610 pConfigData
->StationAddress
.Addr
[2],
611 pConfigData
->StationAddress
.Addr
[3],
612 pConfigData
->StationAddress
.Addr
[4],
613 pConfigData
->StationAddress
.Addr
[5],
614 pConfigData
->StationAddress
.Addr
[6],
615 pConfigData
->StationAddress
.Addr
[7],
616 pConfigData
->StationAddress
.Addr
[8],
617 pConfigData
->StationAddress
.Addr
[9],
618 pConfigData
->StationAddress
.Addr
[10],
619 pConfigData
->StationAddress
.Addr
[11],
620 pConfigData
->StationAddress
.Addr
[12],
621 pConfigData
->StationAddress
.Addr
[13],
622 pConfigData
->StationAddress
.Addr
[14],
623 pConfigData
->StationAddress
.Addr
[15],
624 pConfigData
->StationPort
));
626 "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
627 pConfigData
->RemoteAddress
.Addr
[0],
628 pConfigData
->RemoteAddress
.Addr
[1],
629 pConfigData
->RemoteAddress
.Addr
[2],
630 pConfigData
->RemoteAddress
.Addr
[3],
631 pConfigData
->RemoteAddress
.Addr
[4],
632 pConfigData
->RemoteAddress
.Addr
[5],
633 pConfigData
->RemoteAddress
.Addr
[6],
634 pConfigData
->RemoteAddress
.Addr
[7],
635 pConfigData
->RemoteAddress
.Addr
[8],
636 pConfigData
->RemoteAddress
.Addr
[9],
637 pConfigData
->RemoteAddress
.Addr
[10],
638 pConfigData
->RemoteAddress
.Addr
[11],
639 pConfigData
->RemoteAddress
.Addr
[12],
640 pConfigData
->RemoteAddress
.Addr
[13],
641 pConfigData
->RemoteAddress
.Addr
[14],
642 pConfigData
->RemoteAddress
.Addr
[15],
643 pConfigData
->RemotePort
));
644 Status
= pUdp6Protocol
->Configure ( pUdp6Protocol
,
646 if ( !EFI_ERROR ( Status
)) {
648 // Update the configuration data
650 Status
= pUdp6Protocol
->GetModeData ( pUdp6Protocol
,
656 if ( EFI_ERROR ( Status
)) {
657 if ( !pSocket
->bConfigured
) {
658 DEBUG (( DEBUG_LISTEN
,
659 "ERROR - Failed to configure the Udp6 port, Status: %r\r\n",
662 case EFI_ACCESS_DENIED
:
663 pSocket
->errno
= EACCES
;
667 case EFI_DEVICE_ERROR
:
668 pSocket
->errno
= EIO
;
671 case EFI_INVALID_PARAMETER
:
672 pSocket
->errno
= EADDRNOTAVAIL
;
676 pSocket
->errno
= EAFNOSUPPORT
;
679 case EFI_OUT_OF_RESOURCES
:
680 pSocket
->errno
= ENOBUFS
;
683 case EFI_UNSUPPORTED
:
684 pSocket
->errno
= EOPNOTSUPP
;
691 "0x%08x: pPort Configured for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> ",
693 pConfigData
->StationAddress
.Addr
[0],
694 pConfigData
->StationAddress
.Addr
[1],
695 pConfigData
->StationAddress
.Addr
[2],
696 pConfigData
->StationAddress
.Addr
[3],
697 pConfigData
->StationAddress
.Addr
[4],
698 pConfigData
->StationAddress
.Addr
[5],
699 pConfigData
->StationAddress
.Addr
[6],
700 pConfigData
->StationAddress
.Addr
[7],
701 pConfigData
->StationAddress
.Addr
[8],
702 pConfigData
->StationAddress
.Addr
[9],
703 pConfigData
->StationAddress
.Addr
[10],
704 pConfigData
->StationAddress
.Addr
[11],
705 pConfigData
->StationAddress
.Addr
[12],
706 pConfigData
->StationAddress
.Addr
[13],
707 pConfigData
->StationAddress
.Addr
[14],
708 pConfigData
->StationAddress
.Addr
[15],
709 pConfigData
->StationPort
));
711 "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
712 pConfigData
->RemoteAddress
.Addr
[0],
713 pConfigData
->RemoteAddress
.Addr
[1],
714 pConfigData
->RemoteAddress
.Addr
[2],
715 pConfigData
->RemoteAddress
.Addr
[3],
716 pConfigData
->RemoteAddress
.Addr
[4],
717 pConfigData
->RemoteAddress
.Addr
[5],
718 pConfigData
->RemoteAddress
.Addr
[6],
719 pConfigData
->RemoteAddress
.Addr
[7],
720 pConfigData
->RemoteAddress
.Addr
[8],
721 pConfigData
->RemoteAddress
.Addr
[9],
722 pConfigData
->RemoteAddress
.Addr
[10],
723 pConfigData
->RemoteAddress
.Addr
[11],
724 pConfigData
->RemoteAddress
.Addr
[12],
725 pConfigData
->RemoteAddress
.Addr
[13],
726 pConfigData
->RemoteAddress
.Addr
[14],
727 pConfigData
->RemoteAddress
.Addr
[15],
728 pConfigData
->RemotePort
));
729 pPort
->bConfigured
= TRUE
;
730 pSocket
->bConfigured
= TRUE
;
733 // Start the first read on the port
735 EslSocketRxStart ( pPort
);
738 // The socket is connected
740 pSocket
->State
= SOCKET_STATE_CONNECTED
;
752 // Determine the socket configuration status
754 Status
= pSocket
->bConfigured
? EFI_SUCCESS
: EFI_NOT_STARTED
;
757 // Return the port connected state.
759 DBG_EXIT_STATUS ( Status
);
765 Buffer data for transmission over a network connection.
767 This routine buffers data for the transmit engine in the normal
768 data queue. When the \ref TransmitEngine has resources, this
769 routine will start the transmission of the next buffer on the
772 This routine is called by ::EslSocketTransmit to buffer
773 data for transmission. The data is copied into a local buffer
774 freeing the application buffer for reuse upon return. When
775 necessary, this routine starts the transmit engine that
776 performs the data transmission on the network connection. The
777 transmit engine transmits the data a packet at a time over the
780 Transmission errors are returned during the next transmission or
781 during the close operation. Only buffering errors are returned
782 during the current transmission attempt.
784 @param [in] pSocket Address of an ::ESL_SOCKET structure
786 @param [in] Flags Message control flags
788 @param [in] BufferLength Length of the the buffer
790 @param [in] pBuffer Address of a buffer to receive the data.
792 @param [in] pDataLength Number of received data bytes in the buffer.
794 @param [in] pAddress Network address of the remote system address
796 @param [in] AddressLength Length of the remote network address structure
798 @retval EFI_SUCCESS - Socket data successfully buffered
803 IN ESL_SOCKET
* pSocket
,
805 IN
size_t BufferLength
,
806 IN CONST UINT8
* pBuffer
,
807 OUT
size_t * pDataLength
,
808 IN
const struct sockaddr
* pAddress
,
809 IN socklen_t AddressLength
812 ESL_PACKET
* pPacket
;
813 ESL_PACKET
* pPreviousPacket
;
815 const struct sockaddr_in6
* pRemoteAddress
;
816 ESL_UDP6_CONTEXT
* pUdp6
;
818 ESL_UDP6_TX_DATA
* pTxData
;
827 Status
= EFI_UNSUPPORTED
;
828 pSocket
->errno
= ENOTCONN
;
832 // Verify that the socket is connected
834 if ( SOCKET_STATE_CONNECTED
== pSocket
->State
) {
836 // Verify that there is enough room to buffer another
837 // transmit operation
839 pTxBytes
= &pSocket
->TxBytes
;
840 if ( pSocket
->MaxTxBuf
> *pTxBytes
) {
844 pPort
= pSocket
->pPortList
;
845 while ( NULL
!= pPort
) {
847 // Determine the queue head
849 pUdp6
= &pPort
->Context
.Udp6
;
852 // Attempt to allocate the packet
854 Status
= EslSocketPacketAllocate ( &pPacket
,
855 sizeof ( pPacket
->Op
.Udp6Tx
)
856 - sizeof ( pPacket
->Op
.Udp6Tx
.Buffer
)
860 if ( !EFI_ERROR ( Status
)) {
862 // Initialize the transmit operation
864 pTxData
= &pPacket
->Op
.Udp6Tx
;
865 pTxData
->TxData
.UdpSessionData
= NULL
;
866 pTxData
->TxData
.DataLength
= (UINT32
) BufferLength
;
867 pTxData
->TxData
.FragmentCount
= 1;
868 pTxData
->TxData
.FragmentTable
[0].FragmentLength
= (UINT32
) BufferLength
;
869 pTxData
->TxData
.FragmentTable
[0].FragmentBuffer
= &pPacket
->Op
.Udp6Tx
.Buffer
[0];
872 // Set the remote system address if necessary
874 pTxData
->TxData
.UdpSessionData
= NULL
;
875 if ( NULL
!= pAddress
) {
876 pRemoteAddress
= (const struct sockaddr_in6
*)pAddress
;
877 CopyMem ( &pTxData
->Session
.SourceAddress
,
878 &pUdp6
->ConfigData
.StationAddress
,
879 sizeof ( pTxData
->Session
.SourceAddress
));
880 pTxData
->Session
.SourcePort
= 0;
881 CopyMem ( &pTxData
->Session
.DestinationAddress
,
882 &pRemoteAddress
->sin6_addr
,
883 sizeof ( pTxData
->Session
.DestinationAddress
));
884 pTxData
->Session
.DestinationPort
= SwapBytes16 ( pRemoteAddress
->sin6_port
);
887 // Use the remote system address when sending this packet
889 pTxData
->TxData
.UdpSessionData
= &pTxData
->Session
;
893 // Copy the data into the buffer
895 CopyMem ( &pPacket
->Op
.Udp6Tx
.Buffer
[0],
900 // Synchronize with the socket layer
902 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
905 // Display the request
908 "Send %d bytes from 0x%08x to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
911 pTxData
->Session
.DestinationAddress
.Addr
[0],
912 pTxData
->Session
.DestinationAddress
.Addr
[1],
913 pTxData
->Session
.DestinationAddress
.Addr
[2],
914 pTxData
->Session
.DestinationAddress
.Addr
[3],
915 pTxData
->Session
.DestinationAddress
.Addr
[4],
916 pTxData
->Session
.DestinationAddress
.Addr
[5],
917 pTxData
->Session
.DestinationAddress
.Addr
[6],
918 pTxData
->Session
.DestinationAddress
.Addr
[7],
919 pTxData
->Session
.DestinationAddress
.Addr
[8],
920 pTxData
->Session
.DestinationAddress
.Addr
[9],
921 pTxData
->Session
.DestinationAddress
.Addr
[10],
922 pTxData
->Session
.DestinationAddress
.Addr
[11],
923 pTxData
->Session
.DestinationAddress
.Addr
[12],
924 pTxData
->Session
.DestinationAddress
.Addr
[13],
925 pTxData
->Session
.DestinationAddress
.Addr
[14],
926 pTxData
->Session
.DestinationAddress
.Addr
[15],
927 pTxData
->Session
.DestinationPort
));
930 // Queue the data for transmission
932 pPacket
->pNext
= NULL
;
933 pPreviousPacket
= pSocket
->pTxPacketListTail
;
934 if ( NULL
== pPreviousPacket
) {
935 pSocket
->pTxPacketListHead
= pPacket
;
938 pPreviousPacket
->pNext
= pPacket
;
940 pSocket
->pTxPacketListTail
= pPacket
;
942 "0x%08x: Packet on transmit list\r\n",
946 // Account for the buffered data
948 *pTxBytes
+= BufferLength
;
949 *pDataLength
= BufferLength
;
952 // Start the transmit engine if it is idle
954 if ( NULL
!= pPort
->pTxFree
) {
955 EslSocketTxStart ( pPort
,
956 &pSocket
->pTxPacketListHead
,
957 &pSocket
->pTxPacketListTail
,
962 // Ignore any transmit error
964 if ( EFI_ERROR ( pSocket
->TxError
)) {
966 "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",
971 pSocket
->TxError
= EFI_SUCCESS
;
975 // Release the socket layer synchronization
977 RESTORE_TPL ( TplPrevious
);
981 // Packet allocation failed
983 pSocket
->errno
= ENOMEM
;
990 pPort
= pPort
->pLinkSocket
;
995 // Not enough buffer space available
997 pSocket
->errno
= EAGAIN
;
998 Status
= EFI_NOT_READY
;
1003 // Return the operation status
1005 DBG_EXIT_STATUS ( Status
);
1011 Process the transmit completion
1013 This routine use ::EslSocketTxComplete to perform the transmit
1014 completion processing for data packets.
1016 This routine is called by the UDPv4 network layer when a data
1017 transmit request completes.
1019 @param [in] Event The normal transmit completion event
1021 @param [in] pIo Address of an ::ESL_IO_MGMT structure
1027 IN ESL_IO_MGMT
* pIo
1030 UINT32 LengthInBytes
;
1032 ESL_PACKET
* pPacket
;
1033 ESL_SOCKET
* pSocket
;
1039 // Locate the active transmit packet
1041 pPacket
= pIo
->pPacket
;
1043 pSocket
= pPort
->pSocket
;
1046 // Get the transmit length and status
1048 LengthInBytes
= pPacket
->Op
.Udp6Tx
.TxData
.DataLength
;
1049 pSocket
->TxBytes
-= LengthInBytes
;
1050 Status
= pIo
->Token
.Udp6Tx
.Status
;
1053 // Ignore the transmit error
1055 if ( EFI_ERROR ( Status
)) {
1057 "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",
1061 Status
= EFI_SUCCESS
;
1065 // Complete the transmit operation
1067 EslSocketTxComplete ( pIo
,
1071 &pSocket
->pTxPacketListHead
,
1072 &pSocket
->pTxPacketListTail
,
1080 Verify the adapter's IP address
1082 This support routine is called by EslSocketBindTest.
1084 @param [in] pPort Address of an ::ESL_PORT structure.
1085 @param [in] pConfigData Address of the configuration data
1087 @retval EFI_SUCCESS - The IP address is valid
1088 @retval EFI_NOT_STARTED - The IP address is invalid
1092 EslUdp6VerifyLocalIpAddress (
1093 IN ESL_PORT
* pPort
,
1094 IN EFI_UDP6_CONFIG_DATA
* pConfigData
1098 EFI_IP6_ADDRESS_INFO
* pAddressInfo
;
1100 EFI_IP6_CONFIG_INTERFACE_INFO
* pIpConfigData
;
1101 EFI_IP6_CONFIG_PROTOCOL
* pIpConfigProtocol
;
1102 ESL_SERVICE
* pService
;
1108 // Use break instead of goto
1110 pIpConfigData
= NULL
;
1113 // Determine if the IP address is specified
1115 DEBUG (( DEBUG_BIND
,
1116 "Requested IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
1117 pConfigData
->StationAddress
.Addr
[0],
1118 pConfigData
->StationAddress
.Addr
[1],
1119 pConfigData
->StationAddress
.Addr
[2],
1120 pConfigData
->StationAddress
.Addr
[3],
1121 pConfigData
->StationAddress
.Addr
[4],
1122 pConfigData
->StationAddress
.Addr
[5],
1123 pConfigData
->StationAddress
.Addr
[6],
1124 pConfigData
->StationAddress
.Addr
[7],
1125 pConfigData
->StationAddress
.Addr
[8],
1126 pConfigData
->StationAddress
.Addr
[9],
1127 pConfigData
->StationAddress
.Addr
[10],
1128 pConfigData
->StationAddress
.Addr
[11],
1129 pConfigData
->StationAddress
.Addr
[12],
1130 pConfigData
->StationAddress
.Addr
[13],
1131 pConfigData
->StationAddress
.Addr
[14],
1132 pConfigData
->StationAddress
.Addr
[15]));
1133 if (( 0 == pConfigData
->StationAddress
.Addr
[ 0 ])
1134 && ( 0 == pConfigData
->StationAddress
.Addr
[ 1 ])
1135 && ( 0 == pConfigData
->StationAddress
.Addr
[ 2 ])
1136 && ( 0 == pConfigData
->StationAddress
.Addr
[ 3 ])
1137 && ( 0 == pConfigData
->StationAddress
.Addr
[ 4 ])
1138 && ( 0 == pConfigData
->StationAddress
.Addr
[ 5 ])
1139 && ( 0 == pConfigData
->StationAddress
.Addr
[ 6 ])
1140 && ( 0 == pConfigData
->StationAddress
.Addr
[ 7 ])
1141 && ( 0 == pConfigData
->StationAddress
.Addr
[ 8 ])
1142 && ( 0 == pConfigData
->StationAddress
.Addr
[ 9 ])
1143 && ( 0 == pConfigData
->StationAddress
.Addr
[ 10 ])
1144 && ( 0 == pConfigData
->StationAddress
.Addr
[ 11 ])
1145 && ( 0 == pConfigData
->StationAddress
.Addr
[ 12 ])
1146 && ( 0 == pConfigData
->StationAddress
.Addr
[ 13 ])
1147 && ( 0 == pConfigData
->StationAddress
.Addr
[ 14 ])
1148 && ( 0 == pConfigData
->StationAddress
.Addr
[ 15 ]))
1150 Status
= EFI_SUCCESS
;
1155 // Open the configuration protocol
1157 pService
= pPort
->pService
;
1158 Status
= gBS
->OpenProtocol ( pService
->Controller
,
1159 &gEfiIp6ConfigProtocolGuid
,
1160 (VOID
**)&pIpConfigProtocol
,
1163 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
1164 if ( EFI_ERROR ( Status
)) {
1165 DEBUG (( DEBUG_ERROR
,
1166 "ERROR - IP Configuration Protocol not available, Status: %r\r\n",
1172 // Get the IP configuration data size
1175 Status
= pIpConfigProtocol
->GetData ( pIpConfigProtocol
,
1176 Ip6ConfigDataTypeInterfaceInfo
,
1179 if ( EFI_BUFFER_TOO_SMALL
!= Status
) {
1180 DEBUG (( DEBUG_ERROR
,
1181 "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",
1187 // Allocate the configuration data buffer
1189 pIpConfigData
= AllocatePool ( DataSize
);
1190 if ( NULL
== pIpConfigData
) {
1191 DEBUG (( DEBUG_ERROR
,
1192 "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));
1193 Status
= EFI_OUT_OF_RESOURCES
;
1198 // Get the IP configuration
1200 Status
= pIpConfigProtocol
->GetData ( pIpConfigProtocol
,
1201 Ip6ConfigDataTypeInterfaceInfo
,
1204 if ( EFI_ERROR ( Status
)) {
1205 DEBUG (( DEBUG_ERROR
,
1206 "ERROR - Failed to return IP Configuration data, Status: %r\r\n",
1212 // Display the current configuration
1214 DEBUG (( DEBUG_BIND
,
1215 "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
1216 pIpConfigData
->HwAddress
.Addr
[ 0 ],
1217 pIpConfigData
->HwAddress
.Addr
[ 1 ],
1218 pIpConfigData
->HwAddress
.Addr
[ 2 ],
1219 pIpConfigData
->HwAddress
.Addr
[ 3 ],
1220 pIpConfigData
->HwAddress
.Addr
[ 4 ],
1221 pIpConfigData
->HwAddress
.Addr
[ 5 ],
1222 pIpConfigData
->HwAddress
.Addr
[ 6 ],
1223 pIpConfigData
->HwAddress
.Addr
[ 7 ],
1224 pIpConfigData
->HwAddress
.Addr
[ 8 ],
1225 pIpConfigData
->HwAddress
.Addr
[ 9 ],
1226 pIpConfigData
->HwAddress
.Addr
[ 10 ],
1227 pIpConfigData
->HwAddress
.Addr
[ 11 ],
1228 pIpConfigData
->HwAddress
.Addr
[ 12 ],
1229 pIpConfigData
->HwAddress
.Addr
[ 13 ],
1230 pIpConfigData
->HwAddress
.Addr
[ 14 ],
1231 pIpConfigData
->HwAddress
.Addr
[ 15 ]));
1234 // Validate the hardware address
1236 Status
= EFI_SUCCESS
;
1237 if (( 16 == pIpConfigData
->HwAddressSize
)
1238 && ( pConfigData
->StationAddress
.Addr
[ 0 ] == pIpConfigData
->HwAddress
.Addr
[ 0 ])
1239 && ( pConfigData
->StationAddress
.Addr
[ 1 ] == pIpConfigData
->HwAddress
.Addr
[ 1 ])
1240 && ( pConfigData
->StationAddress
.Addr
[ 2 ] == pIpConfigData
->HwAddress
.Addr
[ 2 ])
1241 && ( pConfigData
->StationAddress
.Addr
[ 3 ] == pIpConfigData
->HwAddress
.Addr
[ 3 ])
1242 && ( pConfigData
->StationAddress
.Addr
[ 4 ] == pIpConfigData
->HwAddress
.Addr
[ 4 ])
1243 && ( pConfigData
->StationAddress
.Addr
[ 5 ] == pIpConfigData
->HwAddress
.Addr
[ 5 ])
1244 && ( pConfigData
->StationAddress
.Addr
[ 6 ] == pIpConfigData
->HwAddress
.Addr
[ 6 ])
1245 && ( pConfigData
->StationAddress
.Addr
[ 7 ] == pIpConfigData
->HwAddress
.Addr
[ 7 ])
1246 && ( pConfigData
->StationAddress
.Addr
[ 8 ] == pIpConfigData
->HwAddress
.Addr
[ 8 ])
1247 && ( pConfigData
->StationAddress
.Addr
[ 9 ] == pIpConfigData
->HwAddress
.Addr
[ 9 ])
1248 && ( pConfigData
->StationAddress
.Addr
[ 10 ] == pIpConfigData
->HwAddress
.Addr
[ 10 ])
1249 && ( pConfigData
->StationAddress
.Addr
[ 11 ] == pIpConfigData
->HwAddress
.Addr
[ 11 ])
1250 && ( pConfigData
->StationAddress
.Addr
[ 12 ] == pIpConfigData
->HwAddress
.Addr
[ 12 ])
1251 && ( pConfigData
->StationAddress
.Addr
[ 13 ] == pIpConfigData
->HwAddress
.Addr
[ 13 ])
1252 && ( pConfigData
->StationAddress
.Addr
[ 14 ] == pIpConfigData
->HwAddress
.Addr
[ 14 ])
1253 && ( pConfigData
->StationAddress
.Addr
[ 15 ] == pIpConfigData
->HwAddress
.Addr
[ 15 ])) {
1258 // Walk the list of other IP addresses assigned to this adapter
1260 for ( AddressCount
= 0; pIpConfigData
->AddressInfoCount
> AddressCount
; AddressCount
+= 1 ) {
1261 pAddressInfo
= &pIpConfigData
->AddressInfo
[ AddressCount
];
1264 // Display the IP address
1266 DEBUG (( DEBUG_BIND
,
1267 "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
1268 pAddressInfo
->Address
.Addr
[ 0 ],
1269 pAddressInfo
->Address
.Addr
[ 1 ],
1270 pAddressInfo
->Address
.Addr
[ 2 ],
1271 pAddressInfo
->Address
.Addr
[ 3 ],
1272 pAddressInfo
->Address
.Addr
[ 4 ],
1273 pAddressInfo
->Address
.Addr
[ 5 ],
1274 pAddressInfo
->Address
.Addr
[ 6 ],
1275 pAddressInfo
->Address
.Addr
[ 7 ],
1276 pAddressInfo
->Address
.Addr
[ 8 ],
1277 pAddressInfo
->Address
.Addr
[ 9 ],
1278 pAddressInfo
->Address
.Addr
[ 10 ],
1279 pAddressInfo
->Address
.Addr
[ 11 ],
1280 pAddressInfo
->Address
.Addr
[ 12 ],
1281 pAddressInfo
->Address
.Addr
[ 13 ],
1282 pAddressInfo
->Address
.Addr
[ 14 ],
1283 pAddressInfo
->Address
.Addr
[ 15 ]));
1286 // Validate the IP address
1288 if (( pConfigData
->StationAddress
.Addr
[ 0 ] == pAddressInfo
->Address
.Addr
[ 0 ])
1289 && ( pConfigData
->StationAddress
.Addr
[ 1 ] == pAddressInfo
->Address
.Addr
[ 1 ])
1290 && ( pConfigData
->StationAddress
.Addr
[ 2 ] == pAddressInfo
->Address
.Addr
[ 2 ])
1291 && ( pConfigData
->StationAddress
.Addr
[ 3 ] == pAddressInfo
->Address
.Addr
[ 3 ])
1292 && ( pConfigData
->StationAddress
.Addr
[ 4 ] == pAddressInfo
->Address
.Addr
[ 4 ])
1293 && ( pConfigData
->StationAddress
.Addr
[ 5 ] == pAddressInfo
->Address
.Addr
[ 5 ])
1294 && ( pConfigData
->StationAddress
.Addr
[ 6 ] == pAddressInfo
->Address
.Addr
[ 6 ])
1295 && ( pConfigData
->StationAddress
.Addr
[ 7 ] == pAddressInfo
->Address
.Addr
[ 7 ])
1296 && ( pConfigData
->StationAddress
.Addr
[ 8 ] == pAddressInfo
->Address
.Addr
[ 8 ])
1297 && ( pConfigData
->StationAddress
.Addr
[ 9 ] == pAddressInfo
->Address
.Addr
[ 9 ])
1298 && ( pConfigData
->StationAddress
.Addr
[ 10 ] == pAddressInfo
->Address
.Addr
[ 10 ])
1299 && ( pConfigData
->StationAddress
.Addr
[ 11 ] == pAddressInfo
->Address
.Addr
[ 11 ])
1300 && ( pConfigData
->StationAddress
.Addr
[ 12 ] == pAddressInfo
->Address
.Addr
[ 12 ])
1301 && ( pConfigData
->StationAddress
.Addr
[ 13 ] == pAddressInfo
->Address
.Addr
[ 13 ])
1302 && ( pConfigData
->StationAddress
.Addr
[ 14 ] == pAddressInfo
->Address
.Addr
[ 14 ])
1303 && ( pConfigData
->StationAddress
.Addr
[ 15 ] == pAddressInfo
->Address
.Addr
[ 15 ])) {
1307 if ( pIpConfigData
->AddressInfoCount
> AddressCount
) {
1312 // The IP address did not match
1314 Status
= EFI_NOT_STARTED
;
1319 // Free the buffer if necessary
1321 if ( NULL
!= pIpConfigData
) {
1322 FreePool ( pIpConfigData
);
1326 // Return the IP address status
1328 DBG_EXIT_STATUS ( Status
);
1334 Interface between the socket layer and the network specific
1335 code that supports SOCK_DGRAM sockets over UDPv4.
1337 CONST ESL_PROTOCOL_API cEslUdp6Api
= {
1340 OFFSET_OF ( ESL_PORT
, Context
.Udp6
.ConfigData
),
1341 OFFSET_OF ( ESL_LAYER
, pUdp6List
),
1342 sizeof ( struct sockaddr_in6
),
1343 sizeof ( struct sockaddr_in6
),
1345 sizeof (((ESL_PACKET
*)0 )->Op
.Udp6Rx
),
1346 sizeof (((ESL_PACKET
*)0 )->Op
.Udp6Rx
),
1347 OFFSET_OF ( ESL_IO_MGMT
, Token
.Udp6Rx
.Packet
.RxData
),
1351 NULL
, // ConnectPoll
1352 NULL
, // ConnectStart
1353 EslUdp6SocketIsConfigured
,
1354 EslUdp6LocalAddressGet
,
1355 EslUdp6LocalAddressSet
,
1360 EslUdp6PortAllocate
,
1362 NULL
, // PortCloseOp
1365 EslUdp6RemoteAddressGet
,
1366 EslUdp6RemoteAddressSet
,
1371 NULL
, // TxOobComplete
1372 (PFN_API_VERIFY_LOCAL_IP_ADDRESS
)EslUdp6VerifyLocalIpAddress