]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/EfiSocketLib/Tcp4.c
UefiCpuPkg: INF/DEC file updates to EDK II packages
[mirror_edk2.git] / StdLib / EfiSocketLib / Tcp4.c
index ec03b96bc149da61760107f6bae2ee4706a5967f..7ece38d52137329e74d800f8830bd32ded86be03 100644 (file)
@@ -232,6 +232,13 @@ EslTcp4ConnectComplete (
               pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],\r
               pTcp4->ConfigData.AccessPoint.RemotePort ));\r
 \r
+    //\r
+    //  Start the receive operations\r
+    //\r
+    pSocket->bConfigured = TRUE;\r
+    pSocket->State = SOCKET_STATE_CONNECTED;\r
+    EslSocketRxStart ( pPort );\r
+\r
     //\r
     //  Remove the rest of the ports\r
     //\r
@@ -241,15 +248,17 @@ EslTcp4ConnectComplete (
     //\r
     //  The connection failed\r
     //\r
-    DEBUG (( DEBUG_CONNECT,\r
-              "0x%08x: Port connection to %d.%d.%d.%d:%d failed, Status: %r\r\n",\r
-              pPort,\r
-              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],\r
-              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],\r
-              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],\r
-              pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],\r
-              pTcp4->ConfigData.AccessPoint.RemotePort,\r
-              Status ));\r
+    if ( pPort->bConfigured ) {\r
+      DEBUG (( DEBUG_CONNECT,\r
+                "0x%08x: Port connection to %d.%d.%d.%d:%d failed, Status: %r\r\n",\r
+                pPort,\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],\r
+                pTcp4->ConfigData.AccessPoint.RemotePort,\r
+                Status ));\r
+    }\r
 \r
     //\r
     //  Close the current port\r
@@ -272,7 +281,6 @@ EslTcp4ConnectComplete (
     //\r
     Status = EslTcp4ConnectStart ( pSocket );\r
     if ( EFI_NOT_READY != Status ) {\r
-      pSocket->ConnectStatus = Status;\r
       bRemoveFirstPort = TRUE;\r
     }\r
   }\r
@@ -374,29 +382,47 @@ EslTcp4ConnectPoll (
       break;\r
 \r
     case EFI_ABORTED:\r
-      pSocket->errno = ECONNREFUSED;\r
+      pSocket->errno = ECONNABORTED;\r
+      break;\r
+\r
+    case EFI_ACCESS_DENIED:\r
+      pSocket->errno = EACCES;\r
+      break;\r
+\r
+    case EFI_CONNECTION_RESET:\r
+      pSocket->errno = ECONNRESET;\r
       break;\r
 \r
     case EFI_INVALID_PARAMETER:\r
-      pSocket->errno = EINVAL;\r
+      pSocket->errno = EADDRNOTAVAIL;\r
       break;\r
 \r
-    case EFI_NO_MAPPING:\r
+    case EFI_HOST_UNREACHABLE:\r
     case EFI_NO_RESPONSE:\r
       pSocket->errno = EHOSTUNREACH;\r
       break;\r
 \r
+    case EFI_NO_MAPPING:\r
+      pSocket->errno = EAFNOSUPPORT;\r
+      break;\r
+\r
     case EFI_NO_MEDIA:\r
+    case EFI_NETWORK_UNREACHABLE:\r
       pSocket->errno = ENETDOWN;\r
       break;\r
 \r
     case EFI_OUT_OF_RESOURCES:\r
-      pSocket->errno = ENOMEM;\r
+      pSocket->errno = ENOBUFS;\r
+      break;\r
+\r
+    case EFI_PORT_UNREACHABLE:\r
+    case EFI_PROTOCOL_UNREACHABLE:\r
+    case EFI_CONNECTION_REFUSED:\r
+      pSocket->errno = ECONNREFUSED;\r
       break;\r
 \r
     case EFI_SUCCESS:\r
       pSocket->errno = 0;\r
-      pSocket->bConfigured = TRUE;\r
       break;\r
 \r
     case EFI_TIMEOUT:\r
@@ -404,13 +430,17 @@ EslTcp4ConnectPoll (
       break;\r
 \r
     case EFI_UNSUPPORTED:\r
-      pSocket->errno = ENOTSUP;\r
-      break;\r
-\r
-    case 0x80000069:\r
-      pSocket->errno = ECONNRESET;\r
+      pSocket->errno = EOPNOTSUPP;\r
       break;\r
     }\r
+\r
+    //\r
+    //  Display the translation\r
+    //\r
+    DEBUG (( DEBUG_CONNECT,\r
+              "ERROR - errno: %d, Status: %r\r\n",\r
+              pSocket->errno,\r
+              Status ));\r
   }\r
 \r
   //\r
