Ignore transmit errors for UDPv4, UDPv6 and IPv4.
Support local bind by validating the IP address using the IP configuration protocol.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Lee Leahy <leroy.p.leahy@intel.com>
Reviewed-by: Ankit Singh3 <Ankit_Singh3@Dell.com>



git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14875 6f19259b-4bc3-4df7-8a09-765794883524
diff --git a/StdLib/EfiSocketLib/EfiSocketLib.inf b/StdLib/EfiSocketLib/EfiSocketLib.inf
index 5e6ff59..a68e241 100644
--- a/StdLib/EfiSocketLib/EfiSocketLib.inf
+++ b/StdLib/EfiSocketLib/EfiSocketLib.inf
@@ -52,6 +52,8 @@
   UefiLib

 

 [Protocols]

+  gEfiIp4ConfigProtocolGuid

+  gEfiIp6ConfigProtocolGuid

   gEfiIp4ProtocolGuid

   gEfiIp4ServiceBindingProtocolGuid

   gEfiIp6ProtocolGuid

diff --git a/StdLib/EfiSocketLib/Ip4.c b/StdLib/EfiSocketLib/Ip4.c
index 2e832c7..1f7096e 100644
--- a/StdLib/EfiSocketLib/Ip4.c
+++ b/StdLib/EfiSocketLib/Ip4.c
@@ -1067,71 +1067,64 @@
           RAISE_TPL ( TplPrevious, TPL_SOCKETS );

 

           //

-          //  Stop transmission after an error

+          //  Display the request

           //

-          if ( !EFI_ERROR ( pSocket->TxError )) {

-            //

-            //  Display the request

-            //

-            DEBUG (( DEBUG_TX,

-                      "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n",

-                      BufferLength,

-                      pBuffer,

-                      pIp4->ModeData.ConfigData.StationAddress.Addr[0],

-                      pIp4->ModeData.ConfigData.StationAddress.Addr[1],

-                      pIp4->ModeData.ConfigData.StationAddress.Addr[2],

-                      pIp4->ModeData.ConfigData.StationAddress.Addr[3],

-                      pTxData->TxData.DestinationAddress.Addr[0],

-                      pTxData->TxData.DestinationAddress.Addr[1],

-                      pTxData->TxData.DestinationAddress.Addr[2],

-                      pTxData->TxData.DestinationAddress.Addr[3]));

+          DEBUG (( DEBUG_TX,

+                    "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n",

+                    BufferLength,

+                    pBuffer,

+                    pIp4->ModeData.ConfigData.StationAddress.Addr[0],

+                    pIp4->ModeData.ConfigData.StationAddress.Addr[1],

+                    pIp4->ModeData.ConfigData.StationAddress.Addr[2],

+                    pIp4->ModeData.ConfigData.StationAddress.Addr[3],

+                    pTxData->TxData.DestinationAddress.Addr[0],

+                    pTxData->TxData.DestinationAddress.Addr[1],

+                    pTxData->TxData.DestinationAddress.Addr[2],

+                    pTxData->TxData.DestinationAddress.Addr[3]));

 

-            //

-            //  Queue the data for transmission

-            //

-            pPacket->pNext = NULL;

-            pPreviousPacket = pSocket->pTxPacketListTail;

-            if ( NULL == pPreviousPacket ) {

-              pSocket->pTxPacketListHead = pPacket;

-            }

-            else {

-              pPreviousPacket->pNext = pPacket;

-            }

-            pSocket->pTxPacketListTail = pPacket;

-            DEBUG (( DEBUG_TX,

-                      "0x%08x: Packet on transmit list\r\n",

-                      pPacket ));

-

-            //

-            //  Account for the buffered data

-            //

-            *pTxBytes += BufferLength;

-            *pDataLength = BufferLength;

-

-            //

-            //  Start the transmit engine if it is idle

-            //

-            if ( NULL != pPort->pTxFree ) {

-              EslSocketTxStart ( pPort,

-                                 &pSocket->pTxPacketListHead,

-                                 &pSocket->pTxPacketListTail,

-                                 &pPort->pTxActive,

-                                 &pPort->pTxFree );

-            }

+          //

+          //  Queue the data for transmission

+          //

+          pPacket->pNext = NULL;

+          pPreviousPacket = pSocket->pTxPacketListTail;

+          if ( NULL == pPreviousPacket ) {

+            pSocket->pTxPacketListHead = pPacket;

           }

           else {

-            //

-            //  Previous transmit error

-            //  Stop transmission

-            //

-            Status = pSocket->TxError;

-            pSocket->errno = EIO;

+            pPreviousPacket->pNext = pPacket;

+          }

+          pSocket->pTxPacketListTail = pPacket;

+          DEBUG (( DEBUG_TX,

+                    "0x%08x: Packet on transmit list\r\n",

+                    pPacket ));

+

+          //

+          //  Account for the buffered data

+          //

+          *pTxBytes += BufferLength;

+          *pDataLength = BufferLength;

+

+          //

+          //  Start the transmit engine if it is idle

+          //

+          if ( NULL != pPort->pTxFree ) {

+            EslSocketTxStart ( pPort,

+                               &pSocket->pTxPacketListHead,

+                               &pSocket->pTxPacketListTail,

+                               &pPort->pTxActive,

+                               &pPort->pTxFree );

 

             //

-            //  Free the packet

+            //  Ignore any transmit error

             //

-            EslSocketPacketFree ( pPacket, DEBUG_TX );

-            break;

+            if ( EFI_ERROR ( pSocket->TxError )) {

+              DEBUG (( DEBUG_TX,

+                       "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",

+                       pPort,

+                       pPacket,

+                       pSocket->TxError ));

+            }

+            pSocket->TxError = EFI_SUCCESS;

           }

 

           //

@@ -1213,6 +1206,18 @@
   Status = pIo->Token.Ip4Tx.Status;

 

   //

+  //  Ignore the transmit error

+  //

+  if ( EFI_ERROR ( Status )) {

+    DEBUG (( DEBUG_TX,

+             "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",

+             pPort,

+             pPacket,

+             Status ));

+    Status = EFI_SUCCESS;

+  }

+

+  //

   //  Complete the transmit operation

   //

   EslSocketTxComplete ( pIo,

@@ -1228,6 +1233,157 @@
 

 

 /**

+  Verify the adapter's IP address

+

+  This support routine is called by EslSocketBindTest.

+

+  @param [in] pPort       Address of an ::ESL_PORT structure.

+  @param [in] pConfigData Address of the configuration data

+

+  @retval EFI_SUCCESS - The IP address is valid

+  @retval EFI_NOT_STARTED - The IP address is invalid

+

+ **/

+EFI_STATUS

+EslIp4VerifyLocalIpAddress (

+  IN ESL_PORT * pPort,

+  IN EFI_IP4_CONFIG_DATA * pConfigData

+  )

+{

+  UINTN DataSize;

+  EFI_IP4_IPCONFIG_DATA * pIpConfigData;

+  EFI_IP4_CONFIG_PROTOCOL * pIpConfigProtocol;

+  ESL_SERVICE * pService;

+  EFI_STATUS Status;

+

+  DBG_ENTER ( );

+

+  //

+  //  Use break instead of goto

+  //

+  pIpConfigData = NULL;

+  for ( ; ; ) {

+    //

+    //  Determine if the IP address is specified

+    //

+    DEBUG (( DEBUG_BIND,

+              "UseDefaultAddress: %s\r\n",

+              pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" ));

+    DEBUG (( DEBUG_BIND,

+              "Requested IP address: %d.%d.%d.%d\r\n",

+              pConfigData->StationAddress.Addr [ 0 ],

+              pConfigData->StationAddress.Addr [ 1 ],

+              pConfigData->StationAddress.Addr [ 2 ],

+              pConfigData->StationAddress.Addr [ 3 ]));

+    if ( pConfigData->UseDefaultAddress

+      || (( 0 == pConfigData->StationAddress.Addr [ 0 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 1 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 2 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 3 ])))

+    {

+      Status = EFI_SUCCESS;

+      break;

+    }

+

+    //

+    //  Open the configuration protocol

+    //

+    pService = pPort->pService;

+    Status = gBS->OpenProtocol ( pService->Controller,

+                                 &gEfiIp4ConfigProtocolGuid,

+                                 (VOID **)&pIpConfigProtocol,

+                                 NULL,

+                                 NULL,

+                                 EFI_OPEN_PROTOCOL_GET_PROTOCOL );

+    if ( EFI_ERROR ( Status )) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - IP Configuration Protocol not available, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Get the IP configuration data size

+    //

+    DataSize = 0;

+    Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,

+                                          &DataSize,

+                                          NULL );

+    if ( EFI_BUFFER_TOO_SMALL != Status ) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Allocate the configuration data buffer

+    //

+    pIpConfigData = AllocatePool ( DataSize );

+    if ( NULL == pIpConfigData ) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));

+      Status = EFI_OUT_OF_RESOURCES;

+      break;

+    }

+

+    //

+    //  Get the IP configuration

+    //

+    Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,

+                                          &DataSize,

+                                          pIpConfigData );

+    if ( EFI_ERROR ( Status )) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Failed to return IP Configuration data, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Display the current configuration

+    //

+    DEBUG (( DEBUG_BIND,

+              "Actual adapter IP address: %d.%d.%d.%d\r\n",

+              pIpConfigData->StationAddress.Addr [ 0 ],

+              pIpConfigData->StationAddress.Addr [ 1 ],

+              pIpConfigData->StationAddress.Addr [ 2 ],

+              pIpConfigData->StationAddress.Addr [ 3 ]));

+

+    //

+    //  Assume the port is not configured

+    //

+    Status = EFI_SUCCESS;

+    if (( pConfigData->StationAddress.Addr [ 0 ] == pIpConfigData->StationAddress.Addr [ 0 ])

+      && ( pConfigData->StationAddress.Addr [ 1 ] == pIpConfigData->StationAddress.Addr [ 1 ])

+      && ( pConfigData->StationAddress.Addr [ 2 ] == pIpConfigData->StationAddress.Addr [ 2 ])

+      && ( pConfigData->StationAddress.Addr [ 3 ] == pIpConfigData->StationAddress.Addr [ 3 ])) {

+      break;

+    }

+

+    //

+    //  The IP address did not match

+    //

+    Status = EFI_NOT_STARTED;

+    break;

+  }

