VBoxServiceVMInfo.cpp revision 9df808060e0e4b6da01006c2800a3d47cec2cc18
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/* $Id$ */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/** @file
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * VBoxService - Virtual Machine Information for the Host.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/*
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Copyright (C) 2009-2010 Oracle Corporation
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync *
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * available from http://www.virtualbox.org. This file is free software;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * you can redistribute it and/or modify it under the terms of the GNU
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * General Public License (GPL) as published by the Free Software
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/*******************************************************************************
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync* Header Files *
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync*******************************************************************************/
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#ifdef RT_OS_WINDOWS
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# ifdef TARGET_NT4 /* HACK ALERT! PMIB_IPSTATS undefined if 0x0400 with newer SDKs. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# undef _WIN32_WINNT
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# define _WIN32_WINNT 0x0500
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# endif
359f2915f947abde1bba4358eada89941ee87cccvboxsync# include <winsock2.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <iphlpapi.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <ws2tcpip.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <windows.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <Ntsecapi.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#else
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# define __STDC_LIMIT_MACROS
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <arpa/inet.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <errno.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <netinet/in.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <sys/ioctl.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <sys/socket.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <net/if.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <pwd.h> /* getpwuid */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <unistd.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# if !defined(RT_OS_OS2) && !defined(RT_OS_FREEBSD) && !defined(RT_OS_HAIKU)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <utmpx.h> /* @todo FreeBSD 9 should have this. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# endif
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# ifdef RT_OS_SOLARIS
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <sys/sockio.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <net/if_arp.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# endif
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# ifdef RT_OS_FREEBSD
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <ifaddrs.h> /* getifaddrs, freeifaddrs */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <net/if_dl.h> /* LLADDR */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <netdb.h> /* getnameinfo */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# endif
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# ifdef VBOX_WITH_DBUS
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# include <VBox/dbus.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# endif
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#endif
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#include <iprt/mem.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#include <iprt/thread.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#include <iprt/string.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#include <iprt/semaphore.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#include <iprt/system.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#include <iprt/time.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#include <iprt/assert.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#include <VBox/version.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#include <VBox/VBoxGuestLib.h>
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#include "VBoxServiceInternal.h"
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#include "VBoxServiceUtils.h"
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#include "VBoxServicePropCache.h"
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/*******************************************************************************
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync* Global Variables *
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync*******************************************************************************/
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/** The vminfo interval (milliseconds). */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsyncstatic uint32_t g_cMsVMInfoInterval = 0;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/** The semaphore we're blocking on. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsyncstatic RTSEMEVENTMULTI g_hVMInfoEvent = NIL_RTSEMEVENTMULTI;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/** The guest property service client ID. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsyncstatic uint32_t g_uVMInfoGuestPropSvcClientID = 0;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/** Number of logged in users in OS. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsyncstatic uint32_t g_cVMInfoLoggedInUsers = UINT32_MAX;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/** The guest property cache. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsyncstatic VBOXSERVICEVEPROPCACHE g_VMInfoPropCache;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/** The VM session ID. Changes whenever the VM is restored or reset. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsyncstatic uint64_t g_idVMInfoSession;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/*******************************************************************************
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync* Defines *
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync*******************************************************************************/
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#ifdef VBOX_WITH_DBUS
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/** ConsoleKit defines (taken from 0.4.5). */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#define CK_NAME "org.freedesktop.ConsoleKit"
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#define CK_PATH "/org/freedesktop/ConsoleKit"
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#define CK_INTERFACE "org.freedesktop.ConsoleKit"
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager"
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat"
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#endif
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/**
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Signals the event so that a re-enumeration of VM-specific
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * information (like logged in users) can happen.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync *
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * @return IPRT status code.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsyncint VBoxServiceVMInfoSignal(void)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync{
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* Trigger a re-enumeration of all logged-in users by unblocking
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * the multi event semaphore of the VMInfo thread. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (g_hVMInfoEvent)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync return RTSemEventMultiSignal(g_hVMInfoEvent);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync return VINF_SUCCESS;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync}
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/** @copydoc VBOXSERVICE::pfnPreInit */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsyncstatic DECLCALLBACK(int) VBoxServiceVMInfoPreInit(void)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync{
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync return VINF_SUCCESS;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync}
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/** @copydoc VBOXSERVICE::pfnOption */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsyncstatic DECLCALLBACK(int) VBoxServiceVMInfoOption(const char **ppszShort, int argc, char **argv, int *pi)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync{
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync int rc = -1;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (ppszShort)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* no short options */;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync else if (!strcmp(argv[*pi], "--vminfo-interval"))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = VBoxServiceArgUInt32(argc, argv, "", pi,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync &g_cMsVMInfoInterval, 1, UINT32_MAX - 1);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync return rc;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync}
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/** @copydoc VBOXSERVICE::pfnInit */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsyncstatic DECLCALLBACK(int) VBoxServiceVMInfoInit(void)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync{
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /*
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * If not specified, find the right interval default.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Then create the event sem to block on.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (!g_cMsVMInfoInterval)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync g_cMsVMInfoInterval = g_DefaultInterval * 1000;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (!g_cMsVMInfoInterval)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync g_cMsVMInfoInterval = 10 * 1000;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync int rc = RTSemEventMultiCreate(&g_hVMInfoEvent);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync AssertRCReturn(rc, rc);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VbglR3GetSessionId(&g_idVMInfoSession);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* The status code is ignored as this information is not available with VBox < 3.2.10. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = VbglR3GuestPropConnect(&g_uVMInfoGuestPropSvcClientID);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (RT_SUCCESS(rc))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceVerbose(3, "VMInfo: Property Service Client ID: %#x\n", g_uVMInfoGuestPropSvcClientID);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync else
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* If the service was not found, we disable this service without
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync causing VBoxService to fail. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (rc == VERR_HGCM_SERVICE_NOT_FOUND) /* Host service is not available. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceVerbose(0, "VMInfo: Guest property service is not available, disabling the service\n");
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = VERR_SERVICE_DISABLED;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync else
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceError("VMInfo: Failed to connect to the guest property service! Error: %Rrc\n", rc);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync RTSemEventMultiDestroy(g_hVMInfoEvent);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync g_hVMInfoEvent = NIL_RTSEMEVENTMULTI;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (RT_SUCCESS(rc))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServicePropCacheCreate(&g_VMInfoPropCache, g_uVMInfoGuestPropSvcClientID);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /*
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Declare some guest properties with flags and reset values.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBOXSERVICEPROPCACHEFLAG_TEMPORARY | VBOXSERVICEPROPCACHEFLAG_TRANSIENT, NULL /* Delete on exit */);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsers",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBOXSERVICEPROPCACHEFLAG_TEMPORARY | VBOXSERVICEPROPCACHEFLAG_TRANSIENT, "0");
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBOXSERVICEPROPCACHEFLAG_TEMPORARY | VBOXSERVICEPROPCACHEFLAG_TRANSIENT, "true");
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServicePropCacheUpdateEntry(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/Net/Count",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBOXSERVICEPROPCACHEFLAG_TEMPORARY | VBOXSERVICEPROPCACHEFLAG_ALWAYS_UPDATE, NULL /* Delete on exit */);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync return rc;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync}
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/**
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Writes the properties that won't change while the service is running.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync *
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Errors are ignored.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsyncstatic void vboxserviceVMInfoWriteFixedProperties(void)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync{
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /*
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * First get OS information that won't change.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync char szInfo[256];
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync int rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szInfo, sizeof(szInfo));
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Product",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "%s", RT_FAILURE(rc) ? "" : szInfo);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szInfo, sizeof(szInfo));
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Release",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "%s", RT_FAILURE(rc) ? "" : szInfo);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szInfo, sizeof(szInfo));
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/Version",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "%s", RT_FAILURE(rc) ? "" : szInfo);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync rc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szInfo, sizeof(szInfo));
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/OS/ServicePack",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "%s", RT_FAILURE(rc) ? "" : szInfo);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /*
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Retrieve version information about Guest Additions and installed files (components).
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync char *pszAddVer;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync char *pszAddVerExt;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync char *pszAddRev;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = VbglR3GetAdditionsVersion(&pszAddVer, &pszAddVerExt, &pszAddRev);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestAdd/Version",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "%s", RT_FAILURE(rc) ? "" : pszAddVer);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestAdd/VersionExt",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "%s", RT_FAILURE(rc) ? "" : pszAddVerExt);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestAdd/Revision",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "%s", RT_FAILURE(rc) ? "" : pszAddRev);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (RT_SUCCESS(rc))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync RTStrFree(pszAddVer);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync RTStrFree(pszAddVerExt);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync RTStrFree(pszAddRev);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#ifdef RT_OS_WINDOWS
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /*
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Do windows specific properties.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync char *pszInstDir;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = VbglR3GetAdditionsInstallationPath(&pszInstDir);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceWritePropF(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestAdd/InstallDir",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "%s", RT_FAILURE(rc) ? "" : pszInstDir);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (RT_SUCCESS(rc))
359f2915f947abde1bba4358eada89941ee87cccvboxsync RTStrFree(pszInstDir);
359f2915f947abde1bba4358eada89941ee87cccvboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceWinGetComponentVersions(g_uVMInfoGuestPropSvcClientID);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#endif
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync}
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#if defined(VBOX_WITH_DBUS) && defined(RT_OS_LINUX) /* Not yet for Solaris/FreeBSB. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/*
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Simple wrapper to work around compiler-specific va_list madness.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsyncstatic dbus_bool_t vboxService_dbus_message_get_args(DBusMessage *message,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync DBusError *error,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync int first_arg_type,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync ...)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync{
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync va_list va;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync va_start(va, first_arg_type);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync dbus_bool_t ret = dbus_message_get_args_valist(message, error,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync first_arg_type, va);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync va_end(va);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync return ret;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync}
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#endif
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync/**
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Provide information about active users.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsyncstatic int vboxserviceVMInfoWriteUsers(void)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync{
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync int rc = VINF_SUCCESS;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync char *pszUserList = NULL;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync uint32_t cUsersInList = 0;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#ifdef RT_OS_WINDOWS
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# ifndef TARGET_NT4
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = VBoxServiceVMInfoWinWriteUsers(&pszUserList, &cUsersInList);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# else
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = VERR_NOT_IMPLEMENTED;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# endif
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync#elif defined(RT_OS_FREEBSD)
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync /** @todo FreeBSD: Port logged on user info retrieval.
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync * However, FreeBSD 9 supports utmpx, so we could use the code
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync * block below (?). */
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync rc = VERR_NOT_IMPLEMENTED;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync#elif defined(RT_OS_HAIKU)
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync /** @todo Haiku: Port logged on user info retrieval. */
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync rc = VERR_NOT_IMPLEMENTED;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync#elif defined(RT_OS_OS2)
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync /** @todo OS/2: Port logged on (LAN/local/whatever) user info retrieval. */
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync rc = VERR_NOT_IMPLEMENTED;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync#else
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync setutxent();
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync utmpx *ut_user;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync uint32_t cListSize = 32;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync /* Allocate a first array to hold 32 users max. */
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync char **papszUsers = (char **)RTMemAllocZ(cListSize * sizeof(char *));
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync if (papszUsers == NULL)
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync rc = VERR_NO_MEMORY;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* Process all entries in the utmp file.
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Note: This only handles */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync while ( (ut_user = getutxent())
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync && RT_SUCCESS(rc))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceVerbose(4, "Found entry \"%s\" (type: %d, PID: %RU32, session: %RU32)\n",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync ut_user->ut_user, ut_user->ut_type, ut_user->ut_pid, ut_user->ut_session);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (cUsersInList > cListSize)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync cListSize += 32;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync void *pvNew = RTMemRealloc(papszUsers, cListSize * sizeof(char*));
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync AssertPtrBreakStmt(pvNew, cListSize -= 32);
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync papszUsers = (char **)pvNew;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync }
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync /* Make sure we don't add user names which are not
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync * part of type USER_PROCES. */
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync if (ut_user->ut_type == USER_PROCESS) /* Regular user process. */
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync {
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync bool fFound = false;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync for (uint32_t i = 0; i < cUsersInList && !fFound; i++)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync fFound = strcmp(papszUsers[i], ut_user->ut_user) == 0;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync if (!fFound)
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync {
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync VBoxServiceVerbose(4, "Adding user \"%s\" (type: %d) to list\n",
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync ut_user->ut_user, ut_user->ut_type);
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = RTStrDupEx(&papszUsers[cUsersInList], (const char *)ut_user->ut_user);
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync if (RT_FAILURE(rc))
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync break;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync cUsersInList++;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync }
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync }
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync }
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#ifdef VBOX_WITH_DBUS
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# if defined(RT_OS_LINUX) /* Not yet for Solaris/FreeBSB. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync DBusError dbErr;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync DBusConnection *pConnection = NULL;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync int rc2 = RTDBusLoadLib();
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (RT_SUCCESS(rc2))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* Handle desktop sessions using ConsoleKit. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceVerbose(4, "Checking ConsoleKit sessions ...\n");
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync dbus_error_init(&dbErr);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync pConnection = dbus_bus_get(DBUS_BUS_SYSTEM, &dbErr);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if ( pConnection
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync && !dbus_error_is_set(&dbErr))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* Get all available sessions. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync DBusMessage *pMsgSessions = dbus_message_new_method_call("org.freedesktop.ConsoleKit",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "/org/freedesktop/ConsoleKit/Manager",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "org.freedesktop.ConsoleKit.Manager",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "GetSessions");
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if ( pMsgSessions
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync && (dbus_message_get_type(pMsgSessions) == DBUS_MESSAGE_TYPE_METHOD_CALL))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync DBusMessage *pReplySessions = dbus_connection_send_with_reply_and_block(pConnection,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync pMsgSessions, 30 * 1000 /* 30s timeout */,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync &dbErr);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if ( pReplySessions
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync && !dbus_error_is_set(&dbErr))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync char **ppszSessions; int cSessions;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if ( (dbus_message_get_type(pMsgSessions) == DBUS_MESSAGE_TYPE_METHOD_CALL)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync && vboxService_dbus_message_get_args(pReplySessions, &dbErr, DBUS_TYPE_ARRAY,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync DBUS_TYPE_OBJECT_PATH, &ppszSessions, &cSessions,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync DBUS_TYPE_INVALID /* Termination */))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceVerbose(4, "ConsoleKit: retrieved %RU16 session(s)\n", cSessions);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync char **ppszCurSession = ppszSessions;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync for (ppszCurSession;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync ppszCurSession && *ppszCurSession; ppszCurSession++)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceVerbose(4, "ConsoleKit: processing session '%s' ...\n", *ppszCurSession);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* Only respect active sessions .*/
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync bool fActive = false;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync DBusMessage *pMsgSessionActive = dbus_message_new_method_call("org.freedesktop.ConsoleKit",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync *ppszCurSession,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "org.freedesktop.ConsoleKit.Session",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "IsActive");
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if ( pMsgSessionActive
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync && dbus_message_get_type(pMsgSessionActive) == DBUS_MESSAGE_TYPE_METHOD_CALL)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync DBusMessage *pReplySessionActive = dbus_connection_send_with_reply_and_block(pConnection,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync pMsgSessionActive, 30 * 1000 /* 30s timeout */,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync &dbErr);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if ( pReplySessionActive
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync && !dbus_error_is_set(&dbErr))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync DBusMessageIter itMsg;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if ( dbus_message_iter_init(pReplySessionActive, &itMsg)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync && dbus_message_iter_get_arg_type(&itMsg) == DBUS_TYPE_BOOLEAN)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* Get uid from message. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync int val;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync dbus_message_iter_get_basic(&itMsg, &val);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync fActive = val >= 1;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (pReplySessionActive)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync dbus_message_unref(pReplySessionActive);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (pMsgSessionActive)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync dbus_message_unref(pMsgSessionActive);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceVerbose(4, "ConsoleKit: session '%s' is %s\n",
359f2915f947abde1bba4358eada89941ee87cccvboxsync *ppszCurSession, fActive ? "active" : "not active");
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
359f2915f947abde1bba4358eada89941ee87cccvboxsync /* *ppszCurSession now contains the object path
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * (e.g. "/org/freedesktop/ConsoleKit/Session1"). */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync DBusMessage *pMsgUnixUser = dbus_message_new_method_call("org.freedesktop.ConsoleKit",
359f2915f947abde1bba4358eada89941ee87cccvboxsync *ppszCurSession,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "org.freedesktop.ConsoleKit.Session",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync "GetUnixUser");
359f2915f947abde1bba4358eada89941ee87cccvboxsync if ( fActive
359f2915f947abde1bba4358eada89941ee87cccvboxsync && pMsgUnixUser
359f2915f947abde1bba4358eada89941ee87cccvboxsync && dbus_message_get_type(pMsgUnixUser) == DBUS_MESSAGE_TYPE_METHOD_CALL)
359f2915f947abde1bba4358eada89941ee87cccvboxsync {
359f2915f947abde1bba4358eada89941ee87cccvboxsync DBusMessage *pReplyUnixUser = dbus_connection_send_with_reply_and_block(pConnection,
359f2915f947abde1bba4358eada89941ee87cccvboxsync pMsgUnixUser, 30 * 1000 /* 30s timeout */,
359f2915f947abde1bba4358eada89941ee87cccvboxsync &dbErr);
359f2915f947abde1bba4358eada89941ee87cccvboxsync if ( pReplyUnixUser
359f2915f947abde1bba4358eada89941ee87cccvboxsync && !dbus_error_is_set(&dbErr))
359f2915f947abde1bba4358eada89941ee87cccvboxsync {
359f2915f947abde1bba4358eada89941ee87cccvboxsync DBusMessageIter itMsg;
359f2915f947abde1bba4358eada89941ee87cccvboxsync if ( dbus_message_iter_init(pReplyUnixUser, &itMsg)
359f2915f947abde1bba4358eada89941ee87cccvboxsync && dbus_message_iter_get_arg_type(&itMsg) == DBUS_TYPE_UINT32)
359f2915f947abde1bba4358eada89941ee87cccvboxsync {
359f2915f947abde1bba4358eada89941ee87cccvboxsync /* Get uid from message. */
359f2915f947abde1bba4358eada89941ee87cccvboxsync uint32_t uid;
359f2915f947abde1bba4358eada89941ee87cccvboxsync dbus_message_iter_get_basic(&itMsg, &uid);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /** @todo Add support for getting UID_MIN (/etc/login.defs on
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Debian). */
359f2915f947abde1bba4358eada89941ee87cccvboxsync int uid_min = 1000;
359f2915f947abde1bba4358eada89941ee87cccvboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* Look up user name (realname) from uid. */
359f2915f947abde1bba4358eada89941ee87cccvboxsync setpwent();
359f2915f947abde1bba4358eada89941ee87cccvboxsync struct passwd *ppwEntry = getpwuid(uid);
359f2915f947abde1bba4358eada89941ee87cccvboxsync if ( ppwEntry
359f2915f947abde1bba4358eada89941ee87cccvboxsync && ppwEntry->pw_uid >= uid_min /* Only respect users, not daemons etc. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync && ppwEntry->pw_name)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
359f2915f947abde1bba4358eada89941ee87cccvboxsync VBoxServiceVerbose(4, "ConsoleKit: session '%s' -> %s (uid: %RU32)\n",
359f2915f947abde1bba4358eada89941ee87cccvboxsync *ppszCurSession, ppwEntry->pw_name, uid);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
359f2915f947abde1bba4358eada89941ee87cccvboxsync bool fFound = false;
359f2915f947abde1bba4358eada89941ee87cccvboxsync for (uint32_t i = 0; i < cUsersInList && !fFound; i++)
359f2915f947abde1bba4358eada89941ee87cccvboxsync fFound = strcmp(papszUsers[i], ppwEntry->pw_name) == 0;
359f2915f947abde1bba4358eada89941ee87cccvboxsync
359f2915f947abde1bba4358eada89941ee87cccvboxsync if (!fFound)
359f2915f947abde1bba4358eada89941ee87cccvboxsync {
359f2915f947abde1bba4358eada89941ee87cccvboxsync VBoxServiceVerbose(4, "ConsoleKit: adding user \"%s\" to list\n",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync ppwEntry->pw_name);
359f2915f947abde1bba4358eada89941ee87cccvboxsync
359f2915f947abde1bba4358eada89941ee87cccvboxsync rc = RTStrDupEx(&papszUsers[cUsersInList], (const char *)ppwEntry->pw_name);
359f2915f947abde1bba4358eada89941ee87cccvboxsync if (RT_FAILURE(rc))
359f2915f947abde1bba4358eada89941ee87cccvboxsync break;
359f2915f947abde1bba4358eada89941ee87cccvboxsync cUsersInList++;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
359f2915f947abde1bba4358eada89941ee87cccvboxsync else
359f2915f947abde1bba4358eada89941ee87cccvboxsync VBoxServiceError("ConsoleKit: unable to lookup user name for uid=%RU32\n", uid);
359f2915f947abde1bba4358eada89941ee87cccvboxsync }
359f2915f947abde1bba4358eada89941ee87cccvboxsync else
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync AssertMsgFailed(("ConsoleKit: GetUnixUser returned a wrong argument type\n"));
359f2915f947abde1bba4358eada89941ee87cccvboxsync }
359f2915f947abde1bba4358eada89941ee87cccvboxsync
359f2915f947abde1bba4358eada89941ee87cccvboxsync if (pReplyUnixUser)
359f2915f947abde1bba4358eada89941ee87cccvboxsync dbus_message_unref(pReplyUnixUser);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
359f2915f947abde1bba4358eada89941ee87cccvboxsync else
359f2915f947abde1bba4358eada89941ee87cccvboxsync VBoxServiceError("ConsoleKit: unable to retrieve user for session '%s' (msg type=%d): %s",
359f2915f947abde1bba4358eada89941ee87cccvboxsync *ppszCurSession, dbus_message_get_type(pMsgUnixUser),
359f2915f947abde1bba4358eada89941ee87cccvboxsync dbus_error_is_set(&dbErr) ? dbErr.message : "No error information available\n");
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
359f2915f947abde1bba4358eada89941ee87cccvboxsync if (pMsgUnixUser)
359f2915f947abde1bba4358eada89941ee87cccvboxsync dbus_message_unref(pMsgUnixUser);
359f2915f947abde1bba4358eada89941ee87cccvboxsync }
359f2915f947abde1bba4358eada89941ee87cccvboxsync
359f2915f947abde1bba4358eada89941ee87cccvboxsync dbus_free_string_array(ppszSessions);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
359f2915f947abde1bba4358eada89941ee87cccvboxsync else
359f2915f947abde1bba4358eada89941ee87cccvboxsync {
359f2915f947abde1bba4358eada89941ee87cccvboxsync VBoxServiceError("ConsoleKit: unable to retrieve session parameters (msg type=%d): %s",
359f2915f947abde1bba4358eada89941ee87cccvboxsync dbus_message_get_type(pMsgSessions),
359f2915f947abde1bba4358eada89941ee87cccvboxsync dbus_error_is_set(&dbErr) ? dbErr.message : "No error information available\n");
359f2915f947abde1bba4358eada89941ee87cccvboxsync }
359f2915f947abde1bba4358eada89941ee87cccvboxsync dbus_message_unref(pReplySessions);
359f2915f947abde1bba4358eada89941ee87cccvboxsync }
359f2915f947abde1bba4358eada89941ee87cccvboxsync
359f2915f947abde1bba4358eada89941ee87cccvboxsync if (pMsgSessions)
359f2915f947abde1bba4358eada89941ee87cccvboxsync {
359f2915f947abde1bba4358eada89941ee87cccvboxsync dbus_message_unref(pMsgSessions);
359f2915f947abde1bba4358eada89941ee87cccvboxsync pMsgSessions = NULL;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync else
359f2915f947abde1bba4358eada89941ee87cccvboxsync {
359f2915f947abde1bba4358eada89941ee87cccvboxsync static int s_iBitchedAboutConsoleKit = 0;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (s_iBitchedAboutConsoleKit++ < 3)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceError("Unable to invoke ConsoleKit (%d/3) -- maybe not installed / used? Error: %s\n",
359f2915f947abde1bba4358eada89941ee87cccvboxsync s_iBitchedAboutConsoleKit,
359f2915f947abde1bba4358eada89941ee87cccvboxsync dbus_error_is_set(&dbErr) ? dbErr.message : "No error information available\n");
359f2915f947abde1bba4358eada89941ee87cccvboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
359f2915f947abde1bba4358eada89941ee87cccvboxsync if (pMsgSessions)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync dbus_message_unref(pMsgSessions);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync else
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync static int s_iBitchedAboutDBus = 0;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (s_iBitchedAboutDBus++ < 3)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceError("Unable to connect to system D-Bus (%d/3): %s\n", s_iBitchedAboutDBus,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync dbus_error_is_set(&dbErr) ? dbErr.message : "D-Bus not installed\n");
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (dbus_error_is_set(&dbErr))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync dbus_error_free(&dbErr);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync# endif /* RT_OS_LINUX */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#endif /* VBOX_WITH_DBUS */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /** @todo Fedora/others: Handle systemd-loginctl. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* Calc the string length. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync size_t cchUserList = 0;
359f2915f947abde1bba4358eada89941ee87cccvboxsync if (RT_SUCCESS(rc))
359f2915f947abde1bba4358eada89941ee87cccvboxsync {
359f2915f947abde1bba4358eada89941ee87cccvboxsync for (uint32_t i = 0; i < cUsersInList; i++)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync cchUserList += (i != 0) + strlen(papszUsers[i]);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* Build the user list. */
359f2915f947abde1bba4358eada89941ee87cccvboxsync if (RT_SUCCESS(rc))
359f2915f947abde1bba4358eada89941ee87cccvboxsync rc = RTStrAllocEx(&pszUserList, cchUserList + 1);
359f2915f947abde1bba4358eada89941ee87cccvboxsync if (RT_SUCCESS(rc))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync char *psz = pszUserList;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync for (uint32_t i = 0; i < cUsersInList; i++)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (i != 0)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync *psz++ = ',';
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync size_t cch = strlen(papszUsers[i]);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync memcpy(psz, papszUsers[i], cch);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync psz += cch;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync *psz = '\0';
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* Cleanup. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync for (uint32_t i = 0; i < cUsersInList; i++)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync RTStrFree(papszUsers[i]);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync RTMemFree(papszUsers);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync endutxent(); /* Close utmpx file. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync#endif
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync Assert(RT_FAILURE(rc) || cUsersInList == 0 || (pszUserList && *pszUserList));
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* If the user enumeration above failed, reset the user count to 0 except
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * we didn't have enough memory anymore. In that case we want to preserve
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * the previous user count in order to not confuse third party tools which
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * rely on that count. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (RT_FAILURE(rc))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (rc == VERR_NO_MEMORY)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync static int s_iVMInfoBitchedOOM = 0;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (s_iVMInfoBitchedOOM++ < 3)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceVerbose(0, "Warning: Not enough memory available to enumerate users! Keeping old value (%u)\n",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync g_cVMInfoLoggedInUsers);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync cUsersInList = g_cVMInfoLoggedInUsers;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync else
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync cUsersInList = 0;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceVerbose(4, "cUsersInList=%RU32, pszUserList=%s, rc=%Rrc\n",
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync cUsersInList, pszUserList ? pszUserList : "<NULL>", rc);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (pszUserList && cUsersInList > 0)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", "%s", pszUserList);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync else
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", NULL);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (RT_FAILURE(rc))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceError("VMInfo: Error writing logged on users list, rc=%Rrc\n", rc);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync cUsersInList = 0; /* Reset user count on error. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsers", "%u", cUsersInList);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (RT_FAILURE(rc))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceError("VMInfo: Error writing logged on users count, rc=%Rrc\n", rc);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync cUsersInList = 0; /* Reset user count on error. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (g_cVMInfoLoggedInUsers != cUsersInList)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync rc = VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/NoLoggedInUsers",
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync cUsersInList == 0 ? "true" : "false");
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (RT_FAILURE(rc))
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync VBoxServiceError("VMInfo: Error writing no logged in users beacon, rc=%Rrc\n", rc);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync g_cVMInfoLoggedInUsers = cUsersInList;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (pszUserList)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync RTStrFree(pszUserList);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync return rc;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync}
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync/**
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * Provide information about the guest network.
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync */
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsyncstatic int vboxserviceVMInfoWriteNetwork(void)
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync{
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync int rc = VINF_SUCCESS;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync uint32_t cIfacesReport = 0;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync char szPropPath[256];
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync#ifdef RT_OS_WINDOWS
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync IP_ADAPTER_INFO *pAdpInfo = NULL;
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync# ifndef TARGET_NT4
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync ULONG cbAdpInfo = sizeof(*pAdpInfo);
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync pAdpInfo = (IP_ADAPTER_INFO *)RTMemAlloc(cbAdpInfo);
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync if (!pAdpInfo)
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync {
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync VBoxServiceError("VMInfo/Network: Failed to allocate IP_ADAPTER_INFO\n");
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync return VERR_NO_MEMORY;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync DWORD dwRet = GetAdaptersInfo(pAdpInfo, &cbAdpInfo);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (dwRet == ERROR_BUFFER_OVERFLOW)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync IP_ADAPTER_INFO *pAdpInfoNew = (IP_ADAPTER_INFO*)RTMemRealloc(pAdpInfo, cbAdpInfo);
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync if (pAdpInfoNew)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync pAdpInfo = pAdpInfoNew;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync dwRet = GetAdaptersInfo(pAdpInfo, &cbAdpInfo);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync else if (dwRet == ERROR_NO_DATA)
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync {
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync VBoxServiceVerbose(3, "VMInfo/Network: No network adapters available\n");
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync /* If no network adapters available / present in the
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync * system we pretend success to not bail out too early. */
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync dwRet = ERROR_SUCCESS;
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (dwRet != ERROR_SUCCESS)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync {
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync if (pAdpInfo)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync RTMemFree(pAdpInfo);
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync VBoxServiceError("VMInfo/Network: Failed to get adapter info: Error %d\n", dwRet);
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync return RTErrConvertFromWin32(dwRet);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
359f2915f947abde1bba4358eada89941ee87cccvboxsync# endif /* !TARGET_NT4 */
359f2915f947abde1bba4358eada89941ee87cccvboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync if (sd == SOCKET_ERROR) /* Socket invalid. */
359f2915f947abde1bba4358eada89941ee87cccvboxsync {
359f2915f947abde1bba4358eada89941ee87cccvboxsync int wsaErr = WSAGetLastError();
359f2915f947abde1bba4358eada89941ee87cccvboxsync /* Don't complain/bail out with an error if network stack is not up; can happen
359f2915f947abde1bba4358eada89941ee87cccvboxsync * on NT4 due to start up when not connected shares dialogs pop up. */
359f2915f947abde1bba4358eada89941ee87cccvboxsync if (WSAENETDOWN == wsaErr)
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync {
359f2915f947abde1bba4358eada89941ee87cccvboxsync VBoxServiceVerbose(0, "VMInfo/Network: Network is not up yet.\n");
359f2915f947abde1bba4358eada89941ee87cccvboxsync wsaErr = VINF_SUCCESS;
359f2915f947abde1bba4358eada89941ee87cccvboxsync }
359f2915f947abde1bba4358eada89941ee87cccvboxsync else
359f2915f947abde1bba4358eada89941ee87cccvboxsync VBoxServiceError("VMInfo/Network: Failed to get a socket: Error %d\n", wsaErr);
359f2915f947abde1bba4358eada89941ee87cccvboxsync if (pAdpInfo)
359f2915f947abde1bba4358eada89941ee87cccvboxsync RTMemFree(pAdpInfo);
359f2915f947abde1bba4358eada89941ee87cccvboxsync return RTErrConvertFromWin32(wsaErr);
359f2915f947abde1bba4358eada89941ee87cccvboxsync }
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync INTERFACE_INFO InterfaceList[20] = {0};
359f2915f947abde1bba4358eada89941ee87cccvboxsync unsigned long nBytesReturned = 0;
359f2915f947abde1bba4358eada89941ee87cccvboxsync if (WSAIoctl(sd,
359f2915f947abde1bba4358eada89941ee87cccvboxsync SIO_GET_INTERFACE_LIST,
359f2915f947abde1bba4358eada89941ee87cccvboxsync 0,
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync 0,
359f2915f947abde1bba4358eada89941ee87cccvboxsync &InterfaceList,
359f2915f947abde1bba4358eada89941ee87cccvboxsync sizeof(InterfaceList),
0a7c9cc36ee176228eab4150144ad2561b0c4647vboxsync &nBytesReturned,
359f2915f947abde1bba4358eada89941ee87cccvboxsync 0,
359f2915f947abde1bba4358eada89941ee87cccvboxsync 0) == SOCKET_ERROR)
359f2915f947abde1bba4358eada89941ee87cccvboxsync {
359f2915f947abde1bba4358eada89941ee87cccvboxsync VBoxServiceError("VMInfo/Network: Failed to WSAIoctl() on socket: Error: %d\n", WSAGetLastError());
359f2915f947abde1bba4358eada89941ee87cccvboxsync if (pAdpInfo)
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync RTMemFree(pAdpInfo);
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync return RTErrConvertFromWin32(WSAGetLastError());
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync }
2b73ea648457a8fb1ec027d1eeea63f879dad507vboxsync int cIfacesSystem = nBytesReturned / sizeof(INTERFACE_INFO);
/** @todo Use GetAdaptersInfo() and GetAdapterAddresses (IPv4 + IPv6) for more information. */
for (int i = 0; i < cIfacesSystem; ++i)
{
sockaddr_in *pAddress;
u_long nFlags = 0;
if (InterfaceList[i].iiFlags & IFF_LOOPBACK) /* Skip loopback device. */
continue;
nFlags = InterfaceList[i].iiFlags;
pAddress = (sockaddr_in *)&(InterfaceList[i].iiAddress);
Assert(pAddress);
char szIp[32];
RTStrPrintf(szIp, sizeof(szIp), "%s", inet_ntoa(pAddress->sin_addr));
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/V4/IP", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szIp);
pAddress = (sockaddr_in *) & (InterfaceList[i].iiBroadcastAddress);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/V4/Broadcast", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
pAddress = (sockaddr_in *)&(InterfaceList[i].iiNetmask);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/V4/Netmask", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/Status", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, nFlags & IFF_UP ? "Up" : "Down");
# ifndef TARGET_NT4
IP_ADAPTER_INFO *pAdp;
for (pAdp = pAdpInfo; pAdp; pAdp = pAdp->Next)
if (!strcmp(pAdp->IpAddressList.IpAddress.String, szIp))
break;
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/MAC", cIfacesReport);
if (pAdp)
{
char szMac[32];
RTStrPrintf(szMac, sizeof(szMac), "%02X%02X%02X%02X%02X%02X",
pAdp->Address[0], pAdp->Address[1], pAdp->Address[2],
pAdp->Address[3], pAdp->Address[4], pAdp->Address[5]);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szMac);
}
else
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, NULL);
# endif /* !TARGET_NT4 */
cIfacesReport++;
}
if (pAdpInfo)
RTMemFree(pAdpInfo);
if (sd >= 0)
closesocket(sd);
#elif defined(RT_OS_HAIKU)
/** @todo Haiku: implement network info. retreival */
return VERR_NOT_IMPLEMENTED;
#elif defined(RT_OS_FREEBSD)
struct ifaddrs *pIfHead = NULL;
/* Get all available interfaces */
rc = getifaddrs(&pIfHead);
if (rc < 0)
{
rc = RTErrConvertFromErrno(errno);
VBoxServiceError("VMInfo/Network: Failed to get all interfaces: Error %Rrc\n");
return rc;
}
/* Loop through all interfaces and set the data. */
for (struct ifaddrs *pIfCurr = pIfHead; pIfCurr; pIfCurr = pIfCurr->ifa_next)
{
/*
* Only AF_INET and no loopback interfaces
* @todo: IPv6 interfaces
*/
if ( pIfCurr->ifa_addr->sa_family == AF_INET
&& !(pIfCurr->ifa_flags & IFF_LOOPBACK))
{
char szInetAddr[NI_MAXHOST];
memset(szInetAddr, 0, NI_MAXHOST);
getnameinfo(pIfCurr->ifa_addr, sizeof(struct sockaddr_in),
szInetAddr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/V4/IP", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szInetAddr);
memset(szInetAddr, 0, NI_MAXHOST);
getnameinfo(pIfCurr->ifa_broadaddr, sizeof(struct sockaddr_in),
szInetAddr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/V4/Broadcast", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szInetAddr);
memset(szInetAddr, 0, NI_MAXHOST);
getnameinfo(pIfCurr->ifa_netmask, sizeof(struct sockaddr_in),
szInetAddr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/V4/Netmask", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szInetAddr);
/* Search for the AF_LINK interface of the current AF_INET one and get the mac. */
for (struct ifaddrs *pIfLinkCurr = pIfHead; pIfLinkCurr; pIfLinkCurr = pIfLinkCurr->ifa_next)
{
if ( pIfLinkCurr->ifa_addr->sa_family == AF_LINK
&& !strcmp(pIfCurr->ifa_name, pIfLinkCurr->ifa_name))
{
char szMac[32];
uint8_t *pu8Mac = NULL;
struct sockaddr_dl *pLinkAddress = (struct sockaddr_dl *)pIfLinkCurr->ifa_addr;
AssertPtr(pLinkAddress);
pu8Mac = (uint8_t *)LLADDR(pLinkAddress);
RTStrPrintf(szMac, sizeof(szMac), "%02X%02X%02X%02X%02X%02X",
pu8Mac[0], pu8Mac[1], pu8Mac[2], pu8Mac[3], pu8Mac[4], pu8Mac[5]);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/MAC", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szMac);
break;
}
}
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/Status", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, pIfCurr->ifa_flags & IFF_UP ? "Up" : "Down");
cIfacesReport++;
}
}
/* Free allocated resources. */
freeifaddrs(pIfHead);
#else /* !RT_OS_WINDOWS && !RT_OS_FREEBSD */
int sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0)
{
rc = RTErrConvertFromErrno(errno);
VBoxServiceError("VMInfo/Network: Failed to get a socket: Error %Rrc\n", rc);
return rc;
}
ifconf ifcfg;
char buffer[1024] = {0};
ifcfg.ifc_len = sizeof(buffer);
ifcfg.ifc_buf = buffer;
if (ioctl(sd, SIOCGIFCONF, &ifcfg) < 0)
{
close(sd);
rc = RTErrConvertFromErrno(errno);
VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFCONF) on socket: Error %Rrc\n", rc);
return rc;
}
ifreq* ifrequest = ifcfg.ifc_req;
int cIfacesSystem = ifcfg.ifc_len / sizeof(ifreq);
for (int i = 0; i < cIfacesSystem; ++i)
{
sockaddr_in *pAddress;
if (ioctl(sd, SIOCGIFFLAGS, &ifrequest[i]) < 0)
{
rc = RTErrConvertFromErrno(errno);
VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFFLAGS) on socket: Error %Rrc\n", rc);
break;
}
if (ifrequest[i].ifr_flags & IFF_LOOPBACK) /* Skip the loopback device. */
continue;
bool fIfUp = !!(ifrequest[i].ifr_flags & IFF_UP);
pAddress = ((sockaddr_in *)&ifrequest[i].ifr_addr);
Assert(pAddress);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/V4/IP", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
if (ioctl(sd, SIOCGIFBRDADDR, &ifrequest[i]) < 0)
{
rc = RTErrConvertFromErrno(errno);
VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFBRDADDR) on socket: Error %Rrc\n", rc);
break;
}
pAddress = (sockaddr_in *)&ifrequest[i].ifr_broadaddr;
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/V4/Broadcast", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
if (ioctl(sd, SIOCGIFNETMASK, &ifrequest[i]) < 0)
{
rc = RTErrConvertFromErrno(errno);
VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFNETMASK) on socket: Error %Rrc\n", rc);
break;
}
# if defined(RT_OS_OS2) || defined(RT_OS_SOLARIS)
pAddress = (sockaddr_in *)&ifrequest[i].ifr_addr;
# else
pAddress = (sockaddr_in *)&ifrequest[i].ifr_netmask;
# endif
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/V4/Netmask", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", inet_ntoa(pAddress->sin_addr));
# if defined(RT_OS_SOLARIS)
/*
* "ifreq" is obsolete on Solaris. We use the recommended "lifreq".
* We might fail if the interface has not been assigned an IP address.
* That doesn't matter; as long as it's plumbed we can pick it up.
* But, if it has not acquired an IP address we cannot obtain it's MAC
* address this way, so we just use all zeros there.
*/
RTMAC IfMac;
RT_ZERO(IfMac);
struct lifreq IfReq;
RT_ZERO(IfReq);
AssertCompile(sizeof(IfReq.lifr_name) >= sizeof(ifrequest[i].ifr_name));
strncpy(IfReq.lifr_name, ifrequest[i].ifr_name, sizeof(ifrequest[i].ifr_name));
if (ioctl(sd, SIOCGLIFADDR, &IfReq) >= 0)
{
struct arpreq ArpReq;
RT_ZERO(ArpReq);
memcpy(&ArpReq.arp_pa, &IfReq.lifr_addr, sizeof(struct sockaddr_in));
if (ioctl(sd, SIOCGARP, &ArpReq) >= 0)
memcpy(&IfMac, ArpReq.arp_ha.sa_data, sizeof(IfMac));
else
{
rc = RTErrConvertFromErrno(errno);
VBoxServiceError("VMInfo/Network: failed to ioctl(SIOCGARP) on socket: Error %Rrc\n", rc);
break;
}
}
else
{
VBoxServiceVerbose(2, "VMInfo/Network: Interface %d has no assigned IP address, skipping ...\n", i);
continue;
}
# else
# ifndef RT_OS_OS2 /** @todo port this to OS/2 */
if (ioctl(sd, SIOCGIFHWADDR, &ifrequest[i]) < 0)
{
rc = RTErrConvertFromErrno(errno);
VBoxServiceError("VMInfo/Network: Failed to ioctl(SIOCGIFHWADDR) on socket: Error %Rrc\n", rc);
break;
}
# endif
# endif
# ifndef RT_OS_OS2 /** @todo port this to OS/2 */
char szMac[32];
# if defined(RT_OS_SOLARIS)
uint8_t *pu8Mac = IfMac.au8;
# else
uint8_t *pu8Mac = (uint8_t*)&ifrequest[i].ifr_hwaddr.sa_data[0]; /* @todo see above */
# endif
RTStrPrintf(szMac, sizeof(szMac), "%02X%02X%02X%02X%02X%02X",
pu8Mac[0], pu8Mac[1], pu8Mac[2], pu8Mac[3], pu8Mac[4], pu8Mac[5]);
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/MAC", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, "%s", szMac);
# endif /* !OS/2*/
RTStrPrintf(szPropPath, sizeof(szPropPath), "/VirtualBox/GuestInfo/Net/%u/Status", cIfacesReport);
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, szPropPath, fIfUp ? "Up" : "Down");
cIfacesReport++;
} /* For all interfaces */
close(sd);
if (RT_FAILURE(rc))
VBoxServiceError("VMInfo/Network: Network enumeration for interface %u failed with error %Rrc\n", cIfacesReport, rc);
#endif /* !RT_OS_WINDOWS */
#if 0 /* Zapping not enabled yet, needs more testing first. */
/*
* Zap all stale network interface data if the former (saved) network ifaces count
* is bigger than the current one.
*/
/* Get former count. */
uint32_t cIfacesReportOld;
rc = VBoxServiceReadPropUInt32(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestInfo/Net/Count", &cIfacesReportOld,
0 /* Min */, UINT32_MAX /* Max */);
if ( RT_SUCCESS(rc)
&& cIfacesReportOld > cIfacesReport) /* Are some ifaces not around anymore? */
{
VBoxServiceVerbose(3, "VMInfo/Network: Stale interface data detected (%u old vs. %u current)\n",
cIfacesReportOld, cIfacesReport);
uint32_t uIfaceDeleteIdx = cIfacesReport;
do
{
VBoxServiceVerbose(3, "VMInfo/Network: Deleting stale data of interface %d ...\n", uIfaceDeleteIdx);
rc = VBoxServicePropCacheUpdateByPath(&g_VMInfoPropCache, NULL /* Value, delete */, 0 /* Flags */, "/VirtualBox/GuestInfo/Net/%u", uIfaceDeleteIdx++);
} while (RT_SUCCESS(rc));
}
else if ( RT_FAILURE(rc)
&& rc != VERR_NOT_FOUND)
{
VBoxServiceError("VMInfo/Network: Failed retrieving old network interfaces count with error %Rrc\n", rc);
}
#endif
/*
* This property is a beacon which is _always_ written, even if the network configuration
* does not change. If this property is missing, the host assumes that all other GuestInfo
* properties are no longer valid.
*/
VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/Net/Count", "%d",
cIfacesReport);
/* Don't fail here; just report everything we got. */
return VINF_SUCCESS;
}
/** @copydoc VBOXSERVICE::pfnWorker */
DECLCALLBACK(int) VBoxServiceVMInfoWorker(bool volatile *pfShutdown)
{
int rc;
/*
* Tell the control thread that it can continue
* spawning services.
*/
RTThreadUserSignal(RTThreadSelf());
#ifdef RT_OS_WINDOWS
/* Required for network information (must be called per thread). */
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData))
VBoxServiceError("VMInfo/Network: WSAStartup failed! Error: %Rrc\n", RTErrConvertFromWin32(WSAGetLastError()));
#endif /* RT_OS_WINDOWS */
/*
* Write the fixed properties first.
*/
vboxserviceVMInfoWriteFixedProperties();
/*
* Now enter the loop retrieving runtime data continuously.
*/
for (;;)
{
rc = vboxserviceVMInfoWriteUsers();
if (RT_FAILURE(rc))
break;
rc = vboxserviceVMInfoWriteNetwork();
if (RT_FAILURE(rc))
break;
/*
* Flush all properties if we were restored.
*/
uint64_t idNewSession = g_idVMInfoSession;
VbglR3GetSessionId(&idNewSession);
if (idNewSession != g_idVMInfoSession)
{
VBoxServiceVerbose(3, "VMInfo: The VM session ID changed, flushing all properties\n");
vboxserviceVMInfoWriteFixedProperties();
VBoxServicePropCacheFlush(&g_VMInfoPropCache);
g_idVMInfoSession = idNewSession;
}
/*
* Block for a while.
*
* The event semaphore takes care of ignoring interruptions and it
* allows us to implement service wakeup later.
*/
if (*pfShutdown)
break;
int rc2 = RTSemEventMultiWait(g_hVMInfoEvent, g_cMsVMInfoInterval);
if (*pfShutdown)
break;
if (rc2 != VERR_TIMEOUT && RT_FAILURE(rc2))
{
VBoxServiceError("VMInfo: RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);
rc = rc2;
break;
}
else if (RT_LIKELY(RT_SUCCESS(rc2)))
{
/* Reset event semaphore if it got triggered. */
rc2 = RTSemEventMultiReset(g_hVMInfoEvent);
if (RT_FAILURE(rc2))
rc2 = VBoxServiceError("VMInfo: RTSemEventMultiReset failed; rc2=%Rrc\n", rc2);
}
}
#ifdef RT_OS_WINDOWS
WSACleanup();
#endif
return rc;
}
/** @copydoc VBOXSERVICE::pfnStop */
static DECLCALLBACK(void) VBoxServiceVMInfoStop(void)
{
RTSemEventMultiSignal(g_hVMInfoEvent);
}
/** @copydoc VBOXSERVICE::pfnTerm */
static DECLCALLBACK(void) VBoxServiceVMInfoTerm(void)
{
if (g_hVMInfoEvent != NIL_RTSEMEVENTMULTI)
{
/** @todo temporary solution: Zap all values which are not valid
* anymore when VM goes down (reboot/shutdown ). Needs to
* be replaced with "temporary properties" later.
*
* One idea is to introduce a (HGCM-)session guest property
* flag meaning that a guest property is only valid as long
* as the HGCM session isn't closed (e.g. guest application
* terminates). [don't remove till implemented]
*/
/** @todo r=bird: Drop the VbglR3GuestPropDelSet call here and use the cache
* since it remembers what we've written. */
/* Delete the "../Net" branch. */
const char *apszPat[1] = { "/VirtualBox/GuestInfo/Net/*" };
int rc = VbglR3GuestPropDelSet(g_uVMInfoGuestPropSvcClientID, &apszPat[0], RT_ELEMENTS(apszPat));
/* Destroy property cache. */
VBoxServicePropCacheDestroy(&g_VMInfoPropCache);
/* Disconnect from guest properties service. */
rc = VbglR3GuestPropDisconnect(g_uVMInfoGuestPropSvcClientID);
if (RT_FAILURE(rc))
VBoxServiceError("VMInfo: Failed to disconnect from guest property service! Error: %Rrc\n", rc);
g_uVMInfoGuestPropSvcClientID = 0;
RTSemEventMultiDestroy(g_hVMInfoEvent);
g_hVMInfoEvent = NIL_RTSEMEVENTMULTI;
}
}
/**
* The 'vminfo' service description.
*/
VBOXSERVICE g_VMInfo =
{
/* pszName. */
"vminfo",
/* pszDescription. */
"Virtual Machine Information",
/* pszUsage. */
" [--vminfo-interval <ms>]"
,
/* pszOptions. */
" --vminfo-interval Specifies the interval at which to retrieve the\n"
" VM information. The default is 10000 ms.\n"
,
/* methods */
VBoxServiceVMInfoPreInit,
VBoxServiceVMInfoOption,
VBoxServiceVMInfoInit,
VBoxServiceVMInfoWorker,
VBoxServiceVMInfoStop,
VBoxServiceVMInfoTerm
};