@@ -453,6 +483,7 @@ EslTcp4ConnectStart (
   ESL_PORT * pPort;\r
   ESL_TCP4_CONTEXT * pTcp4;\r
   EFI_TCP4_PROTOCOL * pTcp4Protocol;\r
+  EFI_SIMPLE_NETWORK_MODE SnpModeData;\r
   EFI_STATUS Status;\r
 \r
   DBG_ENTER ( );\r
@@ -475,32 +506,6 @@ EslTcp4ConnectStart (
       DEBUG (( DEBUG_CONNECT,\r
                 "ERROR - Failed to configure the Tcp4 port, Status: %r\r\n",\r
                 Status ));\r
-      switch ( Status ) {\r
-      case EFI_ACCESS_DENIED:\r
-        pSocket->errno = EACCES;\r
-        break;\r
-    \r
-      default:\r
-      case EFI_DEVICE_ERROR:\r
-        pSocket->errno = EIO;\r
-        break;\r
-    \r
-      case EFI_INVALID_PARAMETER:\r
-        pSocket->errno = EADDRNOTAVAIL;\r
-        break;\r
-    \r
-      case EFI_NO_MAPPING:\r
-        pSocket->errno = EAFNOSUPPORT;\r
-        break;\r
-    \r
-      case EFI_OUT_OF_RESOURCES:\r
-        pSocket->errno = ENOBUFS;\r
-        break;\r
-    \r
-      case EFI_UNSUPPORTED:\r
-        pSocket->errno = EOPNOTSUPP;\r
-        break;\r
-      }\r
     }\r
     else {\r
       DEBUG (( DEBUG_CONNECT,\r
@@ -509,26 +514,31 @@ EslTcp4ConnectStart (
       pPort->bConfigured = TRUE;\r
 \r
       //\r
-      //  Attempt the connection to the remote system\r
+      //  Verify the port connection\r
       //\r
-      Status = pTcp4Protocol->Connect ( pTcp4Protocol,\r
-                                        &pTcp4->ConnectToken );\r
+      Status = pTcp4Protocol->GetModeData ( pTcp4Protocol,\r
+                                            NULL,\r
+                                            NULL,\r
+                                            NULL,\r
+                                            NULL,\r
+                                            &SnpModeData );\r
       if ( !EFI_ERROR ( Status )) {\r
-        //\r
-        //  Connection in progress\r
-        //\r
-        pSocket->errno = EINPROGRESS;\r
-        Status = EFI_NOT_READY;\r
-        DEBUG (( DEBUG_CONNECT,\r
-                  "0x%08x: Port attempting connection to %d.%d.%d.%d:%d\r\n",\r
-                  pPort,\r
-                  pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],\r
-                  pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],\r
-                  pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],\r
-                  pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],\r
-                  pTcp4->ConfigData.AccessPoint.RemotePort ));\r
+        if ( SnpModeData.MediaPresentSupported\r
+          && ( !SnpModeData.MediaPresent )) {\r
+          //\r
+          //  Port is not connected to the network\r
+          //\r
+          Status = EFI_NO_MEDIA;\r
+        }\r
+        else {\r
+          //\r
+          //  Attempt the connection to the remote system\r
+          //\r
+          Status = pTcp4Protocol->Connect ( pTcp4Protocol,\r
+                                            &pTcp4->ConnectToken );\r
+        }\r
       }\r
-      else {\r
+      if ( EFI_ERROR ( Status )) {\r
         //\r
         //  Connection error\r
         //\r
@@ -536,42 +546,38 @@ EslTcp4ConnectStart (
                   "ERROR - Port 0x%08x not connected, Status: %r\r\n",\r
                   pPort,\r
                   Status ));\r
-        //\r
-        //  Determine the errno value\r
-        //\r
-        switch ( Status ) {\r
-        default:\r
-          pSocket->errno = EIO;\r
-          break;\r
-\r
-        case EFI_OUT_OF_RESOURCES:\r
-          pSocket->errno = ENOBUFS;\r
-          break;\r
-\r
-        case EFI_TIMEOUT:\r
-          pSocket->errno = ETIMEDOUT;\r
-          break;\r
-\r
-        case EFI_NETWORK_UNREACHABLE:\r
-          pSocket->errno = ENETDOWN;\r
-          break;\r
-\r
-        case EFI_HOST_UNREACHABLE:\r
-          pSocket->errno = EHOSTUNREACH;\r
-          break;\r
-\r
-        case EFI_PORT_UNREACHABLE:\r
-        case EFI_PROTOCOL_UNREACHABLE:\r
-        case EFI_CONNECTION_REFUSED:\r
-          pSocket->errno = ECONNREFUSED;\r
-          break;\r
-\r
-        case EFI_CONNECTION_RESET:\r
-          pSocket->errno = ECONNRESET;\r
-          break;\r
-        }\r
       }\r
     }\r