+

+  //

+  //  Free the buffer if necessary

+  //

+  if ( NULL != pIpConfigData ) {

+    FreePool ( pIpConfigData );

+  }

+

+  //

+  //  Return the IP address status

+  //

+  DBG_EXIT_STATUS ( Status );

+  return Status;

+}

+

+

+/**

   Interface between the socket layer and the network specific

   code that supports SOCK_RAW sockets over IPv4.

 **/

@@ -1265,5 +1421,6 @@
   NULL,   //  RxStart

   EslIp4TxBuffer,

   EslIp4TxComplete,

-  NULL    //  TxOobComplete

+  NULL,   //  TxOobComplete

+  EslIp4VerifyLocalIpAddress

 };

diff --git a/StdLib/EfiSocketLib/Socket.c b/StdLib/EfiSocketLib/Socket.c
index a74dcd0..b801195 100644
--- a/StdLib/EfiSocketLib/Socket.c
+++ b/StdLib/EfiSocketLib/Socket.c
@@ -1336,27 +1336,40 @@
   pConfigData = (VOID *)pBuffer;

 

   //

-  //  Attempt to use this configuration

+  //  Validate that the port is connected

   //

-  Status = pPort->pfnConfigure ( pPort->pProtocol.v, pConfigData );

+  Status = pPort->pSocket->pApi->pfnVerifyLocalIpAddress ( pPort, pBuffer );

   if ( EFI_ERROR ( Status )) {

     DEBUG (( DEBUG_WARN | DEBUG_BIND,

-              "WARNING - Port 0x%08x failed configuration, Status: %r\r\n",

+              "WARNING - Port 0x%08x invalid IP address: %r\r\n",

               pPort,

               Status ));

     pPort->pSocket->errno = ErrnoValue;

   }

   else {

     //

-    //  Reset the port

+    //  Attempt to use this configuration

     //

-    Status = pPort->pfnConfigure ( pPort->pProtocol.v, NULL );

+    Status = pPort->pfnConfigure ( pPort->pProtocol.v, pConfigData );

     if ( EFI_ERROR ( Status )) {

-      DEBUG (( DEBUG_ERROR | DEBUG_BIND,

-                "ERROR - Port 0x%08x failed configuration reset, Status: %r\r\n",

+      DEBUG (( DEBUG_WARN | DEBUG_BIND,

+                "WARNING - Port 0x%08x failed configuration, Status: %r\r\n",

                 pPort,

                 Status ));

-      ASSERT ( EFI_SUCCESS == Status );

+      pPort->pSocket->errno = ErrnoValue;

+    }

+    else {

+      //

+      //  Reset the port

+      //

+      Status = pPort->pfnConfigure ( pPort->pProtocol.v, NULL );

+      if ( EFI_ERROR ( Status )) {

+        DEBUG (( DEBUG_ERROR | DEBUG_BIND,

+                  "ERROR - Port 0x%08x failed configuration reset, Status: %r\r\n",

+                  pPort,

+                  Status ));

+        ASSERT ( EFI_SUCCESS == Status );

+      }

     }

   }

 

@@ -5924,11 +5937,25 @@
       *ppActive = pIo;

     }

     else {

+      //

+      //  Display the transmit error

+      //

+      DEBUG (( DEBUG_TX | DEBUG_INFO,

+                "0x%08x, 0x%08x: pIo, pPacket transmit failure: %r\r\n",

+                pIo,

+                pPacket,

+                Status ));

       if ( EFI_SUCCESS == pSocket->TxError ) {

         pSocket->TxError = Status;

       }

 

       //

+      //  Free the IO structure

+      //

+      pIo->pNext = *ppFree;

+      *ppFree = pIo;

+

+      //

       //  Discard the transmit buffer

       //

       EslSocketPacketFree ( pPacket, DEBUG_TX );

diff --git a/StdLib/EfiSocketLib/Socket.h b/StdLib/EfiSocketLib/Socket.h
index b38bec6..583be1f 100644
--- a/StdLib/EfiSocketLib/Socket.h
+++ b/StdLib/EfiSocketLib/Socket.h
@@ -921,6 +921,25 @@
   );

 

 /**

+  Verify the adapter's IP address

+

+  This support routine is called by EslSocketBindTest.

+

+  @param [in] pPort       Address of an ::ESL_PORT structure.

+  @param [in] pConfigData Address of the configuration data

+

+  @retval EFI_SUCCESS - The IP address is valid

+  @retval EFI_NOT_STARTED - The IP address is invalid

+

+ **/

+typedef

+EFI_STATUS

+(* PFN_API_VERIFY_LOCAL_IP_ADDRESS) (

+  IN ESL_PORT * pPort,

+  IN VOID * pConfigData

+  );

+

+/**

   Socket type control structure

 

   This driver uses this structure to define the API for the socket type.

@@ -960,6 +979,7 @@
   PFN_API_TRANSMIT pfnTransmit;             ///<  Attempt to buffer a packet for transmit

   PFN_API_TX_COMPLETE pfnTxComplete;        ///<  TX completion for normal data

   PFN_API_TX_COMPLETE pfnTxOobComplete;     ///<  TX completion for urgent data

+  PFN_API_VERIFY_LOCAL_IP_ADDRESS pfnVerifyLocalIpAddress;  ///< Verify the local IP address

 } ESL_PROTOCOL_API;

 

 

diff --git a/StdLib/EfiSocketLib/Tcp4.c b/StdLib/EfiSocketLib/Tcp4.c
index 34e60e2..1e1d62a 100644
--- a/StdLib/EfiSocketLib/Tcp4.c
+++ b/StdLib/EfiSocketLib/Tcp4.c
@@ -2226,6 +2226,159 @@
 

 

 /**

+  Verify the adapter's IP address

+

+  This support routine is called by EslSocketBindTest.

+

+  @param [in] pPort       Address of an ::ESL_PORT structure.

+  @param [in] pConfigData Address of the configuration data

+

+  @retval EFI_SUCCESS - The IP address is valid

+  @retval EFI_NOT_STARTED - The IP address is invalid

+

+ **/

+EFI_STATUS

+EslTcp4VerifyLocalIpAddress (

+  IN ESL_PORT * pPort,

+  IN EFI_TCP4_CONFIG_DATA * pConfigData

+  )

+{

+  UINTN DataSize;

+  EFI_TCP4_ACCESS_POINT * pAccess;

+  EFI_IP4_IPCONFIG_DATA * pIpConfigData;

+  EFI_IP4_CONFIG_PROTOCOL * pIpConfigProtocol;

+  ESL_SERVICE * pService;

+  EFI_STATUS Status;

+

+  DBG_ENTER ( );

+

+  //

+  //  Use break instead of goto

+  //

+  pIpConfigData = NULL;

+  for ( ; ; ) {

+    //

+    //  Determine if the IP address is specified

+    //

+    pAccess = &pConfigData->AccessPoint;

+    DEBUG (( DEBUG_BIND,

+              "UseDefaultAddress: %s\r\n",

+              pAccess->UseDefaultAddress ? L"TRUE" : L"FALSE" ));

+    DEBUG (( DEBUG_BIND,

+              "Requested IP address: %d.%d.%d.%d\r\n",

+              pAccess->StationAddress.Addr [ 0 ],

+              pAccess->StationAddress.Addr [ 1 ],

+              pAccess->StationAddress.Addr [ 2 ],

+              pAccess->StationAddress.Addr [ 3 ]));

+    if ( pAccess->UseDefaultAddress

+      || (( 0 == pAccess->StationAddress.Addr [ 0 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 1 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 2 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 3 ])))

+    {

+      Status = EFI_SUCCESS;

+      break;

+    }

+

+    //

+    //  Open the configuration protocol

+    //

+    pService = pPort->pService;

+    Status = gBS->OpenProtocol ( pService->Controller,

+                                 &gEfiIp4ConfigProtocolGuid,

+                                 (VOID **)&pIpConfigProtocol,

+                                 NULL,

+                                 NULL,

+                                 EFI_OPEN_PROTOCOL_GET_PROTOCOL );

+    if ( EFI_ERROR ( Status )) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - IP Configuration Protocol not available, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Get the IP configuration data size

+    //

+    DataSize = 0;

+    Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,

+                                          &DataSize,

+                                          NULL );

+    if ( EFI_BUFFER_TOO_SMALL != Status ) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Allocate the configuration data buffer

+    //

+    pIpConfigData = AllocatePool ( DataSize );

+    if ( NULL == pIpConfigData ) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));

