VMGuestLibError VMGuestLib_CloseHandle(VMGuestLibHandle handle) // IN { void *data; if (NULL == handle) { return VMGUESTLIB_ERROR_INVALID_HANDLE; } data = HANDLE_DATA(handle); if (data != NULL && HANDLE_SESSIONID(handle) != 0 && HANDLE_VERSION(handle) == 3) { VMGuestLibStatisticsV3 *v3stats = data; GuestLibV3StatCount count; for (count = 0; count < v3stats->numStats; count++) { VMX_XDR_FREE(xdr_GuestLibV3Stat, &v3stats->stats[count]); } } free(data); /* Be paranoid. */ HANDLE_DATA(handle) = NULL; free(handle); return VMGUESTLIB_ERROR_SUCCESS; }
static gboolean TestDebugValidateRpc3(RpcInData *data, gboolean ret) { TestPluginData pdata = { NULL, }; CU_ASSERT(XdrUtil_Deserialize(data->result, data->resultLen, xdr_TestPluginData, &pdata)); CU_ASSERT_STRING_EQUAL(pdata.data, "Hello World!"); CU_ASSERT_EQUAL(pdata.f_int, 8642); CU_ASSERT(pdata.f_bool); VMX_XDR_FREE(xdr_TestPluginData, &pdata); return ret; }
Bool XdrUtil_Deserialize(const void *data, // IN size_t dataLen, // IN void *xdrProc, // IN void *dest) // IN { Bool ret; xdrproc_t proc = xdrProc; XDR xdrs; ASSERT(data != NULL); ASSERT(xdrProc != NULL); ASSERT(dest != NULL); xdrmem_create(&xdrs, (char *) data, dataLen, XDR_DECODE); ret = (Bool) proc(&xdrs, dest, 0); xdr_destroy(&xdrs); if (!ret) { VMX_XDR_FREE(proc, dest); } return ret; }
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; }
static Bool RecordResolverInfo(NicInfoV3 *nicInfo) // OUT { DnsConfigInfo *dnsConfigInfo = NULL; char namebuf[DNSINFO_MAX_ADDRLEN + 1]; char **s; if (res_init() == -1) { return FALSE; } dnsConfigInfo = Util_SafeCalloc(1, sizeof *dnsConfigInfo); /* * Copy in the host name. not this */ if (!GuestInfoGetFqdn(sizeof namebuf, namebuf)) { goto fail; } dnsConfigInfo->hostName = Util_SafeCalloc(1, sizeof *dnsConfigInfo->hostName); *dnsConfigInfo->hostName = Util_SafeStrdup(namebuf); /* * Repeat with the domain name. not this */ dnsConfigInfo->domainName = Util_SafeCalloc(1, sizeof *dnsConfigInfo->domainName); *dnsConfigInfo->domainName = Util_SafeStrdup(_res.defdname); /* * Name servers. */ RecordResolverNS(dnsConfigInfo); /* * Search suffixes. */ for (s = _res.dnsrch; *s; s++) { DnsHostname *suffix; /* Check to see if we're going above our limit. See bug 605821. */ if (dnsConfigInfo->searchSuffixes.searchSuffixes_len == DNSINFO_MAX_SUFFIXES) { g_message("%s: dns search suffix limit (%d) reached, skipping overflow.", __FUNCTION__, DNSINFO_MAX_SUFFIXES); break; } suffix = XDRUTIL_ARRAYAPPEND(dnsConfigInfo, searchSuffixes, 1); ASSERT_MEM_ALLOC(suffix); *suffix = Util_SafeStrdup("test suffix"); } /* * "Commit" dnsConfigInfo to nicInfo. */ nicInfo->dnsConfigInfo = dnsConfigInfo; return TRUE; fail: VMX_XDR_FREE(xdr_DnsConfigInfo, dnsConfigInfo); free(dnsConfigInfo); return FALSE; }
static gboolean RpcDebugSend(RpcChannel *chan, char const *data, size_t dataLen, char **result, size_t *resultLen) { char *copy; gpointer xdrdata = NULL; DbgChannelData *cdata = chan->_private; RpcDebugPlugin *plugin = cdata->plugin; RpcDebugRecvMapping *mapping = NULL; RpcDebugRecvFn recvFn = NULL; gboolean ret = TRUE; ASSERT(cdata->ctx != NULL); /* Be paranoid. Like the VMX, NULL-terminate the incoming data. */ copy = g_malloc(dataLen + 1); memcpy(copy, data, dataLen); copy[dataLen] = '\0'; /* Try to find a mapping the the command in the RPC. */ if (plugin->recvFns) { char *cmd; unsigned int idx = 0; cmd = StrUtil_GetNextToken(&idx, copy, " "); if (cmd != NULL) { RpcDebugRecvMapping *test; for (test = plugin->recvFns; test->name != NULL; test++) { if (strcmp(test->name, cmd) == 0) { mapping = test; break; } } } vm_free(cmd); } if (mapping != NULL) { recvFn = mapping->recvFn; if (mapping->xdrProc != NULL) { char *start; ASSERT(mapping->xdrSize > 0); /* Find out where the XDR data starts. */ start = strchr(copy, ' '); if (start == NULL) { RpcDebug_SetResult("Can't find command delimiter.", result, resultLen); ret = FALSE; goto exit; } start++; xdrdata = g_malloc0(mapping->xdrSize); if (!XdrUtil_Deserialize(start, dataLen - (start - copy), mapping->xdrProc, xdrdata)) { RpcDebug_SetResult("XDR deserialization failed.", result, resultLen); ret = FALSE; goto exit; } } } else { recvFn = plugin->dfltRecvFn; } if (recvFn != NULL) { ret = recvFn((xdrdata != NULL) ? xdrdata : copy, dataLen, result, resultLen); } else { RpcDebug_SetResult("", result, resultLen); } exit: if (xdrdata != NULL) { VMX_XDR_FREE(mapping->xdrProc, xdrdata); g_free(xdrdata); } g_free(copy); return ret; }
static Bool RpcChannelXdrWrapper(RpcInData *data, RpcChannelCallback *rpc) { Bool ret; RpcInData copy; void *xdrData = NULL; if (rpc->xdrIn != NULL) { xdrData = malloc(rpc->xdrInSize); if (xdrData == NULL) { ret = RPCIN_SETRETVALS(data, "Out of memory.", FALSE); goto exit; } memset(xdrData, 0, rpc->xdrInSize); if (!XdrUtil_Deserialize(data->args + 1, data->argsSize - 1, rpc->xdrIn, xdrData)) { ret = RPCIN_SETRETVALS(data, "XDR deserialization failed.", FALSE); free(xdrData); goto exit; } copy.name = data->name; copy.args = xdrData; copy.argsSize = rpc->xdrInSize; copy.result = data->result; copy.resultLen = data->resultLen; copy.freeResult = data->freeResult; copy.appCtx = data->appCtx; copy.clientData = rpc->clientData; } else { memcpy(©, data, sizeof copy); } ret = rpc->callback(©); if (rpc->xdrIn != NULL) { VMX_XDR_FREE(rpc->xdrIn, xdrData); free(xdrData); copy.args = NULL; data->result = copy.result; data->resultLen = copy.resultLen; data->freeResult = copy.freeResult; } if (rpc->xdrOut != NULL && copy.result != NULL) { XDR xdrs; xdrproc_t xdrProc = rpc->xdrOut; if (DynXdr_Create(&xdrs) == NULL) { ret = RPCIN_SETRETVALS(data, "Out of memory.", FALSE); goto exit; } if (!xdrProc(&xdrs, copy.result)) { ret = RPCIN_SETRETVALS(data, "XDR serialization failed.", FALSE); DynXdr_Destroy(&xdrs, TRUE); goto exit; } if (copy.freeResult) { VMX_XDR_FREE(rpc->xdrOut, copy.result); } data->result = DynXdr_Get(&xdrs); data->resultLen = XDR_GETPOS(&xdrs); data->freeResult = TRUE; DynXdr_Destroy(&xdrs, FALSE); } exit: if (copy.freeResult && copy.result != NULL) { g_free(copy.result); } return ret; }