+    if ( !EFI_ERROR ( Status )) {\r
+      //\r
+      //  Connection in progress\r
+      //\r
+      pSocket->errno = EINPROGRESS;\r
+      DEBUG (( DEBUG_CONNECT,\r
+                "0x%08x: Port attempting connection to %d.%d.%d.%d:%d\r\n",\r
+                pPort,\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],\r
+                pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],\r
+                pTcp4->ConfigData.AccessPoint.RemotePort ));\r
+    }\r
+    else {\r
+      //\r
+      //  Error return path is through EslTcp4ConnectComplete to\r
+      //  enable retry on other ports\r
+      //\r
+      //  Status to errno translation gets done in EslTcp4ConnectPoll\r
+      //\r
+      pTcp4->ConnectToken.CompletionToken.Status = Status;\r
+\r
+      //\r
+      //  Continue with the next port\r
+      //\r
+      gBS->CheckEvent ( pTcp4->ConnectToken.CompletionToken.Event );\r
+      gBS->SignalEvent ( pTcp4->ConnectToken.CompletionToken.Event );\r
+    }\r
+    Status = EFI_NOT_READY;\r
   }\r
   else {\r
     //\r
@@ -790,6 +796,8 @@ EslTcp4Listen (
     //  Mark the socket as configured\r
     //\r
     pSocket->bConfigured = TRUE;\r
+    Status = EFI_SUCCESS;\r
+    pSocket->errno = 0;\r
 \r
     //\r
     //  All done\r
@@ -1155,9 +1163,9 @@ EslTcp4LocalAddressSet (
     }\r
     else {\r
       pAccessPoint->SubnetMask.Addr[0] = 0xff;\r
-      pAccessPoint->SubnetMask.Addr[1] = 0xff;\r
-      pAccessPoint->SubnetMask.Addr[2] = 0xff;\r
-      pAccessPoint->SubnetMask.Addr[3] = 0xff;\r
+      pAccessPoint->SubnetMask.Addr[1] = ( 128 <= pAccessPoint->StationAddress.Addr[0]) ? 0xff : 0;\r
+      pAccessPoint->SubnetMask.Addr[2] = ( 192 <= pAccessPoint->StationAddress.Addr[0]) ? 0xff : 0;\r
+      pAccessPoint->SubnetMask.Addr[3] = ( 224 <= pAccessPoint->StationAddress.Addr[0]) ? 0xff : 0;\r
     }\r
 \r
     //\r
@@ -1171,6 +1179,7 @@ EslTcp4LocalAddressSet (
       //  Set the port number\r
       //\r
       pAccessPoint->StationPort = SwapBytes16 ( pIpAddress->sin_port );\r
+      pPort->pSocket->bAddressSet = TRUE;\r
 \r
       //\r
       //  Display the local address\r
@@ -1307,6 +1316,7 @@ EslTcp4PortAllocate (
     //  pPort->pfnRxCancel = NULL; since the UEFI implementation returns EFI_UNSUPPORTED\r
     //\r
     pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.TCPv4->Configure;\r
+    pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.TCPv4->Poll;\r
     pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv4->Receive;\r
     pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv4->Transmit;\r
 \r
@@ -1569,6 +1579,11 @@ EslTcp4Receive (
             DataLength ));\r
   CopyMem ( pBuffer, pPacket->pBuffer, DataLength );\r
 \r
+  //\r
+  //  Set the next buffer address\r
+  //\r
+  pBuffer += DataLength;\r
+\r
   //\r
   //  Determine if the data is being read\r
   //\r
@@ -2216,6 +2231,159 @@ EslTcp4TxOobComplete (
 }\r
 \r
 \r
+/**\r
+  Verify the adapter's IP address\r
+\r
+  This support routine is called by EslSocketBindTest.\r
+\r
+  @param [in] pPort       Address of an ::ESL_PORT structure.\r
+  @param [in] pConfigData Address of the configuration data\r
+\r
+  @retval EFI_SUCCESS - The IP address is valid\r
+  @retval EFI_NOT_STARTED - The IP address is invalid\r
+\r
+ **/\r
+EFI_STATUS\r
+EslTcp4VerifyLocalIpAddress (\r
+  IN ESL_PORT * pPort,\r
+  IN EFI_TCP4_CONFIG_DATA * pConfigData\r
+  )\r
+{\r
+  UINTN DataSize;\r
+  EFI_TCP4_ACCESS_POINT * pAccess;\r
+  EFI_IP4_IPCONFIG_DATA * pIpConfigData;\r
+  EFI_IP4_CONFIG_PROTOCOL * pIpConfigProtocol;\r
+  ESL_SERVICE * pService;\r
+  EFI_STATUS Status;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Use break instead of goto\r
+  //\r
+  pIpConfigData = NULL;\r
+  for ( ; ; ) {\r
+    //\r
+    //  Determine if the IP address is specified\r
+    //\r
+    pAccess = &pConfigData->AccessPoint;\r
+    DEBUG (( DEBUG_BIND,\r
+              "UseDefaultAddress: %s\r\n",\r
+              pAccess->UseDefaultAddress ? L"TRUE" : L"FALSE" ));\r
+    DEBUG (( DEBUG_BIND,\r
+              "Requested IP address: %d.%d.%d.%d\r\n",\r
+              pAccess->StationAddress.Addr [ 0 ],\r
+              pAccess->StationAddress.Addr [ 1 ],\r
+              pAccess->StationAddress.Addr [ 2 ],\r
+              pAccess->StationAddress.Addr [ 3 ]));\r
+    if ( pAccess->UseDefaultAddress\r
+      || (( 0 == pAccess->StationAddress.Addr [ 0 ])\r
+      && ( 0 == pAccess->StationAddress.Addr [ 1 ])\r
+      && ( 0 == pAccess->StationAddress.Addr [ 2 ])\r
+      && ( 0 == pAccess->StationAddress.Addr [ 3 ])))\r
+    {\r
+      Status = EFI_SUCCESS;\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Open the configuration protocol\r
+    //\r
+    pService = pPort->pService;\r
+    Status = gBS->OpenProtocol ( pService->Controller,\r
+                                 &gEfiIp4ConfigProtocolGuid,\r
+                                 (VOID **)&pIpConfigProtocol,\r
+                                 NULL,\r
+                                 NULL,\r
+                                 EFI_OPEN_PROTOCOL_GET_PROTOCOL );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - IP Configuration Protocol not available, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Get the IP configuration data size\r
+    //\r
+    DataSize = 0;\r
+    Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,\r
+                                          &DataSize,\r
+                                          NULL );\r
+    if ( EFI_BUFFER_TOO_SMALL != Status ) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Allocate the configuration data buffer\r
+    //\r
+    pIpConfigData = AllocatePool ( DataSize );\r
+    if ( NULL == pIpConfigData ) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Get the IP configuration\r
+    //\r
+    Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,\r
+                                          &DataSize,\r
+                                          pIpConfigData );\r
+    if ( EFI_ERROR ( Status )) {\r
+      DEBUG (( DEBUG_ERROR,\r
+                "ERROR - Failed to return IP Configuration data, Status: %r\r\n",\r
+                Status ));\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  Display the current configuration\r
+    //\r
+    DEBUG (( DEBUG_BIND,\r
+              "Actual adapter IP address: %d.%d.%d.%d\r\n",\r
+              pIpConfigData->StationAddress.Addr [ 0 ],\r
+              pIpConfigData->StationAddress.Addr [ 1 ],\r
+              pIpConfigData->StationAddress.Addr [ 2 ],\r
+              pIpConfigData->StationAddress.Addr [ 3 ]));\r
+\r
+    //\r
+    //  Assume the port is not configured\r
+    //\r
+    Status = EFI_SUCCESS;\r
+    if (( pAccess->StationAddress.Addr [ 0 ] == pIpConfigData->StationAddress.Addr [ 0 ])\r
+      && ( pAccess->StationAddress.Addr [ 1 ] == pIpConfigData->StationAddress.Addr [ 1 ])\r
+      && ( pAccess->StationAddress.Addr [ 2 ] == pIpConfigData->StationAddress.Addr [ 2 ])\r
+      && ( pAccess->StationAddress.Addr [ 3 ] == pIpConfigData->StationAddress.Addr [ 3 ])) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    //  The IP address did not match\r
+    //\r
+    Status = EFI_NOT_STARTED;\r
+    break;\r
+  }\r
+\r
+  //\r
+  //  Free the buffer if necessary\r
+  //\r
+  if ( NULL != pIpConfigData ) {\r
+    FreePool ( pIpConfigData );\r
+  }\r
+\r
+  //\r
+  //  Return the IP address status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
 /**\r
   Interface between the socket layer and the network specific\r
   code that supports SOCK_STREAM and SOCK_SEQPACKET sockets\r
@@ -2255,5 +2423,6 @@ CONST ESL_PROTOCOL_API cEslTcp4Api = {
   EslTcp4RxStart,\r
   EslTcp4TxBuffer,\r
   EslTcp4TxComplete,\r
-  EslTcp4TxOobComplete\r
+  EslTcp4TxOobComplete,\r
+  (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslTcp4VerifyLocalIpAddress\r
 };\r