+      Status = EFI_OUT_OF_RESOURCES;

+      break;

+    }

+

+    //

+    //  Get the IP configuration

+    //

+    Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,

+                                          &DataSize,

+                                          pIpConfigData );

+    if ( EFI_ERROR ( Status )) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Failed to return IP Configuration data, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Display the current configuration

+    //

+    DEBUG (( DEBUG_BIND,

+              "Actual adapter IP address: %d.%d.%d.%d\r\n",

+              pIpConfigData->StationAddress.Addr [ 0 ],

+              pIpConfigData->StationAddress.Addr [ 1 ],

+              pIpConfigData->StationAddress.Addr [ 2 ],

+              pIpConfigData->StationAddress.Addr [ 3 ]));

+

+    //

+    //  Assume the port is not configured

+    //

+    Status = EFI_SUCCESS;

+    if (( pAccess->StationAddress.Addr [ 0 ] == pIpConfigData->StationAddress.Addr [ 0 ])

+      && ( pAccess->StationAddress.Addr [ 1 ] == pIpConfigData->StationAddress.Addr [ 1 ])

+      && ( pAccess->StationAddress.Addr [ 2 ] == pIpConfigData->StationAddress.Addr [ 2 ])

+      && ( pAccess->StationAddress.Addr [ 3 ] == pIpConfigData->StationAddress.Addr [ 3 ])) {

+      break;

+    }

+

+    //

+    //  The IP address did not match

+    //

+    Status = EFI_NOT_STARTED;

+    break;

+  }

+

+  //

+  //  Free the buffer if necessary

+  //

+  if ( NULL != pIpConfigData ) {

+    FreePool ( pIpConfigData );

+  }

+

+  //

+  //  Return the IP address status

+  //

+  DBG_EXIT_STATUS ( Status );

+  return Status;

+}

+

+

+/**

   Interface between the socket layer and the network specific

   code that supports SOCK_STREAM and SOCK_SEQPACKET sockets

   over TCPv4.

@@ -2264,5 +2417,6 @@
   EslTcp4RxStart,

   EslTcp4TxBuffer,

   EslTcp4TxComplete,

-  EslTcp4TxOobComplete

+  EslTcp4TxOobComplete,

+  EslTcp4VerifyLocalIpAddress

 };

diff --git a/StdLib/EfiSocketLib/Tcp6.c b/StdLib/EfiSocketLib/Tcp6.c
index df70a94..d68cb76 100644
--- a/StdLib/EfiSocketLib/Tcp6.c
+++ b/StdLib/EfiSocketLib/Tcp6.c
@@ -2295,6 +2295,262 @@
 

 

 /**

+  Verify the adapter's IP address

+

+  This support routine is called by EslSocketBindTest.

+

+  @param [in] pPort       Address of an ::ESL_PORT structure.

+  @param [in] pConfigData Address of the configuration data

+

+  @retval EFI_SUCCESS - The IP address is valid

+  @retval EFI_NOT_STARTED - The IP address is invalid

+

+ **/

+EFI_STATUS

+EslTcp6VerifyLocalIpAddress (

+  IN ESL_PORT * pPort,

+  IN EFI_TCP6_CONFIG_DATA * pConfigData

+  )

