VBoxServiceVMInfo.cpp revision 45005135e38aa4b7dfcc20dd2358f7e2586753ed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VBoxService - Virtual Machine Information for the Host.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Copyright (C) 2009-2013 Oracle Corporation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * available from http://www.virtualbox.org. This file is free software;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * you can redistribute it and/or modify it under the terms of the GNU
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * General Public License (GPL) as published by the Free Software
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*******************************************************************************
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync* Header Files *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*******************************************************************************/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync# ifdef TARGET_NT4 /* HACK ALERT! PMIB_IPSTATS undefined if 0x0400 with newer SDKs. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync# if !defined(RT_OS_OS2) && !defined(RT_OS_FREEBSD) && !defined(RT_OS_HAIKU)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync# include <utmpx.h> /* @todo FreeBSD 9 should have this. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync# if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** Structure containing information about a location awarness
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * client provided by the host. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @todo Move this (and functions) into VbglR3. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} VBOXSERVICELACLIENTINFO, *PVBOXSERVICELACLIENTINFO;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*******************************************************************************
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync* Global Variables *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*******************************************************************************/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** The vminfo interval (milliseconds). */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** The semaphore we're blocking on. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic RTSEMEVENTMULTI g_hVMInfoEvent = NIL_RTSEMEVENTMULTI;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** The guest property service client ID. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** Number of currently logged in users in OS. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** The guest property cache. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *g_pszPropCacheValLoggedInUsersList = "/VirtualBox/GuestInfo/OS/LoggedInUsersList";
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *g_pszPropCacheValLoggedInUsers = "/VirtualBox/GuestInfo/OS/LoggedInUsers";
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *g_pszPropCacheValNoLoggedInUsers = "/VirtualBox/GuestInfo/OS/NoLoggedInUsers";
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *g_pszPropCacheValNetCount = "/VirtualBox/GuestInfo/Net/Count";
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** A guest user's guest property root key. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *g_pszPropCacheValUser = "/VirtualBox/GuestInfo/User/";
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** The VM session ID. Changes whenever the VM is restored or reset. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** The last attached locartion awareness (LA) client timestamp. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** The current LA client info. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** User idle threshold. This specifies the minimum time a user is considered
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * being idle and then will be reported to the host. Default is 5s. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*******************************************************************************
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*******************************************************************************/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *g_pszLAActiveClient = "/VirtualBox/HostInfo/VRDP/ActiveClient";
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** ConsoleKit defines (taken from 0.4.5). */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Signals the event so that a re-enumeration of VM-specific
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * information (like logged in users) can happen.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @return IPRT status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Trigger a re-enumeration of all logged-in users by unblocking
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the multi event semaphore of the VMInfo thread. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @copydoc VBOXSERVICE::pfnPreInit */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(int) VBoxServiceVMInfoPreInit(void)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @copydoc VBOXSERVICE::pfnOption */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(int) VBoxServiceVMInfoOption(const char **ppszShort, int argc, char **argv, int *pi)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /** @todo Use RTGetOpt here. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* no short options */;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else if (!strcmp(argv[*pi], "--vminfo-user-idle-threshold"))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @copydoc VBOXSERVICE::pfnInit */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic DECLCALLBACK(int) VBoxServiceVMInfoInit(void)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * If not specified, find the right interval default.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Then create the event sem to block on.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Set it to 5s by default for location awareness checks. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* The status code is ignored as this information is not available with VBox < 3.2.10. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Initialize the LA client object. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = VbglR3GuestPropConnect(&g_uVMInfoGuestPropSvcClientID);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBoxServiceVerbose(3, "Property Service Client ID: %#x\n", g_uVMInfoGuestPropSvcClientID);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* If the service was not found, we disable this service without
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync causing VBoxService to fail. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (rc == VERR_HGCM_SERVICE_NOT_FOUND) /* Host service is not available. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBoxServiceVerbose(0, "Guest property service is not available, disabling the service\n");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBoxServiceError("Failed to connect to the guest property service! Error: %Rrc\n", rc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBoxServicePropCacheCreate(&g_VMInfoPropCache, g_uVMInfoGuestPropSvcClientID);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Declare some guest properties with flags and reset values.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rc2 = VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, g_pszPropCacheValLoggedInUsersList,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBOXSERVICEPROPCACHEFLAG_TEMPORARY | VBOXSERVICEPROPCACHEFLAG_TRANSIENT, NULL /* Delete on exit */);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VBoxServiceError("Failed to init property cache value \"%s\", rc=%Rrc\n", g_pszPropCacheValLoggedInUsersList, rc2);
VBoxServiceError("Failed to init property cache value \"%s\", rc=%Rrc\n", g_pszPropCacheValLoggedInUsers, rc2);
VBoxServiceError("Failed to init property cache value \"%s\", rc=%Rrc\n", g_pszPropCacheValNoLoggedInUsers, rc2);
VBOXSERVICEPROPCACHEFLAG_TEMPORARY | VBOXSERVICEPROPCACHEFLAG_ALWAYS_UPDATE, NULL /* Delete on exit */);
VBoxServiceError("Failed to init property cache value \"%s\", rc=%Rrc\n", g_pszPropCacheValNetCount, rc2);
char *pszValue;
rc2 = VBoxServiceReadHostProp(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestAdd/VBoxService/--vminfo-user-idle-threshold", true /* Read only */,
return rc;
int rc;
return rc;
char *pszAttach;
return rc;
if (pClient)
int vboxServiceUserUpdateF(PVBOXSERVICEVEPROPCACHE pCache, const char *pszUser, const char *pszDomain,
char *pszName;
if (pszDomain)
&& pszValueFormat)
&& !pszValue)
return rc;
static void vboxserviceVMInfoWriteFixedProperties(void)
char *pszAddVer;
char *pszAddVerExt;
char *pszAddRev;
#ifdef RT_OS_WINDOWS
char *pszInstDir;
int first_arg_type,
return ret;
static int vboxserviceVMInfoWriteUsers(void)
#ifdef RT_OS_WINDOWS
# ifndef TARGET_NT4
setutxent();
bool fFound = false;
if (!fFound)
cUsersInList++;
#ifdef VBOX_WITH_DBUS
if ( pConnection
if ( pMsgSessions
&dbErr);
if ( pReplySessions
for (ppszCurSession;
bool fActive = false;
if ( pMsgSessionActive
&dbErr);
if ( pReplySessionActive
int val;
if (pReplySessionActive)
if (pMsgSessionActive)
* (e.g. "/org/freedesktop/ConsoleKit/Session1"). */
if ( fActive
&& pMsgUnixUser
&dbErr);
if ( pReplyUnixUser
/** @todo Add support for getting UID_MIN (/etc/login.defs on
setpwent();
if ( ppwEntry
bool fFound = false;
if (!fFound)
cUsersInList++;
if (pReplyUnixUser)
if (pMsgUnixUser)
if (pMsgSessions)
static int s_iBitchedAboutConsoleKit = 0;
if (pMsgSessions)
static int s_iBitchedAboutDBus = 0;
if ( pConnection
static int s_iVMInfoBitchedOOM = 0;
VBoxServiceVerbose(0, "Warning: Not enough memory available to enumerate users! Keeping old value (%RU32)\n",
cUsersInList = 0;
if (pszUserList)
rc = VBoxServicePropCacheUpdate(&g_VMInfoPropCache, g_pszPropCacheValLoggedInUsersList, "%s", pszUserList);
rc = VBoxServicePropCacheUpdate(&g_VMInfoPropCache, g_pszPropCacheValLoggedInUsers, "%RU32", cUsersInList);
if (pszUserList)
return rc;
static int vboxserviceVMInfoWriteNetwork(void)
#ifdef RT_OS_WINDOWS
# ifndef TARGET_NT4
if (!pAdpInfo)
return VERR_NO_MEMORY;
if (pAdpInfoNew)
if (pAdpInfo)
if (pAdpInfo)
unsigned long nBytesReturned = 0;
sizeof(InterfaceList),
0) == SOCKET_ERROR)
if (pAdpInfo)
for (int i = 0; i < cIfacesSystem; ++i)
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%RU32/V4/IP", cIfacesReport);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%RU32/V4/Broadcast", cIfacesReport);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%RU32/V4/Netmask", cIfacesReport);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%RU32/Status", cIfacesReport);
# ifndef TARGET_NT4
if (pAdp)
if (pAdpInfo)
if (sd >= 0)
return VERR_NOT_IMPLEMENTED;
if (rc < 0)
return rc;
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%RU32/V4/IP", cIfacesReport);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%RU32/V4/Broadcast", cIfacesReport);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%RU32/V4/Netmask", cIfacesReport);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%RU32/Status", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, pIfCurr->ifa_flags & IFF_UP ? "Up" : "Down");
if (sd < 0)
return rc;
return rc;
for (int i = 0; i < cIfacesSystem; ++i)
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%RU32/V4/IP", cIfacesReport);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%RU32/V4/Broadcast", cIfacesReport);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%RU32/V4/Netmask", cIfacesReport);
# if defined(RT_OS_SOLARIS)
VBoxServiceVerbose(2, "VMInfo/Network: Interface %d has no assigned IP address, skipping ...\n", i);
# if defined(RT_OS_SOLARIS)
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%RU32/Status", cIfacesReport);
VBoxServiceError("VMInfo/Network: Network enumeration for interface %RU32 failed with error %Rrc\n", cIfacesReport, rc);
rc = VBoxServiceReadPropUInt32(g_uVMInfoGuestPropSvcClientID, g_pszPropCacheValNetCount, &cIfacesReportOld,
VBoxServiceVerbose(3, "VMInfo/Network: Stale interface data detected (%RU32 old vs. %RU32 current)\n",
VBoxServiceVerbose(3, "VMInfo/Network: Deleting stale data of interface %d ...\n", uIfaceDeleteIdx);
rc = VBoxServicePropCacheUpdateByPath(&g_VMInfoPropCache, NULL /* Value, delete */, 0 /* Flags */, "/VirtualBox/GuestInfo/Net/%RU32", uIfaceDeleteIdx++);
VBoxServiceError("VMInfo/Network: Failed retrieving old network interfaces count with error %Rrc\n", rc);
return VINF_SUCCESS;
int rc;
#ifdef RT_OS_WINDOWS
VBoxServiceError("VMInfo/Network: WSAStartup failed! Error: %Rrc\n", RTErrConvertFromWin32(WSAGetLastError()));
bool fWait = true;
int rc2 = VBoxServiceReadHostProp(g_uVMInfoGuestPropSvcClientID, g_pszLAActiveClient, true /* Read only */,
&& ( !g_LAClientAttachedTS
fWait = false;
static int s_iBitchedAboutLAClientInfo = 0;
if (pszAttach)
static int s_iBitchedAboutLAClient = 0;
if (*pfShutdown)
if (fWait)
if (*pfShutdown)
#ifdef RT_OS_WINDOWS
WSACleanup();
return rc;