Changeset 79610 in vbox
- Timestamp:
- Jul 8, 2019 11:29:30 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 131912
- Location:
- trunk/src/VBox/Main
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/UnattendedTemplates/ubuntu_preseed.cfg
r79419 r79610 46 46 d-i apt-setup/universe boolean true 47 47 d-i pkgsel/install-language-support boolean false 48 # Stuff we need to build additions modules: 49 d-i pkgsel/include string build-essential linux-headers-generic perl make 48 50 49 51 # Users -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r79605 r79610 1834 1834 uuid="ea2d467f-b6c2-4b9a-8eb5-6e2f275dd72e" 1835 1835 wsmap="managed" 1836 reservedMethods=" 2" reservedAttributes="6"1836 reservedMethods="1" reservedAttributes="6" 1837 1837 > 1838 1838 <desc> … … 2043 2043 </desc> 2044 2044 </method> 2045 2046 <method name="findLeaseByMAC"> 2047 <desc> 2048 Queries the persistent lease database by MAC address. 2049 2050 This is handy if the host wants to connect to a server running inside 2051 a VM on a host only network. 2052 2053 <result name="VBOX_E_OBJECT_NOT_FOUND">If MAC address not in the database.</result> 2054 <result name="VBOX_E_FILE_ERROR">If not able to read the lease database file.</result> 2055 </desc> 2056 <param name="mac" type="wstring" dir="in"> 2057 <desc>The MAC address to look up.</desc> 2058 </param> 2059 <param name="type" type="long" dir="in"> 2060 <desc>Reserved, MBZ.</desc> 2061 </param> 2062 <param name="address" type="wstring" dir="out"> 2063 <desc>The assigned address.</desc> 2064 </param> 2065 <param name="state" type="wstring" dir="out"> 2066 <desc>The lease state.</desc> 2067 </param> 2068 <param name="issued" type="long long" dir="out"> 2069 <desc>Timestamp of when the lease was issued, in seconds since 1970-01-01 UTC.</desc> 2070 </param> 2071 <param name="expire" type="long long" dir="out"> 2072 <desc>Timestamp of when the lease expires/expired, in seconds since 1970-01-01 UTC.</desc> 2073 </param> 2074 </method> 2075 2076 <!-- @todo Add variant of queryLeaseByMac that goes by VM name and optionally slot. --> 2077 <!-- @todo Add min/default/max lease time settings --> 2078 <!-- @todo Add lease database attribute (readonly) --> 2079 <!-- @todo Add methods for complex group operations, that includes lists of mac address, 2080 client ids, vendor/user class ids as selection criteria --> 2081 <!-- @todo Add fake DHCP option for assigning fixed IP addresses. Figure out a way to 2082 do it for the host only trunk interface too (possible special group operation). --> 2083 2045 2084 </interface> 2046 2085 -
trunk/src/VBox/Main/include/DHCPServerImpl.h
r76562 r79610 36 36 #endif 37 37 38 #if def RT_OS_WINDOWS38 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) 39 39 # define DHCP_EXECUTABLE_NAME "VBoxNetDHCP.exe" 40 40 #else … … 42 42 #endif 43 43 44 class DHCPServerRunner : public NetworkServiceRunner44 class DHCPServerRunner : public NetworkServiceRunner 45 45 { 46 46 public: 47 DHCPServerRunner() :NetworkServiceRunner(DHCP_EXECUTABLE_NAME){}48 virtual ~DHCPServerRunner() {};47 DHCPServerRunner() : NetworkServiceRunner(DHCP_EXECUTABLE_NAME) {} 48 virtual ~DHCPServerRunner() {}; 49 49 50 50 static const std::string kDsrKeyGateway; … … 68 68 */ 69 69 70 class ATL_NO_VTABLE DHCPServer :71 public DHCPServerWrap70 class ATL_NO_VTABLE DHCPServer 71 : public DHCPServerWrap 72 72 { 73 73 public: … … 134 134 HRESULT stop(); 135 135 HRESULT restart(); 136 HRESULT findLeaseByMAC(const com::Utf8Str &aMac, LONG aType, 137 com::Utf8Str &aAddress, com::Utf8Str &aState, LONG64 *aIssued, LONG64 *aExpire) RT_OVERRIDE; 138 139 /** @name Helpers 140 * @{ */ 141 HRESULT i_calcLeaseFilename(const com::Utf8Str &aNetwork) RT_NOEXCEPT; 142 /** @} */ 136 143 137 144 struct Data; -
trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp
r76592 r79610 26 26 #include <iprt/net.h> 27 27 #include <iprt/path.h> 28 #include <iprt/cpp/path.h> 28 29 #include <iprt/cpp/utils.h> 29 30 #include <iprt/cpp/xml.h> … … 36 37 // constructor / destructor 37 38 ///////////////////////////////////////////////////////////////////////////// 39 /** @todo Convert to C strings as this is wastefull: */ 38 40 const std::string DHCPServerRunner::kDsrKeyGateway = "--gateway"; 39 41 const std::string DHCPServerRunner::kDsrKeyLowerIp = "--lower-ip"; … … 64 66 65 67 char tempConfigFileName[RTPATH_MAX]; 68 com::Utf8Str strLeaseFilename; 66 69 com::Utf8Str networkName; 67 70 com::Utf8Str trunkName; … … 665 668 { 666 669 if (!m->dhcp.isRunning()) 667 return E_FAIL; 670 return setErrorBoth(E_FAIL, VERR_PROCESS_NOT_FOUND, tr("not running")); 671 668 672 /* 669 670 671 673 * Disabled servers will be brought down, but won't be restarted. 674 * (see DHCPServer::start) 675 */ 672 676 HRESULT hrc = stop(); 673 677 if (SUCCEEDED(hrc)) … … 685 689 return S_OK; 686 690 687 /* 691 /** 688 692 * @todo: the existing code cannot handle concurrent attempts to start DHCP server. 689 693 * Note that technically it may receive different parameters from different callers. 690 694 */ 691 695 m->networkName = aNetworkName; 692 m->trunkName = aTrunkName; 693 m->trunkType = aTrunkType; 694 695 m->dhcp.clearOptions(); 696 m->trunkName = aTrunkName; 697 m->trunkType = aTrunkType; 698 HRESULT hrc = i_calcLeaseFilename(aNetworkName); 699 if (FAILED(hrc)) 700 return hrc; 701 702 m->dhcp.clearOptions(); /* (Not DHCP options, but command line options for the service) */ 703 696 704 #ifdef VBOX_WITH_DHCPD 705 706 /* 707 * Create configuration file path. 708 */ 709 /** @todo put this next to the leases file. */ 697 710 int rc = RTPathTemp(m->tempConfigFileName, sizeof(m->tempConfigFileName)); 698 if (RT_FAILURE(rc)) 699 return E_FAIL; 700 rc = RTPathAppend(m->tempConfigFileName, sizeof(m->tempConfigFileName), "dhcp-config-XXXXX.xml"); 711 if (RT_SUCCESS(rc)) 712 rc = RTPathAppend(m->tempConfigFileName, sizeof(m->tempConfigFileName), "dhcp-config-XXXXX.xml"); 713 if (RT_SUCCESS(rc)) 714 rc = RTFileCreateTemp(m->tempConfigFileName, 0600); 701 715 if (RT_FAILURE(rc)) 702 716 { … … 704 718 return E_FAIL; 705 719 } 706 rc = RTFileCreateTemp(m->tempConfigFileName, 0600); 707 if (RT_FAILURE(rc)) 708 { 709 m->tempConfigFileName[0] = '\0'; 710 return E_FAIL; 711 } 712 720 721 /* 722 * Produce the DHCP server configuration. 723 */ 713 724 xml::Document doc; 714 725 xml::ElementNode *pElmRoot = doc.createRootElement("DHCPServer"); 715 pElmRoot->setAttribute("networkName", m->networkName.c_str()); 716 if (!m->trunkName.isEmpty()) 717 pElmRoot->setAttribute("trunkName", m->trunkName.c_str()); 718 pElmRoot->setAttribute("trunkType", m->trunkType.c_str()); 719 pElmRoot->setAttribute("IPAddress", Utf8Str(m->IPAddress).c_str()); 720 pElmRoot->setAttribute("networkMask", Utf8Str(m->GlobalDhcpOptions[DhcpOpt_SubnetMask].text).c_str()); 721 pElmRoot->setAttribute("lowerIP", Utf8Str(m->lowerIP).c_str()); 722 pElmRoot->setAttribute("upperIP", Utf8Str(m->upperIP).c_str()); 726 pElmRoot->setAttribute("networkName", m->networkName); 727 if (m->trunkName.isNotEmpty()) 728 pElmRoot->setAttribute("trunkName", m->trunkName); 729 pElmRoot->setAttribute("trunkType", m->trunkType); 730 pElmRoot->setAttribute("IPAddress", m->IPAddress); 731 pElmRoot->setAttribute("networkMask", m->GlobalDhcpOptions[DhcpOpt_SubnetMask].text); 732 pElmRoot->setAttribute("lowerIP", m->lowerIP); 733 pElmRoot->setAttribute("upperIP", m->upperIP); 734 pElmRoot->setAttribute("leaseFilename", m->strLeaseFilename); 723 735 724 736 /* Process global options */ 725 737 xml::ElementNode *pOptions = pElmRoot->createChild("Options"); 726 // settings::DhcpOptionMap::const_iterator itGlobal; 727 for (settings::DhcpOptionMap::const_iterator it = m->GlobalDhcpOptions.begin(); 728 it != m->GlobalDhcpOptions.end(); 729 ++it) 738 for (settings::DhcpOptionMap::const_iterator it = m->GlobalDhcpOptions.begin(); it != m->GlobalDhcpOptions.end(); ++it) 730 739 addOptionChild(pOptions, (*it).first, (*it).second); 731 740 732 741 /* Process network-adapter-specific options */ 733 742 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 734 HRESULThrc = S_OK;743 hrc = S_OK; 735 744 ComPtr<IMachine> machine; 736 745 ComPtr<INetworkAdapter> nic; 737 746 settings::VmSlot2OptionsIterator it; 738 for (it = m->VmSlot2Options.begin(); it != m->VmSlot2Options.end(); ++it)747 for (it = m->VmSlot2Options.begin(); it != m->VmSlot2Options.end(); ++it) 739 748 { 740 749 alock.release(); … … 782 791 783 792 xml::XmlFileWriter writer(doc); 784 writer.write(m->tempConfigFileName, true);785 786 m->dhcp.setOption(DHCPServerRunner::kDsrKeyConfig, m->tempConfigFileName); 793 writer.write(m->tempConfigFileName, false); 794 795 m->dhcp.setOption(DHCPServerRunner::kDsrKeyConfig, m->tempConfigFileName); /* command line options, not dhcp ones. */ 787 796 m->dhcp.setOption(DHCPServerRunner::kDsrKeyComment, m->networkName.c_str()); 797 788 798 #else /* !VBOX_WITH_DHCPD */ 789 799 /* Main is needed for NATNetwork */ … … 833 843 834 844 845 HRESULT DHCPServer::findLeaseByMAC(const com::Utf8Str &aMac, LONG aType, 846 com::Utf8Str &aAddress, com::Utf8Str &aState, LONG64 *aIssued, LONG64 *aExpire) 847 { 848 /* Reset output before we start */ 849 *aIssued = 0; 850 *aExpire = 0; 851 aAddress.setNull(); 852 aState.setNull(); 853 854 /* 855 * Convert and check input. 856 */ 857 RTMAC MacAddress; 858 int vrc = RTStrConvertHexBytes(aMac.c_str(), &MacAddress, sizeof(MacAddress), RTSTRCONVERTHEXBYTES_F_SEP_COLON); 859 if (vrc != VINF_SUCCESS) 860 return setErrorBoth(E_INVALIDARG, vrc, tr("Invalid MAC address '%s': %Rrc"), aMac.c_str(), vrc); 861 if (aType != 0) 862 return setError(E_INVALIDARG, tr("flags must be zero (not %#x)"), aType); 863 864 /* 865 * Make sure we've got a lease filename to work with. 866 */ 867 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 868 if (m->strLeaseFilename.isEmpty()) 869 { 870 HRESULT hrc = i_calcLeaseFilename(m->networkName.isEmpty() ? mName : m->networkName); 871 if (FAILED(hrc)) 872 return hrc; 873 } 874 875 /* 876 * Try at least twice to read the lease database, more if busy. 877 */ 878 uint64_t const nsStart = RTTimeNanoTS(); 879 for (uint32_t uReadAttempt = 0; ; uReadAttempt++) 880 { 881 /* 882 * Try read the file. 883 */ 884 xml::Document doc; 885 try 886 { 887 xml::XmlFileParser parser; 888 parser.read(m->strLeaseFilename.c_str(), doc); 889 } 890 catch (const xml::EIPRTFailure &e) 891 { 892 vrc = e.rc(); 893 LogThisFunc(("caught xml::EIPRTFailure: rc=%Rrc (attempt %u, msg=%s)\n", vrc, uReadAttempt, e.what())); 894 if ( ( vrc == VERR_FILE_NOT_FOUND 895 || vrc == VERR_OPEN_FAILED 896 || vrc == VERR_ACCESS_DENIED 897 || vrc == VERR_SHARING_VIOLATION 898 || vrc == VERR_READ_ERROR /*?*/) 899 && ( uReadAttempt == 0 900 || ( uReadAttempt < 64 901 && RTTimeNanoTS() - nsStart < RT_NS_1SEC / 4)) ) 902 { 903 alock.release(); 904 905 if (uReadAttempt > 0) 906 RTThreadYield(); 907 RTThreadSleep(8/*ms*/); 908 909 alock.acquire(); 910 LogThisFunc(("Retrying...\n")); 911 continue; 912 } 913 return setErrorBoth(VBOX_E_FILE_ERROR, vrc, "Reading '%s' failed: %Rrc - %s", 914 m->strLeaseFilename.c_str(), vrc, e.what()); 915 } 916 catch (const RTCError &e) 917 { 918 if (e.what()) 919 return setError(VBOX_E_FILE_ERROR, "Reading '%s' failed: %s", m->strLeaseFilename.c_str(), e.what()); 920 return setError(VBOX_E_FILE_ERROR, "Reading '%s' failed: RTCError", m->strLeaseFilename.c_str()); 921 } 922 catch (std::bad_alloc &) 923 { 924 return E_OUTOFMEMORY; 925 } 926 catch (...) 927 { 928 AssertFailed(); 929 return setError(VBOX_E_FILE_ERROR, tr("Reading '%s' failed: Unexpected exception"), m->strLeaseFilename.c_str()); 930 } 931 932 /* 933 * Look for that mac address. 934 */ 935 xml::ElementNode *pElmRoot = doc.getRootElement(); 936 if (pElmRoot && pElmRoot->nameEquals("Leases")) 937 { 938 xml::NodesLoop it(*pElmRoot); 939 const xml::ElementNode *pElmLease; 940 while ((pElmLease = it.forAllNodes()) != NULL) 941 if (pElmLease->nameEquals("Lease")) 942 { 943 const char *pszCurMacAddress = pElmLease->findAttributeValue("mac"); 944 RTMAC CurMacAddress; 945 if ( pszCurMacAddress 946 && RT_SUCCESS(RTNetStrToMacAddr(pszCurMacAddress, &CurMacAddress)) 947 && memcmp(&CurMacAddress, &MacAddress, sizeof(MacAddress)) == 0) 948 { 949 /* 950 * Found it! 951 */ 952 xml::ElementNode const *pElmTime = pElmLease->findChildElement("Time"); 953 int64_t secIssued = 0; 954 uint32_t cSecsToLive = 0; 955 if (pElmTime) 956 { 957 pElmTime->getAttributeValue("issued", &secIssued); 958 pElmTime->getAttributeValue("expiration", &cSecsToLive); 959 *aIssued = secIssued; 960 *aExpire = secIssued + cSecsToLive; 961 } 962 try 963 { 964 aAddress = pElmLease->findChildElementAttributeValue("Address", "value"); 965 aState = pElmLease->findAttributeValue("state"); 966 } 967 catch (std::bad_alloc &) 968 { 969 return E_OUTOFMEMORY; 970 } 971 972 /* Check if the lease has expired in the mean time. */ 973 HRESULT hrc = S_OK; 974 RTTIMESPEC Now; 975 if ( (aState.equals("acked") || aState.equals("offered") || aState.isEmpty()) 976 && secIssued + cSecsToLive < RTTimeSpecGetSeconds(RTTimeNow(&Now))) 977 hrc = aState.assignNoThrow("expired"); 978 return hrc; 979 } 980 } 981 } 982 break; 983 } 984 985 return setError(VBOX_E_OBJECT_NOT_FOUND, tr("Could not find a lease for %RTmac"), &MacAddress); 986 } 987 988 989 /** 990 * Calculates and updates the value of strLeaseFilename given @a aNetwork. 991 */ 992 HRESULT DHCPServer::i_calcLeaseFilename(const com::Utf8Str &aNetwork) 993 { 994 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 995 996 /* The lease file must be the same as we used the last time, so careful when changing this code. */ 997 int vrc = m->strLeaseFilename.assignNoThrow(mVirtualBox->i_homeDir()); 998 if (RT_SUCCESS(vrc)) 999 vrc = RTPathAppendCxx(m->strLeaseFilename, aNetwork); 1000 if (RT_SUCCESS(vrc)) 1001 vrc = m->strLeaseFilename.appendNoThrow("-Dhcpd.leases"); 1002 if (RT_SUCCESS(vrc)) 1003 { 1004 RTPathPurgeFilename(RTPathFilename(m->strLeaseFilename.mutableRaw()), RTPATH_STR_F_STYLE_HOST); 1005 m->strLeaseFilename.jolt(); 1006 return S_OK; 1007 } 1008 return setErrorBoth(E_FAIL, vrc, tr("Failed to construct lease filename: %Rrc"), vrc); 1009 } 1010 835 1011 settings::DhcpOptionMap &DHCPServer::i_findOptMapByVmNameSlot(const com::Utf8Str &aVmName, 836 1012 LONG aSlot) … … 838 1014 return m->VmSlot2Options[settings::VmNameSlotKey(aVmName, aSlot)]; 839 1015 } 1016 -
trunk/src/VBox/Main/src-server/NetworkServiceRunner.cpp
r76553 r79610 16 16 */ 17 17 18 19 /********************************************************************************************************************************* 20 * Header Files * 21 *********************************************************************************************************************************/ 18 22 #include <map> 19 23 #include <string> 20 24 #include "NetworkServiceRunner.h" 25 21 26 #include <iprt/process.h> 27 #include <iprt/path.h> 22 28 #include <iprt/param.h> 23 29 #include <iprt/env.h> … … 26 32 27 33 34 /********************************************************************************************************************************* 35 * Global Variables * 36 *********************************************************************************************************************************/ 37 /** @todo Convert to C strings as this is wastefull: */ 28 38 const std::string NetworkServiceRunner::kNsrKeyName = "--name"; 29 39 const std::string NetworkServiceRunner::kNsrKeyNetwork = "--network"; … … 35 45 const std::string NetworkServiceRunner::kNsrKeyNeedMain = "--need-main"; 36 46 47 48 /********************************************************************************************************************************* 49 * Structures and Typedefs * 50 *********************************************************************************************************************************/ 37 51 struct NetworkServiceRunner::Data 38 52 { … … 44 58 const char *mProcName; 45 59 RTPROCESS mProcess; 46 std::map<std::string, std::string> mOptions; 60 std::map<std::string, std::string> mOptions; /**< @todo r=bird: A map for command line option/value pairs? really? 61 * Wouldn't a simple argument list have done it much much more efficiently? */ 47 62 bool mKillProcOnStop; 48 63 }; 64 65 49 66 50 67 NetworkServiceRunner::NetworkServiceRunner(const char *aProcName) … … 86 103 return VINF_ALREADY_INITIALIZED; 87 104 88 const char * args[10*2]; 89 90 AssertReturn(m->mOptions.size() < 10, VERR_INTERNAL_ERROR); 91 92 /* get the path to the executable */ 93 char exePathBuf[RTPATH_MAX]; 94 const char *exePath = RTProcGetExecutablePath(exePathBuf, RTPATH_MAX); 95 char *substrSl = strrchr(exePathBuf, '/'); 96 char *substrBs = strrchr(exePathBuf, '\\'); 97 char *suffix = substrSl ? substrSl : substrBs; 98 99 if (suffix) 105 /* 106 * Construct the path to the executable. ASSUME it is relative to the 107 * directory that holds VBoxSVC. 108 */ 109 char szExePath[RTPATH_MAX]; 110 AssertReturn(RTProcGetExecutablePath(szExePath, RTPATH_MAX), VERR_FILENAME_TOO_LONG); 111 RTPathStripFilename(szExePath); 112 int vrc = RTPathAppend(szExePath, sizeof(szExePath), m->mProcName); 113 AssertLogRelRCReturn(vrc, vrc); 114 115 /* 116 * Allocate the argument array and construct the argument vector. 117 */ 118 size_t const cArgs = 1 + m->mOptions.size() * 2 + 1; 119 char const **papszArgs = (char const **)RTMemTmpAllocZ(sizeof(papszArgs[0]) * cArgs); 120 AssertReturn(papszArgs, VERR_NO_TMP_MEMORY); 121 122 size_t iArg = 0; 123 papszArgs[iArg++] = szExePath; 124 for (std::map<std::string, std::string>::const_iterator it = m->mOptions.begin(); it != m->mOptions.end(); ++it) 100 125 { 101 suffix++;102 strcpy(suffix, m->mProcName);126 papszArgs[iArg++] = it->first.c_str(); 127 papszArgs[iArg++] = it->second.c_str(); 103 128 } 104 105 int index = 0; 106 107 args[index++] = exePath; 108 109 std::map<std::string, std::string>::const_iterator it; 110 for(it = m->mOptions.begin(); it != m->mOptions.end(); ++it) 111 { 112 args[index++] = it->first.c_str(); 113 args[index++] = it->second.c_str(); 114 } 115 116 args[index++] = NULL; 117 118 int rc = RTProcCreate(suffix ? exePath : m->mProcName, args, RTENV_DEFAULT, 0, &m->mProcess); 129 Assert(iArg + 1 == cArgs); 130 Assert(papszArgs[iArg] == NULL); 131 132 /* 133 * Start the process: 134 */ 135 int rc = RTProcCreate(szExePath, papszArgs, RTENV_DEFAULT, 0, &m->mProcess); 119 136 if (RT_FAILURE(rc)) 120 137 m->mProcess = NIL_RTPROCESS; 121 138 122 139 m->mKillProcOnStop = aKillProcOnStop; 140 141 RTMemTmpFree(papszArgs); 123 142 return rc; 124 143 }
Note:
See TracChangeset
for help on using the changeset viewer.