+{

+  UINTN AddressCount;

+  EFI_IP6_ADDRESS_INFO * pAddressInfo;

+  UINTN DataSize;

+  EFI_TCP6_ACCESS_POINT * pAccess;

+  EFI_IP6_CONFIG_INTERFACE_INFO * pIpConfigData;

+  EFI_IP6_CONFIG_PROTOCOL * pIpConfigProtocol;

+  ESL_SERVICE * pService;

+  EFI_STATUS Status;

+

+  DBG_ENTER ( );

+

+  //

+  //  Use break instead of goto

+  //

+  pIpConfigData = NULL;

+  for ( ; ; ) {

+    //

+    //  Determine if the IP address is specified

+    //

+    pAccess = &pConfigData->AccessPoint;

+    DEBUG (( DEBUG_BIND,

+              "Requested IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",

+              pAccess->StationAddress.Addr[0],

+              pAccess->StationAddress.Addr[1],

+              pAccess->StationAddress.Addr[2],

+              pAccess->StationAddress.Addr[3],

+              pAccess->StationAddress.Addr[4],

+              pAccess->StationAddress.Addr[5],

+              pAccess->StationAddress.Addr[6],

+              pAccess->StationAddress.Addr[7],

+              pAccess->StationAddress.Addr[8],

+              pAccess->StationAddress.Addr[9],

+              pAccess->StationAddress.Addr[10],

+              pAccess->StationAddress.Addr[11],

+              pAccess->StationAddress.Addr[12],

+              pAccess->StationAddress.Addr[13],

+              pAccess->StationAddress.Addr[14],

+              pAccess->StationAddress.Addr[15]));

+    if (( 0 == pAccess->StationAddress.Addr [ 0 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 1 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 2 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 3 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 4 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 5 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 6 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 7 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 8 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 9 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 10 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 11 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 12 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 13 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 14 ])

+      && ( 0 == pAccess->StationAddress.Addr [ 15 ]))

+    {

+      Status = EFI_SUCCESS;

+      break;

+    }

+

+    //

+    //  Open the configuration protocol

+    //

+    pService = pPort->pService;

+    Status = gBS->OpenProtocol ( pService->Controller,

+                                 &gEfiIp6ConfigProtocolGuid,

+                                 (VOID **)&pIpConfigProtocol,

+                                 NULL,

+                                 NULL,

+                                 EFI_OPEN_PROTOCOL_GET_PROTOCOL );

+    if ( EFI_ERROR ( Status )) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - IP Configuration Protocol not available, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Get the IP configuration data size

+    //

+    DataSize = 0;

+    Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,

+                                          Ip6ConfigDataTypeInterfaceInfo,

+                                          &DataSize,

+                                          NULL );

+    if ( EFI_BUFFER_TOO_SMALL != Status ) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Allocate the configuration data buffer

+    //

+    pIpConfigData = AllocatePool ( DataSize );

+    if ( NULL == pIpConfigData ) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));

+      Status = EFI_OUT_OF_RESOURCES;

+      break;

+    }

+

+    //

+    //  Get the IP configuration

+    //

+    Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,

+                                          Ip6ConfigDataTypeInterfaceInfo,

+                                          &DataSize,

+                                          pIpConfigData );

+    if ( EFI_ERROR ( Status )) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Failed to return IP Configuration data, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Display the current configuration

+    //

+    DEBUG (( DEBUG_BIND,

+              "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",

+              pIpConfigData->HwAddress.Addr [ 0 ],

+              pIpConfigData->HwAddress.Addr [ 1 ],

+              pIpConfigData->HwAddress.Addr [ 2 ],

+              pIpConfigData->HwAddress.Addr [ 3 ],

+              pIpConfigData->HwAddress.Addr [ 4 ],

+              pIpConfigData->HwAddress.Addr [ 5 ],

+              pIpConfigData->HwAddress.Addr [ 6 ],

+              pIpConfigData->HwAddress.Addr [ 7 ],

+              pIpConfigData->HwAddress.Addr [ 8 ],

+              pIpConfigData->HwAddress.Addr [ 9 ],

+              pIpConfigData->HwAddress.Addr [ 10 ],

+              pIpConfigData->HwAddress.Addr [ 11 ],

+              pIpConfigData->HwAddress.Addr [ 12 ],

+              pIpConfigData->HwAddress.Addr [ 13 ],

+              pIpConfigData->HwAddress.Addr [ 14 ],

+              pIpConfigData->HwAddress.Addr [ 15 ]));

+

+    //

+    //  Validate the hardware address

+    //

+    Status = EFI_SUCCESS;

+    if (( 16 == pIpConfigData->HwAddressSize )

+      && ( pAccess->StationAddress.Addr [ 0 ] == pIpConfigData->HwAddress.Addr [ 0 ])

+      && ( pAccess->StationAddress.Addr [ 1 ] == pIpConfigData->HwAddress.Addr [ 1 ])

+      && ( pAccess->StationAddress.Addr [ 2 ] == pIpConfigData->HwAddress.Addr [ 2 ])

+      && ( pAccess->StationAddress.Addr [ 3 ] == pIpConfigData->HwAddress.Addr [ 3 ])

+      && ( pAccess->StationAddress.Addr [ 4 ] == pIpConfigData->HwAddress.Addr [ 4 ])

+      && ( pAccess->StationAddress.Addr [ 5 ] == pIpConfigData->HwAddress.Addr [ 5 ])

+      && ( pAccess->StationAddress.Addr [ 6 ] == pIpConfigData->HwAddress.Addr [ 6 ])

+      && ( pAccess->StationAddress.Addr [ 7 ] == pIpConfigData->HwAddress.Addr [ 7 ])

+      && ( pAccess->StationAddress.Addr [ 8 ] == pIpConfigData->HwAddress.Addr [ 8 ])

+      && ( pAccess->StationAddress.Addr [ 9 ] == pIpConfigData->HwAddress.Addr [ 9 ])

+      && ( pAccess->StationAddress.Addr [ 10 ] == pIpConfigData->HwAddress.Addr [ 10 ])

+      && ( pAccess->StationAddress.Addr [ 11 ] == pIpConfigData->HwAddress.Addr [ 11 ])

+      && ( pAccess->StationAddress.Addr [ 12 ] == pIpConfigData->HwAddress.Addr [ 12 ])

+      && ( pAccess->StationAddress.Addr [ 13 ] == pIpConfigData->HwAddress.Addr [ 13 ])

+      && ( pAccess->StationAddress.Addr [ 14 ] == pIpConfigData->HwAddress.Addr [ 14 ])

+      && ( pAccess->StationAddress.Addr [ 15 ] == pIpConfigData->HwAddress.Addr [ 15 ])) {

+      break;

+    }

+

+    //

+    //  Walk the list of other IP addresses assigned to this adapter

+    //

+    for ( AddressCount = 0; pIpConfigData->AddressInfoCount > AddressCount; AddressCount += 1 ) {

+      pAddressInfo = &pIpConfigData->AddressInfo [ AddressCount ];

+

+      //

+      //  Display the IP address

+      //

+      DEBUG (( DEBUG_BIND,

+                "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",

+                pAddressInfo->Address.Addr [ 0 ],

+                pAddressInfo->Address.Addr [ 1 ],

+                pAddressInfo->Address.Addr [ 2 ],

+                pAddressInfo->Address.Addr [ 3 ],

+                pAddressInfo->Address.Addr [ 4 ],

+                pAddressInfo->Address.Addr [ 5 ],

+                pAddressInfo->Address.Addr [ 6 ],

+                pAddressInfo->Address.Addr [ 7 ],

+                pAddressInfo->Address.Addr [ 8 ],

+                pAddressInfo->Address.Addr [ 9 ],

+                pAddressInfo->Address.Addr [ 10 ],

+                pAddressInfo->Address.Addr [ 11 ],

+                pAddressInfo->Address.Addr [ 12 ],

+                pAddressInfo->Address.Addr [ 13 ],

+                pAddressInfo->Address.Addr [ 14 ],

+                pAddressInfo->Address.Addr [ 15 ]));

+

+      //

+      //  Validate the IP address

+      //

+      if (( pAccess->StationAddress.Addr [ 0 ] == pAddressInfo->Address.Addr [ 0 ])

+        && ( pAccess->StationAddress.Addr [ 1 ] == pAddressInfo->Address.Addr [ 1 ])

+        && ( pAccess->StationAddress.Addr [ 2 ] == pAddressInfo->Address.Addr [ 2 ])

+        && ( pAccess->StationAddress.Addr [ 3 ] == pAddressInfo->Address.Addr [ 3 ])

+        && ( pAccess->StationAddress.Addr [ 4 ] == pAddressInfo->Address.Addr [ 4 ])

+        && ( pAccess->StationAddress.Addr [ 5 ] == pAddressInfo->Address.Addr [ 5 ])

+        && ( pAccess->StationAddress.Addr [ 6 ] == pAddressInfo->Address.Addr [ 6 ])

+        && ( pAccess->StationAddress.Addr [ 7 ] == pAddressInfo->Address.Addr [ 7 ])

+        && ( pAccess->StationAddress.Addr [ 8 ] == pAddressInfo->Address.Addr [ 8 ])

+        && ( pAccess->StationAddress.Addr [ 9 ] == pAddressInfo->Address.Addr [ 9 ])

+        && ( pAccess->StationAddress.Addr [ 10 ] == pAddressInfo->Address.Addr [ 10 ])

+        && ( pAccess->StationAddress.Addr [ 11 ] == pAddressInfo->Address.Addr [ 11 ])

+        && ( pAccess->StationAddress.Addr [ 12 ] == pAddressInfo->Address.Addr [ 12 ])

+        && ( pAccess->StationAddress.Addr [ 13 ] == pAddressInfo->Address.Addr [ 13 ])

+        && ( pAccess->StationAddress.Addr [ 14 ] == pAddressInfo->Address.Addr [ 14 ])

+        && ( pAccess->StationAddress.Addr [ 15 ] == pAddressInfo->Address.Addr [ 15 ])) {

+        break;

+      }

+    }

