Exemplo n.º 1
0
static Bool
SetCustomizationStatusInVmxEx(int customizationState,
                              int errCode,
                              const char* errMsg,
                              char   *vmxResponse,
                              size_t *vmxResponseLength,
                              size_t  responseBufferSize)
{
   char   *msg = NULL;
   char   *response = NULL;
   size_t  responseLength = 0;
   Bool success;

   if (errMsg) {
      msg = malloc(strlen(CABCOMMANDLOG) + 1 + strlen(errMsg) + 1);
      strcpy (msg, CABCOMMANDLOG);
      strcat (msg, "@");
      strcat (msg, errMsg);
   } else {
      msg = malloc(strlen(CABCOMMANDLOG) + 1);
      strcpy (msg, CABCOMMANDLOG);
   }

   success = RpcChannel_SendOne(vmxResponse != NULL ? &response : NULL,
                                vmxResponse != NULL ? &responseLength : NULL,
                                "deployPkg.update.state %d %d %s",
                                customizationState,
                                errCode,
                                msg);
   free (msg);

   if (vmxResponse != NULL) {
      if (response != NULL) {
         sLog(log_debug, "Got VMX response '%s'", response);
         if (responseLength > responseBufferSize - 1) {
            sLog(log_warning,
                 "The VMX response is too long (only %d chars are allowed)",
                 responseBufferSize - 1);
            responseLength = responseBufferSize - 1;
         }
         memcpy(vmxResponse, response, responseLength);
         free(response);
      }
      else {
         sLog(log_debug, "Got no VMX response");
         responseLength = 0;
      }
      vmxResponse[responseLength] = 0;
      if (vmxResponseLength != NULL) {
         *vmxResponseLength = responseLength;
      }
   }

   if (!success) {
      sLog(log_error, "Unable to set customization status in vmx.\n");
   }

   return success;
}
Exemplo n.º 2
0
static VMGuestLibError
VMGuestLibUpdateInfo(VMGuestLibHandle handle) // IN
{
   char *reply = NULL;
   size_t replyLen;
   VMGuestLibError ret = VMGUESTLIB_ERROR_INVALID_ARG;
   uint32 hostVersion = HANDLE_VERSION(handle);

   /* 
    * Starting with the highest supported protocol (major) version, negotiate
    * down to the highest host supported version. Host supports minimum version
    * 2.
    */
   if (hostVersion == 0) {
      hostVersion = VMGUESTLIB_DATA_VERSION;
   }

   do {
      char commandBuf[64];
      unsigned int index = 0;

      /* Free the last reply when retrying. */
      free(reply);
      reply = NULL;

      /*
       * Construct command string with the command name and the version
       * of the data struct that we want.
       */
      Str_Sprintf(commandBuf, sizeof commandBuf, "%s %d",
                  VMGUESTLIB_BACKDOOR_COMMAND_STRING,
                  hostVersion);

      /* Send the request. */
      if (RpcChannel_SendOne(&reply, &replyLen, commandBuf)) {
         VMGuestLibDataV2 *v2reply = (VMGuestLibDataV2 *)reply;
         VMSessionId sessionId = HANDLE_SESSIONID(handle);

         ASSERT(hostVersion == v2reply->hdr.version);

         if (sessionId != 0 && sessionId != v2reply->hdr.sessionId) {
            /* Renegotiate protocol if sessionId changed. */
            hostVersion = VMGUESTLIB_DATA_VERSION;
            HANDLE_SESSIONID(handle) = 0;
            continue;
         }
         ret = VMGUESTLIB_ERROR_SUCCESS;
         break;
      }

      /* 
       * Host is older and doesn't support the requested protocol version.
       * Request the highest version the host supports.
       */
      Debug("Failed to retrieve info: %s\n", reply ? reply : "NULL");

      if (hostVersion == 2 ||
          Str_Strncmp(reply, "Unknown command", sizeof "Unknown command") == 0) {
         /* 
          * Host does not support this feature. Older (v2) host would return
          * "Unsupported version" if it doesn't recognize the requested version.
          *
          * XXX: Maybe use another error code for this case where the host
          * product doesn't support this feature?
          */
         ret = VMGUESTLIB_ERROR_NOT_ENABLED;
         break;
      } else if (hostVersion == 3) {
         /*
          * Host supports v2 at a minimum. If request for v3 fails, then just use
          * v2, since v2 host does not send the highest supported version in the
          * reply.
          */
         hostVersion = 2;
         HANDLE_SESSIONID(handle) = 0;
         continue;
      } else if (!StrUtil_GetNextUintToken(&hostVersion, &index, reply, ":")) {
         /*
          * v3 and onwards, the host returns the highest major version it supports,
          * if the requested version is not supported. So parse out the host
          * version from the reply and return error if it didn't.
          */
         Debug("Bad reply received from host.\n");
         ret = VMGUESTLIB_ERROR_OTHER;
         break;
      }
      ASSERT(hostVersion < VMGUESTLIB_DATA_VERSION);
   } while (ret != VMGUESTLIB_ERROR_SUCCESS);

   if (ret != VMGUESTLIB_ERROR_SUCCESS) {
      goto done;
   }

   /* Sanity check the results. */
   if (replyLen < sizeof hostVersion) {
      Debug("Unable to retrieve version\n");
      ret = VMGUESTLIB_ERROR_OTHER;
      goto done;
   }

   if (hostVersion == 2) {
      VMGuestLibDataV2 *v2reply = (VMGuestLibDataV2 *)reply;
      size_t dataSize = sizeof *v2reply;

      /* More sanity checks. */
      if (v2reply->hdr.version != hostVersion) {
         Debug("Incorrect data version returned\n");
         ret = VMGUESTLIB_ERROR_OTHER;
         goto done;
      }
      if (replyLen != dataSize) {
         Debug("Incorrect data size returned\n");
         ret = VMGUESTLIB_ERROR_OTHER;
         goto done;
      }

      /* Store the reply in the handle. */
      HANDLE_VERSION(handle) = v2reply->hdr.version;
      HANDLE_SESSIONID(handle) = v2reply->hdr.sessionId;
      if (HANDLE_DATASIZE(handle) < dataSize) {
         /* [Re]alloc if the local handle buffer is not big enough. */
         free(HANDLE_DATA(handle));
         HANDLE_DATA(handle) = Util_SafeCalloc(1, dataSize);
         HANDLE_DATASIZE(handle) = dataSize;
      }
      memcpy(HANDLE_DATA(handle), reply, replyLen);

      /* Make sure resourcePoolPath is NUL terminated. */
      v2reply = HANDLE_DATA(handle);
      v2reply->resourcePoolPath.value[sizeof v2reply->resourcePoolPath.value - 1] = '\0';
      ret = VMGUESTLIB_ERROR_SUCCESS;
   } else if (hostVersion == 3) {
      VMGuestLibDataV3 *v3reply = (VMGuestLibDataV3 *)reply;
      size_t dataSize;
      XDR xdrs;
      GuestLibV3StatCount count;
      VMGuestLibStatisticsV3 *v3stats;

      /* More sanity checks. */
      if (v3reply->hdr.version != hostVersion) {
         Debug("Incorrect data version returned\n");
         ret = VMGUESTLIB_ERROR_OTHER;
         goto done;
      }
      if (replyLen < sizeof *v3reply) {
         Debug("Incorrect data size returned\n");
         ret = VMGUESTLIB_ERROR_OTHER;
         goto done;
      }

      /* 0. Copy the reply version and sessionId to the handle. */
      HANDLE_VERSION(handle) = v3reply->hdr.version;
      HANDLE_SESSIONID(handle) = v3reply->hdr.sessionId;

      /* 
       * 1. Retrieve the length of the statistics array from the XDR encoded
       * part of the reply.
       */
      xdrmem_create(&xdrs, v3reply->data, v3reply->dataSize, XDR_DECODE);

      if (!xdr_GuestLibV3StatCount(&xdrs, &count)) {
         xdr_destroy(&xdrs);
         goto done;
      }
      if (count >= GUESTLIB_MAX_STATISTIC_ID) {
         /* 
          * Host has more than we can process. So process only what this side
          * can.
          */
         count = GUESTLIB_MAX_STATISTIC_ID - 1;
      }

      /* 2. [Re]alloc if the local handle buffer is not big enough. */
      dataSize = sizeof *v3stats + (count * sizeof (GuestLibV3Stat));
      if (HANDLE_DATASIZE(handle) < dataSize) {
         free(HANDLE_DATA(handle));
         HANDLE_DATA(handle) = Util_SafeCalloc(1, dataSize);
         HANDLE_DATASIZE(handle) = dataSize;
      }

      /* 3. Unmarshal the array of statistics. */
      v3stats = HANDLE_DATA(handle);
      v3stats->numStats = count;
      for (count = 0; count < v3stats->numStats; count++) {
         GuestLibV3TypeIds statId = count + 1;

         /* Unmarshal the statistic. */
         if (!xdr_GuestLibV3Stat(&xdrs, &v3stats->stats[count])) {
            break;
         }

         /* Host sends all the V3 statistics it supports, in order. */
         if (v3stats->stats[count].d != statId) {
            break;
         }
      }
      if (count >= v3stats->numStats) {
         ret = VMGUESTLIB_ERROR_SUCCESS;
      } else {
         /* 
          * Error while unmarshalling. Deep-free already unmarshalled
          * statistics and invalidate the data in the handle.
          */
         GuestLibV3StatCount c;

         for (c = 0; c < count; c++) {
            VMX_XDR_FREE(xdr_GuestLibV3Stat, &v3stats->stats[c]);
         }
         HANDLE_SESSIONID(handle) = 0;
      }

      /* 4. Free resources. */
      xdr_destroy(&xdrs);
   } else {
      /*
       * Host should never reply with a higher version protocol than requested.
       */
      ret = VMGUESTLIB_ERROR_OTHER;
   }

done:
   free(reply);
   return ret;
}