VBoxServiceVMInfo.cpp revision 2caae01fb624524a93d8322500214c42d9038b74
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * VBoxService - Virtual Machine Information for the Host.
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2009-2010 Oracle Corporation
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * available from http://www.virtualbox.org. This file is free software;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync/*******************************************************************************
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync* Header Files *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync*******************************************************************************/
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync# include <utmpx.h> /* @todo FreeBSD 9 should have this. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/*******************************************************************************
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync* Global Variables *
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync*******************************************************************************/
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/** The vminfo interval (millseconds). */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/** The semaphore we're blocking on. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncstatic RTSEMEVENTMULTI g_hVMInfoEvent = NIL_RTSEMEVENTMULTI;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/** The guest property service client ID. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/** Number of logged in users in OS. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncstatic uint32_t g_cVMInfoLoggedInUsers = UINT32_MAX;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/** The guest property cache. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/** @copydoc VBOXSERVICE::pfnPreInit */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncstatic DECLCALLBACK(int) VBoxServiceVMInfoPreInit(void)
5b0a093ca572a855886faa6747ad46df859dd041vboxsync/** @copydoc VBOXSERVICE::pfnOption */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncstatic DECLCALLBACK(int) VBoxServiceVMInfoOption(const char **ppszShort, int argc, char **argv, int *pi)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /* no short options */;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync/** @copydoc VBOXSERVICE::pfnInit */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncstatic DECLCALLBACK(int) VBoxServiceVMInfoInit(void)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * If not specified, find the right interval default.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Then create the event sem to block on.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync rc = VbglR3GuestPropConnect(&g_uVMInfoGuestPropSvcClientID);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServiceVerbose(3, "VMInfo: Property Service Client ID: %#x\n", g_uVMInfoGuestPropSvcClientID);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /* If the service was not found, we disable this service without
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync causing VBoxService to fail. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync if (rc == VERR_HGCM_SERVICE_NOT_FOUND) /* Host service is not available. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServiceVerbose(0, "VMInfo: Guest property service is not available, disabling the service\n");
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync VBoxServiceError("VMInfo: Failed to connect to the guest property service! Error: %Rrc\n", rc);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheCreate(&g_VMInfoPropCache, g_uVMInfoGuestPropSvcClientID);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Declare some guest properties with flags and reset values.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList",
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBOXSERVICEPROPCACHEFLAG_TEMPORARY, NULL /* Delete on exit */);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsers",
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers",
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/Net/Count",
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBOXSERVICEPROPCACHEFLAG_TEMPORARY | VBOXSERVICEPROPCACHEFLAG_ALWAYS_UPDATE, NULL /* Delete on exit */);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Writes the properties that won't change while the service is running.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Errors are ignored.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncstatic void vboxserviceVMInfoWriteFixedProperties(void)
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync * First get OS information that won't change.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync int rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szInfo, sizeof(szInfo));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Product",
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szInfo, sizeof(szInfo));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Release",
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szInfo, sizeof(szInfo));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Version",
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync rc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szInfo, sizeof(szInfo));
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/ServicePack",
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync * Retrieve version information about Guest Additions and installed files (components).
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync rc = VbglR3GetAdditionsVersion(&pszAddVer, &pszAddRev);
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestAdd/Version",
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestAdd/Revision",
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Do windows specific properties.
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync rc = VbglR3GetAdditionsInstallationPath(&pszInstDir);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestAdd/InstallDir",
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServiceWinGetComponentVersions(g_uVMInfoGuestPropSvcClientID);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Provide information about active users.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync rc = VBoxServiceVMInfoWinWriteUsers(&pszUserList, &cUsersInList);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /** @todo FreeBSD: Port logged on user info retrival.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * However, FreeBSD 9 supports utmpx, so we could use the code
5b0a093ca572a855886faa6747ad46df859dd041vboxsync * block below (?). */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /** @todo OS/2: Port logged on (LAN/local/whatever) user info retrival. */
830a019ad79a45e6bf7a5419efd5a729a36e599evboxsync /* Allocate a first array to hold 32 users max. */
830a019ad79a45e6bf7a5419efd5a729a36e599evboxsync char **papszUsers = (char **)RTMemAllocZ(cListSize * sizeof(char *));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /* Process all entries in the utmp file. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServiceVerbose(4, "VMInfo: Found logged in user \"%s\"\n", ut_user->ut_user);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync void *pvNew = RTMemRealloc(papszUsers, cListSize * sizeof(char*));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /* Make sure we don't add user names which are not
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * part of type USER_PROCESS. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync bool fFound = false;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync for (uint32_t i = 0; i < cUsersInList && !fFound; i++)
5b0a093ca572a855886faa6747ad46df859dd041vboxsync fFound = strcmp(papszUsers[i], ut_user->ut_user) == 0;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync rc = RTStrDupEx(&papszUsers[cUsersInList], (const char *)ut_user->ut_user);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /* Calc the string length. */
5b0a093ca572a855886faa6747ad46df859dd041vboxsync /* Build the user list. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync if (i != 0)
5b0a093ca572a855886faa6747ad46df859dd041vboxsync /* Cleanup. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync Assert(RT_FAILURE(rc) || cUsersInList == 0 || (pszUserList && *pszUserList));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", "%s", pszUserList);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", NULL);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsers", "%u", cUsersInList);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers",
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Provide information about the guest network.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pAdpInfo = (IP_ADAPTER_INFO *)RTMemAlloc(cbAdpInfo);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServiceError("VMInfo/Network: Failed to allocate IP_ADAPTER_INFO\n");
5b0a093ca572a855886faa6747ad46df859dd041vboxsync DWORD dwRet = GetAdaptersInfo(pAdpInfo, &cbAdpInfo);
4e47bb772df0d04d1ded3e06354de547d52e2d06vboxsync IP_ADAPTER_INFO *pAdpInfoNew = (IP_ADAPTER_INFO*)RTMemRealloc(pAdpInfo, cbAdpInfo);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServiceError("VMInfo/Network: Failed to get adapter info: Error %d\n", dwRet);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServiceError("VMInfo/Network: Failed to get a socket: Error %d\n", WSAGetLastError());
5b0a093ca572a855886faa6747ad46df859dd041vboxsync unsigned long nBytesReturned = 0;
5b0a093ca572a855886faa6747ad46df859dd041vboxsync VBoxServiceError("VMInfo/Network: Failed to WSAIoctl() on socket: Error: %d\n", WSAGetLastError());
5b0a093ca572a855886faa6747ad46df859dd041vboxsync int cIfacesSystem = nBytesReturned / sizeof(INTERFACE_INFO);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /** @todo Use GetAdaptersInfo() and GetAdapterAddresses (IPv4 + IPv6) for more information. */
5b0a093ca572a855886faa6747ad46df859dd041vboxsync for (int i = 0; i < cIfacesSystem; ++i)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync if (InterfaceList[i].iiFlags & IFF_LOOPBACK) /* Skip loopback device. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pAddress = (sockaddr_in *)&(InterfaceList[i].iiAddress);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szIp, sizeof(szIp), "%s", inet_ntoa(pAddress->sin_addr));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/IP", cIfacesReport);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szIp);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pAddress = (sockaddr_in *) & (InterfaceList[i].iiBroadcastAddress);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Broadcast", cIfacesReport);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pAddress = (sockaddr_in *)&(InterfaceList[i].iiNetmask);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Netmask", cIfacesReport);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/Status", cIfacesReport);
4e47bb772df0d04d1ded3e06354de547d52e2d06vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, nFlags & IFF_UP ? "Up" : "Down");
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync if (!strcmp(pAdp->IpAddressList.IpAddress.String, szIp))
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/MAC", cIfacesReport);
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync RTStrPrintf(szMac, sizeof(szMac), "%02X%02X%02X%02X%02X%02X",
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pAdp->Address[0], pAdp->Address[1], pAdp->Address[2],
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pAdp->Address[3], pAdp->Address[4], pAdp->Address[5]);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szMac);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, NULL);
5b0a093ca572a855886faa6747ad46df859dd041vboxsync /* Get all available interfaces */
5b0a093ca572a855886faa6747ad46df859dd041vboxsync VBoxServiceError("VMInfo/Network: Failed to get all interfaces: Error %d\n", errno);
5b0a093ca572a855886faa6747ad46df859dd041vboxsync /* Loop through all interfaces and set the data. */
5b0a093ca572a855886faa6747ad46df859dd041vboxsync for (struct ifaddrs *pIfCurr = pIfHead; pIfCurr; pIfCurr = pIfCurr->ifa_next)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * Only AF_INET and no loopback interfaces
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * @todo: IPv6 interfaces
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync getnameinfo(pIfCurr->ifa_addr, sizeof(struct sockaddr_in),
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/IP", cIfacesReport);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szInetAddr);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync getnameinfo(pIfCurr->ifa_broadaddr, sizeof(struct sockaddr_in),
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Broadcast", cIfacesReport);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szInetAddr);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync getnameinfo(pIfCurr->ifa_netmask, sizeof(struct sockaddr_in),
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Netmask", cIfacesReport);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szInetAddr);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /* Search for the AF_LINK interface of the current AF_INET one and get the mac. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync for (struct ifaddrs *pIfLinkCurr = pIfHead; pIfLinkCurr; pIfLinkCurr = pIfLinkCurr->ifa_next)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync && !strcmp(pIfCurr->ifa_name, pIfLinkCurr->ifa_name))
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync struct sockaddr_dl *pLinkAddress = (struct sockaddr_dl *)pIfLinkCurr->ifa_addr;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szMac, sizeof(szMac), "%02X%02X%02X%02X%02X%02X",
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pu8Mac[0], pu8Mac[1], pu8Mac[2], pu8Mac[3], pu8Mac[4], pu8Mac[5]);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/MAC", cIfacesReport);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szMac);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/Status", cIfacesReport);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, pIfCurr->ifa_flags & IFF_UP ? "Up" : "Down");
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /* Free allocated resources. */
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync#else /* !RT_OS_WINDOWS && !RT_OS_FREEBSD */
5b0a093ca572a855886faa6747ad46df859dd041vboxsync VBoxServiceError("VMInfo/Network: Failed to get a socket: Error %d\n", errno);
5b0a093ca572a855886faa6747ad46df859dd041vboxsync VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFCONF) on socket: Error %d\n", errno);
5b0a093ca572a855886faa6747ad46df859dd041vboxsync for (int i = 0; i < cIfacesSystem; ++i)
5b0a093ca572a855886faa6747ad46df859dd041vboxsync VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFFLAGS) on socket: Error %d\n", errno);
5b0a093ca572a855886faa6747ad46df859dd041vboxsync if (ifrequest[i].ifr_flags & IFF_LOOPBACK) /* Skip the loopback device. */
5b0a093ca572a855886faa6747ad46df859dd041vboxsync pAddress = ((sockaddr_in *)&ifrequest[i].ifr_addr);
5b0a093ca572a855886faa6747ad46df859dd041vboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/IP", cIfacesReport);
5b0a093ca572a855886faa6747ad46df859dd041vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFBRDADDR) on socket: Error %d\n", errno);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pAddress = (sockaddr_in *)&ifrequest[i].ifr_broadaddr;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Broadcast", cIfacesReport);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFBRDADDR) on socket: Error %d\n", errno);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pAddress = (sockaddr_in *)&ifrequest[i].ifr_netmask;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/V4/Netmask", cIfacesReport);
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * "ifreq" is obsolete on Solaris. We use the recommended "lifreq".
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * We might fail if the interface has not been assigned an IP address.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * That doesn't matter; as long as it's plumbed we can pick it up.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * But, if it has not acquired an IP address we cannot obtain it's MAC
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync * address this way, so we just use all zeros there.
5b0a093ca572a855886faa6747ad46df859dd041vboxsync AssertCompile(sizeof(IfReq.lifr_name) >= sizeof(ifrequest[i].ifr_name));
5b0a093ca572a855886faa6747ad46df859dd041vboxsync strncpy(IfReq.lifr_name, ifrequest[i].ifr_name, sizeof(ifrequest[i].ifr_name));
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync memcpy(&ArpReq.arp_pa, &IfReq.lifr_addr, sizeof(struct sockaddr_in));
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync memcpy(&IfMac, ArpReq.arp_ha.sa_data, sizeof(IfMac));
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync VBoxServiceError("VMInfo/Network: failed to ioctl(SIOCGARP) on socket: Error %d\n", errno);
5b0a093ca572a855886faa6747ad46df859dd041vboxsync VBoxServiceError("VMInfo/Network: failed to ioctl(SIOCGLIFADDR) on socket: Error %d\n", errno);
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync /* @todo don't fail here, handle failure with zero MAC address */
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFHWADDR) on socket: Error %d\n", errno);
d1e9999d55e7ac80a28692c161710be98071fc00vboxsync uint8_t *pu8Mac = (uint8_t*)&ifrequest[i].ifr_hwaddr.sa_data[0]; /* @todo see above */
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync RTStrPrintf(szMac, sizeof(szMac), "%02X%02X%02X%02X%02X%02X",
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync pu8Mac[0], pu8Mac[1], pu8Mac[2], pu8Mac[3], pu8Mac[4], pu8Mac[5]);
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/MAC", cIfacesReport);
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szMac);
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%d/Status", cIfacesReport);
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, fIfUp ? "Up" : "Down");
5b0a093ca572a855886faa6747ad46df859dd041vboxsync#endif /* !RT_OS_WINDOWS */
5b0a093ca572a855886faa6747ad46df859dd041vboxsync * This property is a beacon which is _always_ written, even if the network configuration
5b0a093ca572a855886faa6747ad46df859dd041vboxsync * does not change. If this property is missing, the host assumes that all other GuestInfo
daa94352f51be2329ac8660f70396e03a7cb983bvboxsync * properties are no longer valid.
5b0a093ca572a855886faa6747ad46df859dd041vboxsync VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/Net/Count", "%d",
5b0a093ca572a855886faa6747ad46df859dd041vboxsync /** @todo r=bird: if cIfacesReport decreased compared to the previous run, zap
5b0a093ca572a855886faa6747ad46df859dd041vboxsync * the stale data. This can probably be encorporated into the cache. */
5b0a093ca572a855886faa6747ad46df859dd041vboxsync/** @copydoc VBOXSERVICE::pfnWorker */
5b0a093ca572a855886faa6747ad46df859dd041vboxsyncDECLCALLBACK(int) VBoxServiceVMInfoWorker(bool volatile *pfShutdown)
5b0a093ca572a855886faa6747ad46df859dd041vboxsync * Tell the control thread that it can continue
5b0a093ca572a855886faa6747ad46df859dd041vboxsync * spawning services.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync /* Required for network information (must be called per thread). */
d3dea25ec07f6546715fe3af943ea863294b392evboxsync VBoxServiceError("VMInfo/Network: WSAStartup failed! Error: %Rrc\n", RTErrConvertFromWin32(WSAGetLastError()));
d3dea25ec07f6546715fe3af943ea863294b392evboxsync#endif /* RT_OS_WINDOWS */
e8859cfff41731e3688972d64cf6d5575addcd8fvboxsync * Write the fixed properties first.
d3dea25ec07f6546715fe3af943ea863294b392evboxsync * Now enter the loop retrieving runtime data continuously.
e8859cfff41731e3688972d64cf6d5575addcd8fvboxsync * Block for a while.
e8859cfff41731e3688972d64cf6d5575addcd8fvboxsync * The event semaphore takes care of ignoring interruptions and it
e8859cfff41731e3688972d64cf6d5575addcd8fvboxsync * allows us to implement service wakeup later.
d3dea25ec07f6546715fe3af943ea863294b392evboxsync int rc2 = RTSemEventMultiWait(g_hVMInfoEvent, g_cMsVMInfoInterval);
d3dea25ec07f6546715fe3af943ea863294b392evboxsync VBoxServiceError("VMInfo: RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);
d3dea25ec07f6546715fe3af943ea863294b392evboxsync/** @copydoc VBOXSERVICE::pfnStop */
d3dea25ec07f6546715fe3af943ea863294b392evboxsyncstatic DECLCALLBACK(void) VBoxServiceVMInfoStop(void)
d3dea25ec07f6546715fe3af943ea863294b392evboxsync/** @copydoc VBOXSERVICE::pfnTerm */
d3dea25ec07f6546715fe3af943ea863294b392evboxsyncstatic DECLCALLBACK(void) VBoxServiceVMInfoTerm(void)
d3dea25ec07f6546715fe3af943ea863294b392evboxsync /** @todo temporary solution: Zap all values which are not valid
d3dea25ec07f6546715fe3af943ea863294b392evboxsync * anymore when VM goes down (reboot/shutdown ). Needs to
d3dea25ec07f6546715fe3af943ea863294b392evboxsync * be replaced with "temporary properties" later.
d3dea25ec07f6546715fe3af943ea863294b392evboxsync * One idea is to introduce a (HGCM-)session guest property
d3dea25ec07f6546715fe3af943ea863294b392evboxsync * flag meaning that a guest property is only valid as long
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync * as the HGCM session isn't closed (e.g. guest application
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync * terminates). [don't remove till implemented]
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync /** @todo r=bird: Drop the VbglR3GuestPropDelSet call here and use the cache
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync * since it remembers what we've written. */
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync /* Delete the "../Net" branch. */
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync const char *apszPat[1] = { "/VirtualBox/GuestInfo/Net/*" };
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync rc = VbglR3GuestPropDelSet(g_uVMInfoGuestPropSvcClientID, &apszPat[0], RT_ELEMENTS(apszPat));
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync /* Destroy property cache. */
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync /* Disconnect from guest properties service. */
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync rc = VbglR3GuestPropDisconnect(g_uVMInfoGuestPropSvcClientID);
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync VBoxServiceError("VMInfo: Failed to disconnect from guest property service! Error: %Rrc\n", rc);
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync * The 'vminfo' service description.
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync /* pszName. */
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync /* pszDescription. */
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync "Virtual Machine Information",
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync /* pszUsage. */
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync " [--vminfo-interval <ms>]"
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync /* pszOptions. */
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync " --vminfo-interval Specifies the interval at which to retrieve the\n"
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync " VM information. The default is 10000 ms.\n"
4bf996d915405be92dc4394b2db1395e00e14d58vboxsync /* methods */