+    if ( pIpConfigData->AddressInfoCount > AddressCount ) {

+      break;

+    }

+

+    //

+    //  The IP address did not match

+    //

+    Status = EFI_NOT_STARTED;

+    break;

+  }

+

+  //

+  //  Free the buffer if necessary

+  //

+  if ( NULL != pIpConfigData ) {

+    FreePool ( pIpConfigData );

+  }

+

+  //

+  //  Return the IP address status

+  //

+  DBG_EXIT_STATUS ( Status );

+  return Status;

+}

+

+

+/**

   Interface between the socket layer and the network specific

   code that supports SOCK_STREAM and SOCK_SEQPACKET sockets

   over TCPv6.

@@ -2333,5 +2589,6 @@
   EslTcp6RxStart,

   EslTcp6TxBuffer,

   EslTcp6TxComplete,

-  EslTcp6TxOobComplete

+  EslTcp6TxOobComplete,

+  EslTcp6VerifyLocalIpAddress

 };

diff --git a/StdLib/EfiSocketLib/Udp4.c b/StdLib/EfiSocketLib/Udp4.c
index 11b7db7..9ab96ac 100644
--- a/StdLib/EfiSocketLib/Udp4.c
+++ b/StdLib/EfiSocketLib/Udp4.c
@@ -867,63 +867,62 @@
           RAISE_TPL ( TplPrevious, TPL_SOCKETS );

 

           //

-          //  Stop transmission after an error

+          //  Display the request

           //

-          if ( !EFI_ERROR ( pSocket->TxError )) {

-            //

-            //  Display the request

-            //

-            DEBUG (( DEBUG_TX,

-                      "Send %d %s bytes from 0x%08x\r\n",

-                      BufferLength,

-                      pBuffer ));

+          DEBUG (( DEBUG_TX,

+                    "Send %d bytes from 0x%08x to %d.%d.%d.%d:%d\r\n",

+                    BufferLength,

+                    pBuffer,

+                    pTxData->Session.DestinationAddress.Addr[0],

+                    pTxData->Session.DestinationAddress.Addr[1],

+                    pTxData->Session.DestinationAddress.Addr[2],

+                    pTxData->Session.DestinationAddress.Addr[3],

+                    pTxData->Session.DestinationPort ));

 

-            //

-            //  Queue the data for transmission

-            //

-            pPacket->pNext = NULL;

-            pPreviousPacket = pSocket->pTxPacketListTail;

-            if ( NULL == pPreviousPacket ) {

-              pSocket->pTxPacketListHead = pPacket;

-            }

-            else {

-              pPreviousPacket->pNext = pPacket;

-            }

-            pSocket->pTxPacketListTail = pPacket;

-            DEBUG (( DEBUG_TX,

-                      "0x%08x: Packet on transmit list\r\n",

-                      pPacket ));

-

-            //

-            //  Account for the buffered data

-            //

-            *pTxBytes += BufferLength;

-            *pDataLength = BufferLength;

-

-            //

-            //  Start the transmit engine if it is idle

-            //

-            if ( NULL != pPort->pTxFree ) {

-              EslSocketTxStart ( pPort,

-                                 &pSocket->pTxPacketListHead,

-                                 &pSocket->pTxPacketListTail,

-                                 &pPort->pTxActive,

-                                 &pPort->pTxFree );

-            }

+          //

+          //  Queue the data for transmission

+          //

+          pPacket->pNext = NULL;

+          pPreviousPacket = pSocket->pTxPacketListTail;

+          if ( NULL == pPreviousPacket ) {

+            pSocket->pTxPacketListHead = pPacket;

           }

           else {

-            //

-            //  Previous transmit error

-            //  Stop transmission

-            //

-            Status = pSocket->TxError;

-            pSocket->errno = EIO;

+            pPreviousPacket->pNext = pPacket;

+          }

+          pSocket->pTxPacketListTail = pPacket;

+          DEBUG (( DEBUG_TX,

+                    "0x%08x: Packet on transmit list\r\n",

+                    pPacket ));

+

+          //

+          //  Account for the buffered data

+          //

+          *pTxBytes += BufferLength;

+          *pDataLength = BufferLength;

+

+          //

+          //  Start the transmit engine if it is idle

+          //

+          if ( NULL != pPort->pTxFree ) {

+            pPacket = pSocket->pTxPacketListHead;

+            EslSocketTxStart ( pPort,

+                               &pSocket->pTxPacketListHead,

+                               &pSocket->pTxPacketListTail,

+                               &pPort->pTxActive,

+                               &pPort->pTxFree );

 

             //

-            //  Free the packet

+            //  Ignore any transmit error

             //

-            EslSocketPacketFree ( pPacket, DEBUG_TX );

-            break;

+            if ( EFI_ERROR ( pSocket->TxError )) {

+              DEBUG (( DEBUG_TX,

+                       "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",

+                       pPort,

+                       pPacket,

+                       pSocket->TxError ));

+            }

+            pSocket->TxError = EFI_SUCCESS;

           }

 

           //

@@ -1005,6 +1004,18 @@
   Status = pIo->Token.Udp4Tx.Status;

 

   //

+  //  Ignore the transmit error

+  //

+  if ( EFI_ERROR ( Status )) {

+    DEBUG (( DEBUG_TX,

+             "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",

+             pPort,

+             pPacket,

+             Status ));

+    Status = EFI_SUCCESS;

+  }

+

+  //

   //  Complete the transmit operation

   //

   EslSocketTxComplete ( pIo,

@@ -1020,6 +1031,157 @@
 

 

 /**

+  Verify the adapter's IP address

+

+  This support routine is called by EslSocketBindTest.

+

+  @param [in] pPort       Address of an ::ESL_PORT structure.

+  @param [in] pConfigData Address of the configuration data

+

+  @retval EFI_SUCCESS - The IP address is valid

+  @retval EFI_NOT_STARTED - The IP address is invalid

+

+ **/

+EFI_STATUS

+EslUdp4VerifyLocalIpAddress (

+  IN ESL_PORT * pPort,

+  IN EFI_UDP4_CONFIG_DATA * pConfigData

+  )

+{

+  UINTN DataSize;

+  EFI_IP4_IPCONFIG_DATA * pIpConfigData;

+  EFI_IP4_CONFIG_PROTOCOL * pIpConfigProtocol;

+  ESL_SERVICE * pService;

+  EFI_STATUS Status;

+

+  DBG_ENTER ( );

+

+  //

+  //  Use break instead of goto

+  //

+  pIpConfigData = NULL;

+  for ( ; ; ) {

+    //

+    //  Determine if the IP address is specified

+    //

+    DEBUG (( DEBUG_BIND,

+              "UseDefaultAddress: %s\r\n",

+              pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" ));

+    DEBUG (( DEBUG_BIND,

+              "Requested IP address: %d.%d.%d.%d\r\n",

+              pConfigData->StationAddress.Addr [ 0 ],

+              pConfigData->StationAddress.Addr [ 1 ],

+              pConfigData->StationAddress.Addr [ 2 ],

+              pConfigData->StationAddress.Addr [ 3 ]));

+    if ( pConfigData->UseDefaultAddress

+      || (( 0 == pConfigData->StationAddress.Addr [ 0 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 1 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 2 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 3 ])))

+    {

+      Status = EFI_SUCCESS;

+      break;

+    }

+

+    //

+    //  Open the configuration protocol

+    //

+    pService = pPort->pService;

+    Status = gBS->OpenProtocol ( pService->Controller,

+                                 &gEfiIp4ConfigProtocolGuid,

+                                 (VOID **)&pIpConfigProtocol,

+                                 NULL,

+                                 NULL,

+                                 EFI_OPEN_PROTOCOL_GET_PROTOCOL );

+    if ( EFI_ERROR ( Status )) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - IP Configuration Protocol not available, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Get the IP configuration data size

+    //

+    DataSize = 0;

+    Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,

+                                          &DataSize,

+                                          NULL );

+    if ( EFI_BUFFER_TOO_SMALL != Status ) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Allocate the configuration data buffer

+    //

+    pIpConfigData = AllocatePool ( DataSize );

+    if ( NULL == pIpConfigData ) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));

+      Status = EFI_OUT_OF_RESOURCES;

+      break;

+    }

+

+    //

+    //  Get the IP configuration

+    //

+    Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,

+                                          &DataSize,

+                                          pIpConfigData );

+    if ( EFI_ERROR ( Status )) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Failed to return IP Configuration data, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Display the current configuration

+    //

+    DEBUG (( DEBUG_BIND,

+              "Actual adapter IP address: %d.%d.%d.%d\r\n",

+              pIpConfigData->StationAddress.Addr [ 0 ],

+              pIpConfigData->StationAddress.Addr [ 1 ],

+              pIpConfigData->StationAddress.Addr [ 2 ],

+              pIpConfigData->StationAddress.Addr [ 3 ]));

+

+    //

+    //  Assume the port is not configured

+    //

+    Status = EFI_SUCCESS;

+    if (( pConfigData->StationAddress.Addr [ 0 ] == pIpConfigData->StationAddress.Addr [ 0 ])

+      && ( pConfigData->StationAddress.Addr [ 1 ] == pIpConfigData->StationAddress.Addr [ 1 ])

+      && ( pConfigData->StationAddress.Addr [ 2 ] == pIpConfigData->StationAddress.Addr [ 2 ])

+      && ( pConfigData->StationAddress.Addr [ 3 ] == pIpConfigData->StationAddress.Addr [ 3 ])) {

+      break;

+    }

+

+    //

+    //  The IP address did not match

+    //

+    Status = EFI_NOT_STARTED;

+    break;

+  }

+

+  //

+  //  Free the buffer if necessary

+  //

+  if ( NULL != pIpConfigData ) {

+    FreePool ( pIpConfigData );

+  }

+

+  //

+  //  Return the IP address status

+  //

+  DBG_EXIT_STATUS ( Status );

+  return Status;

+}

+

+

+/**

   Interface between the socket layer and the network specific

   code that supports SOCK_DGRAM sockets over UDPv4.

 **/

@@ -1057,5 +1219,6 @@
   NULL,   //  RxStart

   EslUdp4TxBuffer,

   EslUdp4TxComplete,

-  NULL    //  TxOobComplete

+  NULL,   //  TxOobComplete

+  EslUdp4VerifyLocalIpAddress

 };

diff --git a/StdLib/EfiSocketLib/Udp6.c b/StdLib/EfiSocketLib/Udp6.c
index 7de5005..59b99f8 100644
--- a/StdLib/EfiSocketLib/Udp6.c
+++ b/StdLib/EfiSocketLib/Udp6.c
@@ -609,7 +609,7 @@
       pUdp6Protocol = pPort->pProtocol.UDPv6;

       pConfigData = &pUdp6->ConfigData;

       DEBUG (( DEBUG_TX,

-                "0x%08x: pPort Configuring for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",

+                "0x%08x: pPort Configuring for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> ",

                 pPort,

                 pConfigData->StationAddress.Addr[0],

                 pConfigData->StationAddress.Addr[1],

@@ -627,7 +627,9 @@
                 pConfigData->StationAddress.Addr[13],

                 pConfigData->StationAddress.Addr[14],

                 pConfigData->StationAddress.Addr[15],

-                pConfigData->StationPort,

+                pConfigData->StationPort ));

+      DEBUG (( DEBUG_TX,

+                "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",

                 pConfigData->RemoteAddress.Addr[0],

                 pConfigData->RemoteAddress.Addr[1],

                 pConfigData->RemoteAddress.Addr[2],

@@ -692,7 +694,7 @@
       }

       else {

         DEBUG (( DEBUG_TX,

-                  "0x%08x: pPort Configured for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",

+                  "0x%08x: pPort Configured for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> ",

                   pPort,

                   pConfigData->StationAddress.Addr[0],

                   pConfigData->StationAddress.Addr[1],

@@ -710,7 +712,9 @@
                   pConfigData->StationAddress.Addr[13],

                   pConfigData->StationAddress.Addr[14],

                   pConfigData->StationAddress.Addr[15],

-                  pConfigData->StationPort,

+                  pConfigData->StationPort ));

+        DEBUG (( DEBUG_TX,

+                  "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",

                   pConfigData->RemoteAddress.Addr[0],

                   pConfigData->RemoteAddress.Addr[1],

                   pConfigData->RemoteAddress.Addr[2],

@@ -904,63 +908,73 @@
           RAISE_TPL ( TplPrevious, TPL_SOCKETS );

 

           //

-          //  Stop transmission after an error

+          //  Display the request

           //

-          if ( !EFI_ERROR ( pSocket->TxError )) {

-            //

-            //  Display the request

-            //

-            DEBUG (( DEBUG_TX,

-                      "Send %d %s bytes from 0x%08x\r\n",

-                      BufferLength,

-                      pBuffer ));

+          DEBUG (( DEBUG_TX,

+                    "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",

+                    BufferLength,

+                    pBuffer,

+                    pTxData->Session.DestinationAddress.Addr[0],

+                    pTxData->Session.DestinationAddress.Addr[1],

+                    pTxData->Session.DestinationAddress.Addr[2],

+                    pTxData->Session.DestinationAddress.Addr[3],

+                    pTxData->Session.DestinationAddress.Addr[4],

+                    pTxData->Session.DestinationAddress.Addr[5],

+                    pTxData->Session.DestinationAddress.Addr[6],

+                    pTxData->Session.DestinationAddress.Addr[7],

+                    pTxData->Session.DestinationAddress.Addr[8],

+                    pTxData->Session.DestinationAddress.Addr[9],

+                    pTxData->Session.DestinationAddress.Addr[10],

+                    pTxData->Session.DestinationAddress.Addr[11],

+                    pTxData->Session.DestinationAddress.Addr[12],

+                    pTxData->Session.DestinationAddress.Addr[13],

+                    pTxData->Session.DestinationAddress.Addr[14],

+                    pTxData->Session.DestinationAddress.Addr[15],

+                    pTxData->Session.DestinationPort ));

 

-            //

-            //  Queue the data for transmission

-            //

-            pPacket->pNext = NULL;

-            pPreviousPacket = pSocket->pTxPacketListTail;

-            if ( NULL == pPreviousPacket ) {

-              pSocket->pTxPacketListHead = pPacket;

-            }

-            else {

-              pPreviousPacket->pNext = pPacket;

-            }

-            pSocket->pTxPacketListTail = pPacket;

-            DEBUG (( DEBUG_TX,

-                      "0x%08x: Packet on transmit list\r\n",

-                      pPacket ));

-

-            //

-            //  Account for the buffered data

-            //

-            *pTxBytes += BufferLength;

-            *pDataLength = BufferLength;

-

-            //

-            //  Start the transmit engine if it is idle

-            //

-            if ( NULL != pPort->pTxFree ) {

-              EslSocketTxStart ( pPort,

-                                 &pSocket->pTxPacketListHead,

-                                 &pSocket->pTxPacketListTail,

-                                 &pPort->pTxActive,

-                                 &pPort->pTxFree );

-            }

+          //

+          //  Queue the data for transmission

+          //

+          pPacket->pNext = NULL;

+          pPreviousPacket = pSocket->pTxPacketListTail;

+          if ( NULL == pPreviousPacket ) {

+            pSocket->pTxPacketListHead = pPacket;

           }

           else {

-            //

-            //  Previous transmit error

-            //  Stop transmission

-            //

-            Status = pSocket->TxError;

-            pSocket->errno = EIO;

+            pPreviousPacket->pNext = pPacket;

+          }

+          pSocket->pTxPacketListTail = pPacket;

+          DEBUG (( DEBUG_TX,

+                    "0x%08x: Packet on transmit list\r\n",

+                    pPacket ));

+

+          //

+          //  Account for the buffered data

+          //

+          *pTxBytes += BufferLength;

+          *pDataLength = BufferLength;

+

+          //

+          //  Start the transmit engine if it is idle

+          //

+          if ( NULL != pPort->pTxFree ) {

+            EslSocketTxStart ( pPort,

+                               &pSocket->pTxPacketListHead,

+                               &pSocket->pTxPacketListTail,

+                               &pPort->pTxActive,

+                               &pPort->pTxFree );

 

             //

-            //  Free the packet

+            //  Ignore any transmit error

             //

-            EslSocketPacketFree ( pPacket, DEBUG_TX );

-            break;

+            if ( EFI_ERROR ( pSocket->TxError )) {

+              DEBUG (( DEBUG_TX,

+                       "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",

+                       pPort,

+                       pPacket,

+                       pSocket->TxError ));

+            }

+            pSocket->TxError = EFI_SUCCESS;

           }

 

           //

@@ -1042,6 +1056,18 @@
   Status = pIo->Token.Udp6Tx.Status;

 

   //

+  //  Ignore the transmit error

+  //

+  if ( EFI_ERROR ( Status )) {

+    DEBUG (( DEBUG_TX,

+             "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",

+             pPort,

+             pPacket,

+             Status ));

+    Status = EFI_SUCCESS;

+  }

+

+  //

   //  Complete the transmit operation

   //

   EslSocketTxComplete ( pIo,

@@ -1057,6 +1083,260 @@
 

 

 /**

+  Verify the adapter's IP address

+

+  This support routine is called by EslSocketBindTest.

+

+  @param [in] pPort       Address of an ::ESL_PORT structure.

+  @param [in] pConfigData Address of the configuration data

+

+  @retval EFI_SUCCESS - The IP address is valid

+  @retval EFI_NOT_STARTED - The IP address is invalid

+

+ **/

+EFI_STATUS

+EslUdp6VerifyLocalIpAddress (

+  IN ESL_PORT * pPort,

+  IN EFI_UDP6_CONFIG_DATA * pConfigData

+  )

+{

+  UINTN AddressCount;

+  EFI_IP6_ADDRESS_INFO * pAddressInfo;

+  UINTN DataSize;

+  EFI_IP6_CONFIG_INTERFACE_INFO * pIpConfigData;

+  EFI_IP6_CONFIG_PROTOCOL * pIpConfigProtocol;

+  ESL_SERVICE * pService;

+  EFI_STATUS Status;

+

+  DBG_ENTER ( );

+

+  //

+  //  Use break instead of goto

+  //

+  pIpConfigData = NULL;

+  for ( ; ; ) {

+    //

+    //  Determine if the IP address is specified

+    //

+    DEBUG (( DEBUG_BIND,

+              "Requested IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",

+              pConfigData->StationAddress.Addr[0],

+              pConfigData->StationAddress.Addr[1],

+              pConfigData->StationAddress.Addr[2],

+              pConfigData->StationAddress.Addr[3],

+              pConfigData->StationAddress.Addr[4],

+              pConfigData->StationAddress.Addr[5],

+              pConfigData->StationAddress.Addr[6],

+              pConfigData->StationAddress.Addr[7],

+              pConfigData->StationAddress.Addr[8],

+              pConfigData->StationAddress.Addr[9],

+              pConfigData->StationAddress.Addr[10],

+              pConfigData->StationAddress.Addr[11],

+              pConfigData->StationAddress.Addr[12],

+              pConfigData->StationAddress.Addr[13],

+              pConfigData->StationAddress.Addr[14],

+              pConfigData->StationAddress.Addr[15]));

+    if (( 0 == pConfigData->StationAddress.Addr [ 0 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 1 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 2 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 3 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 4 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 5 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 6 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 7 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 8 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 9 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 10 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 11 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 12 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 13 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 14 ])

+      && ( 0 == pConfigData->StationAddress.Addr [ 15 ]))

+    {

+      Status = EFI_SUCCESS;

+      break;

+    }

+

+    //

+    //  Open the configuration protocol

+    //

+    pService = pPort->pService;

+    Status = gBS->OpenProtocol ( pService->Controller,

+                                 &gEfiIp6ConfigProtocolGuid,

+                                 (VOID **)&pIpConfigProtocol,

+                                 NULL,

+                                 NULL,

+                                 EFI_OPEN_PROTOCOL_GET_PROTOCOL );

+    if ( EFI_ERROR ( Status )) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - IP Configuration Protocol not available, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Get the IP configuration data size

+    //

+    DataSize = 0;

+    Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,

+                                          Ip6ConfigDataTypeInterfaceInfo,

+                                          &DataSize,

+                                          NULL );

+    if ( EFI_BUFFER_TOO_SMALL != Status ) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Allocate the configuration data buffer

+    //

+    pIpConfigData = AllocatePool ( DataSize );

+    if ( NULL == pIpConfigData ) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));

+      Status = EFI_OUT_OF_RESOURCES;

+      break;

+    }

+

+    //

+    //  Get the IP configuration

+    //

+    Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,

+                                          Ip6ConfigDataTypeInterfaceInfo,

+                                          &DataSize,

+                                          pIpConfigData );

+    if ( EFI_ERROR ( Status )) {

+      DEBUG (( DEBUG_ERROR,

+                "ERROR - Failed to return IP Configuration data, Status: %r\r\n",

+                Status ));

+      break;

+    }

+

+    //

+    //  Display the current configuration

+    //

+    DEBUG (( DEBUG_BIND,

+              "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",

+              pIpConfigData->HwAddress.Addr [ 0 ],

+              pIpConfigData->HwAddress.Addr [ 1 ],

+              pIpConfigData->HwAddress.Addr [ 2 ],

+              pIpConfigData->HwAddress.Addr [ 3 ],

+              pIpConfigData->HwAddress.Addr [ 4 ],

+              pIpConfigData->HwAddress.Addr [ 5 ],

+              pIpConfigData->HwAddress.Addr [ 6 ],

+              pIpConfigData->HwAddress.Addr [ 7 ],

+              pIpConfigData->HwAddress.Addr [ 8 ],

+              pIpConfigData->HwAddress.Addr [ 9 ],

+              pIpConfigData->HwAddress.Addr [ 10 ],

+              pIpConfigData->HwAddress.Addr [ 11 ],

+              pIpConfigData->HwAddress.Addr [ 12 ],

+              pIpConfigData->HwAddress.Addr [ 13 ],

+              pIpConfigData->HwAddress.Addr [ 14 ],

+              pIpConfigData->HwAddress.Addr [ 15 ]));

+

+    //

+    //  Validate the hardware address

+    //

+    Status = EFI_SUCCESS;

+    if (( 16 == pIpConfigData->HwAddressSize )

+      && ( pConfigData->StationAddress.Addr [ 0 ] == pIpConfigData->HwAddress.Addr [ 0 ])

+      && ( pConfigData->StationAddress.Addr [ 1 ] == pIpConfigData->HwAddress.Addr [ 1 ])

+      && ( pConfigData->StationAddress.Addr [ 2 ] == pIpConfigData->HwAddress.Addr [ 2 ])

+      && ( pConfigData->StationAddress.Addr [ 3 ] == pIpConfigData->HwAddress.Addr [ 3 ])

+      && ( pConfigData->StationAddress.Addr [ 4 ] == pIpConfigData->HwAddress.Addr [ 4 ])

+      && ( pConfigData->StationAddress.Addr [ 5 ] == pIpConfigData->HwAddress.Addr [ 5 ])

+      && ( pConfigData->StationAddress.Addr [ 6 ] == pIpConfigData->HwAddress.Addr [ 6 ])

+      && ( pConfigData->StationAddress.Addr [ 7 ] == pIpConfigData->HwAddress.Addr [ 7 ])

+      && ( pConfigData->StationAddress.Addr [ 8 ] == pIpConfigData->HwAddress.Addr [ 8 ])

+      && ( pConfigData->StationAddress.Addr [ 9 ] == pIpConfigData->HwAddress.Addr [ 9 ])

+      && ( pConfigData->StationAddress.Addr [ 10 ] == pIpConfigData->HwAddress.Addr [ 10 ])

+      && ( pConfigData->StationAddress.Addr [ 11 ] == pIpConfigData->HwAddress.Addr [ 11 ])

+      && ( pConfigData->StationAddress.Addr [ 12 ] == pIpConfigData->HwAddress.Addr [ 12 ])

+      && ( pConfigData->StationAddress.Addr [ 13 ] == pIpConfigData->HwAddress.Addr [ 13 ])

+      && ( pConfigData->StationAddress.Addr [ 14 ] == pIpConfigData->HwAddress.Addr [ 14 ])

+      && ( pConfigData->StationAddress.Addr [ 15 ] == pIpConfigData->HwAddress.Addr [ 15 ])) {

+      break;

+    }

+

+    //

+    //  Walk the list of other IP addresses assigned to this adapter

+    //

+    for ( AddressCount = 0; pIpConfigData->AddressInfoCount > AddressCount; AddressCount += 1 ) {

+      pAddressInfo = &pIpConfigData->AddressInfo [ AddressCount ];

+

+      //

+      //  Display the IP address

+      //

+      DEBUG (( DEBUG_BIND,

+                "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",

+                pAddressInfo->Address.Addr [ 0 ],

+                pAddressInfo->Address.Addr [ 1 ],

+                pAddressInfo->Address.Addr [ 2 ],

+                pAddressInfo->Address.Addr [ 3 ],

+                pAddressInfo->Address.Addr [ 4 ],

+                pAddressInfo->Address.Addr [ 5 ],

+                pAddressInfo->Address.Addr [ 6 ],

+                pAddressInfo->Address.Addr [ 7 ],

+                pAddressInfo->Address.Addr [ 8 ],

+                pAddressInfo->Address.Addr [ 9 ],

+                pAddressInfo->Address.Addr [ 10 ],

+                pAddressInfo->Address.Addr [ 11 ],

+                pAddressInfo->Address.Addr [ 12 ],

+                pAddressInfo->Address.Addr [ 13 ],

+                pAddressInfo->Address.Addr [ 14 ],

+                pAddressInfo->Address.Addr [ 15 ]));

+

+      //

+      //  Validate the IP address

+      //

+      if (( pConfigData->StationAddress.Addr [ 0 ] == pAddressInfo->Address.Addr [ 0 ])

+        && ( pConfigData->StationAddress.Addr [ 1 ] == pAddressInfo->Address.Addr [ 1 ])

+        && ( pConfigData->StationAddress.Addr [ 2 ] == pAddressInfo->Address.Addr [ 2 ])

+        && ( pConfigData->StationAddress.Addr [ 3 ] == pAddressInfo->Address.Addr [ 3 ])

+        && ( pConfigData->StationAddress.Addr [ 4 ] == pAddressInfo->Address.Addr [ 4 ])

+        && ( pConfigData->StationAddress.Addr [ 5 ] == pAddressInfo->Address.Addr [ 5 ])

+        && ( pConfigData->StationAddress.Addr [ 6 ] == pAddressInfo->Address.Addr [ 6 ])

+        && ( pConfigData->StationAddress.Addr [ 7 ] == pAddressInfo->Address.Addr [ 7 ])

+        && ( pConfigData->StationAddress.Addr [ 8 ] == pAddressInfo->Address.Addr [ 8 ])

+        && ( pConfigData->StationAddress.Addr [ 9 ] == pAddressInfo->Address.Addr [ 9 ])

+        && ( pConfigData->StationAddress.Addr [ 10 ] == pAddressInfo->Address.Addr [ 10 ])

+        && ( pConfigData->StationAddress.Addr [ 11 ] == pAddressInfo->Address.Addr [ 11 ])

+        && ( pConfigData->StationAddress.Addr [ 12 ] == pAddressInfo->Address.Addr [ 12 ])

+        && ( pConfigData->StationAddress.Addr [ 13 ] == pAddressInfo->Address.Addr [ 13 ])

+        && ( pConfigData->StationAddress.Addr [ 14 ] == pAddressInfo->Address.Addr [ 14 ])

+        && ( pConfigData->StationAddress.Addr [ 15 ] == pAddressInfo->Address.Addr [ 15 ])) {

+        break;

+      }

+    }

+    if ( pIpConfigData->AddressInfoCount > AddressCount ) {

+      break;

+    }

+

+    //

+    //  The IP address did not match

+    //

+    Status = EFI_NOT_STARTED;

+    break;

+  }

+

+  //

+  //  Free the buffer if necessary

+  //

+  if ( NULL != pIpConfigData ) {

+    FreePool ( pIpConfigData );

+  }

+

+  //

+  //  Return the IP address status

+  //

+  DBG_EXIT_STATUS ( Status );

+  return Status;

+}

+

+

+/**

   Interface between the socket layer and the network specific

   code that supports SOCK_DGRAM sockets over UDPv4.

 **/

@@ -1094,5 +1374,6 @@
   NULL,   //  RxStart

   EslUdp6TxBuffer,

   EslUdp6TxComplete,

-  NULL    //  TxOobComplete

+  NULL,   //  TxOobComplete

+  EslUdp6VerifyLocalIpAddress

 };

diff --git a/StdLib/Include/Efi/EfiSocketLib.h b/StdLib/Include/Efi/EfiSocketLib.h
index d78e9f6..efd6a61 100644
--- a/StdLib/Include/Efi/EfiSocketLib.h
+++ b/StdLib/Include/Efi/EfiSocketLib.h
@@ -24,6 +24,8 @@
 #include <Library/UefiLib.h>

 

 #include <Protocol/EfiSocket.h>

+#include <Protocol/Ip4Config.h>

+#include <Protocol/Ip6Config.h>

 #include <Protocol/ServiceBinding.h>

 #include <Protocol/Tcp4.h>

 #include <Protocol/Tcp6.h>