- Timestamp:
- Jul 12, 2019 12:40:09 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/log.h
r79524 r79732 371 371 /** Main group, IDataStream. */ 372 372 LOG_GROUP_MAIN_DATASTREAM, 373 /** Main group, IDHCPConfig. */ 374 LOG_GROUP_MAIN_DHCPCONFIG, 375 /** Main group, IDHCPGlobalConfig. */ 376 LOG_GROUP_MAIN_DHCPGLOBALCONFIG, 377 /** Main group, IDHCPGroupCondition. */ 378 LOG_GROUP_MAIN_DHCPGROUPCONDITION, 379 /** Main group, IDHCPGroupConfig. */ 380 LOG_GROUP_MAIN_DHCPGROUPCONFIG, 381 /** Main group, IDHCPIndividualConfig. */ 382 LOG_GROUP_MAIN_DHCPINDIVIDUALCONFIG, 373 383 /** Main group, IDHCPServer. */ 374 384 LOG_GROUP_MAIN_DHCPSERVER, … … 892 902 "MAIN_DATAMODEL", \ 893 903 "MAIN_DATASTREAM", \ 904 "MAIN_DHCPCONFIG", \ 905 "MAIN_DHCPGLOBALCONFIG", \ 906 "MAIN_DHCPGROUPCONDITION", \ 907 "MAIN_DHCPGROUPCONFIG", \ 908 "MAIN_DHCPINDIVIDUALCONFIG", \ 894 909 "MAIN_DHCPSERVER", \ 895 910 "MAIN_DIRECTORY", \ -
trunk/include/VBox/settings.h
r78632 r79732 338 338 { 339 339 DhcpOptValue(); 340 DhcpOptValue(const com::Utf8Str &aText, D hcpOptEncoding_T aEncoding = DhcpOptEncoding_Legacy);341 342 com::Utf8Str text;343 D hcpOptEncoding_T encoding;340 DhcpOptValue(const com::Utf8Str &aText, DHCPOptionEncoding_T aEncoding = DHCPOptionEncoding_Legacy); 341 342 com::Utf8Str strValue; 343 DHCPOptionEncoding_T enmEncoding; 344 344 }; 345 345 … … 349 349 typedef DhcpOptionMap::const_iterator DhcpOptConstIterator; 350 350 351 typedef struct VmNameSlotKey 352 { 353 VmNameSlotKey(const com::Utf8Str& aVmName, LONG aSlot); 354 355 bool operator<(const VmNameSlotKey& that) const; 356 357 const com::Utf8Str VmName; 358 LONG Slot; 359 } VmNameSlotKey; 360 361 typedef std::map<VmNameSlotKey, DhcpOptionMap> VmSlot2OptionsMap; 362 typedef VmSlot2OptionsMap::value_type VmSlot2OptionsPair; 363 typedef VmSlot2OptionsMap::iterator VmSlot2OptionsIterator; 364 typedef VmSlot2OptionsMap::const_iterator VmSlot2OptionsConstIterator; 351 struct DHCPConfig 352 { 353 DHCPConfig(); 354 355 DhcpOptionMap OptionMap; 356 uint32_t secMinLeaseTime; 357 uint32_t secDefaultLeaseTime; 358 uint32_t secMaxLeaseTime; 359 }; 360 361 struct DHCPIndividualConfig : DHCPConfig 362 { 363 DHCPIndividualConfig(); 364 365 com::Utf8Str strMACAddress; 366 com::Utf8Str strVMName; 367 ULONG uSlot; 368 com::Utf8Str strFixedAddress; 369 }; 370 371 typedef std::map<com::Utf8Str, DHCPIndividualConfig> DHCPIndividualConfigMap; 365 372 366 373 struct DHCPServer … … 368 375 DHCPServer(); 369 376 370 com::Utf8Str strNetworkName,371 strIPAddress,372 strIPLower,373 374 bool fEnabled;375 D hcpOptionMap GlobalDhcpOptions;376 VmSlot2OptionsMap VmSlot2OptionsM;377 com::Utf8Str strNetworkName; 378 com::Utf8Str strIPAddress; 379 com::Utf8Str strIPLower; 380 com::Utf8Str strIPUpper; 381 bool fEnabled; 382 DHCPConfig GlobalConfig; 383 DHCPIndividualConfigMap IndividualConfigs; 377 384 }; 378 385 … … 409 416 410 417 void readMachineRegistry(const xml::ElementNode &elmMachineRegistry); 411 void readDHCPServers(const xml::ElementNode &elmDHCPServers);412 void readDhcpOptions(DhcpOptionMap& map, const xml::ElementNode& options);413 418 void readNATNetworks(const xml::ElementNode &elmNATNetworks); 414 419 … … 427 432 void buildUSBDeviceSources(xml::ElementNode &elmParent, const USBDeviceSourcesList &ll); 428 433 void readUSBDeviceSources(const xml::ElementNode &elmDeviceSources, USBDeviceSourcesList &ll); 434 void buildDHCPServers(xml::ElementNode &elmDHCPServers, DHCPServersList const &ll); 435 void buildDHCPOptions(xml::ElementNode &elmOptions, DHCPConfig const &rConfig, bool fIgnoreSubnetMask); 436 void readDHCPServers(const xml::ElementNode &elmDHCPServers); 437 void readDHCPOptions(DHCPConfig &rConfig, const xml::ElementNode &elmOptions, bool fIgnoreSubnetMask); 429 438 bool convertGuiProxySettings(const com::Utf8Str &strUIProxySettings); 430 439 }; -
trunk/src/VBox/Main/Makefile.kmk
r79360 r79732 550 550 src-server/DataStreamImpl.cpp \ 551 551 src-server/DHCPServerImpl.cpp \ 552 src-server/DHCPConfigImpl.cpp \ 552 553 src-server/NetworkServiceRunner.cpp \ 553 554 src-server/NATNetworkImpl.cpp \ -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r79727 r79732 1824 1824 1825 1825 <enum 1826 name="D hcpOptEncoding"1827 uuid="8 8ea6d70-8648-4871-ba30-1f49c61cfaa2">1826 name="DHCPOptionEncoding" 1827 uuid="84b6d460-2838-4682-c0d6-ef5b573ef28a"> 1828 1828 <const name="Legacy" value="0"/> 1829 <const name="Hex" value="1"/> 1829 <const name="Hex" value="1"/> 1830 </enum> 1831 1832 <enum 1833 name="DHCPConfigScope" 1834 uuid="151df7cd-e596-42dd-235a-b164a781c099"> 1835 <const name="Global" value="0"><desc><link to="IDHCPServer::globalConfig"/></desc></const> 1836 <const name="MachineNIC" value="1"><desc><link to="IDHCPServer::individualConfigs"/></desc></const> 1837 <const name="MAC" value="2"><desc><link to="IDHCPServer::individualConfigs"/></desc></const> 1838 <const name="Group" value="3"><desc><link to="IDHCPServer::groupConfigs"/></desc></const> 1839 </enum> 1840 1841 <enum 1842 name="DHCPGroupFilterType" 1843 uuid="0639cd66-94b7-41ef-18ac-485636e46d97" 1844 > 1845 <const name="MAC" value="0"><desc>MAC address</desc></const> 1846 <const name="MACWildcard" value="1"><desc>MAC address wildcard pattern.</desc></const> 1847 <const name="vendorClassID" value="2"><desc>Vendor class ID</desc></const> 1848 <const name="vendorClassIDWildcard" value="3"><desc>Vendor class ID wildcard pattern.</desc></const> 1849 <const name="userClassID" value="4"><desc>User class ID</desc></const> 1850 <const name="userClassIDWildcard" value="5"><desc>User class ID wildcard pattern.</desc></const> 1830 1851 </enum> 1831 1852 … … 1834 1855 uuid="ea2d467f-b6c2-4b9a-8eb5-6e2f275dd72e" 1835 1856 wsmap="managed" 1836 reservedMethods=" 1" reservedAttributes="6"1857 reservedMethods="0" reservedAttributes="3" 1837 1858 > 1838 1859 <desc> … … 1881 1902 1882 1903 <method name="addGlobalOption"> 1904 <desc>6.0 legacy, will be removed in 6.1.</desc> 1883 1905 <param name="option" type="DhcpOpt" dir="in"/> 1884 1906 <param name="value" type="wstring" dir="in" /> … … 1886 1908 1887 1909 <method name="removeGlobalOption"> 1888 <desc> 1889 removes the specified option 1890 <result name="E_INVALIDARG"> 1891 invalid option id supplied 1892 </result> 1893 </desc> 1910 <desc>6.0 legacy, will be removed in 6.1.</desc> 1894 1911 <param name="option" type="DhcpOpt" dir="in"/> 1895 1912 </method> 1896 1913 1897 1914 <method name="removeGlobalOptions"> 1898 <desc> 1899 removes all global options 1900 <result name="E_FAIL"> 1901 failed to remove global options 1902 </result> 1903 </desc> 1915 <desc>Legacy interface, will be removed in 6.1.</desc> 1904 1916 </method> 1905 1917 1906 1918 <!-- string in format: "option_id:value" --> 1907 <attribute name="globalOptions" type="wstring" safearray="yes" readonly="yes"/> 1919 <attribute name="globalOptions" type="wstring" safearray="yes" readonly="yes"> 1920 <desc>Legacy interface, will be removed in 6.1.</desc> 1921 </attribute> 1908 1922 1909 1923 <!-- string in format: "[vm name]:slot" --> 1910 <attribute name="vmConfigs" type="wstring" safearray="yes" readonly="yes"/> 1924 <attribute name="vmConfigs" type="wstring" safearray="yes" readonly="yes"> 1925 <desc>Legacy interface, will be removed in 6.1.</desc> 1926 </attribute> 1927 1928 <attribute name="globalConfig" type="IDHCPGlobalConfig" readonly="yes"> 1929 <desc>Global configuration that applies to all clients.</desc> 1930 </attribute> 1931 1932 <attribute name="groupConfigs" type="IDHCPGroupConfig" safearray="yes" readonly="yes"> 1933 <desc>Configuration groups that applies to selected clients, selection is flexible.</desc> 1934 </attribute> 1935 1936 <attribute name="individualConfigs" type="IDHCPIndividualConfig" safearray="yes" readonly="yes"> 1937 <desc>Individual NIC configurations either by MAC address or VM + NIC number.</desc> 1938 </attribute> 1911 1939 1912 1940 <!-- VM-slot settings … … 1931 1959 --> 1932 1960 <method name="addVmSlotOption"> 1961 <desc>6.0 legacy, will be removed in 6.1.</desc> 1933 1962 <param name="vmname" type="wstring" dir="in"/> 1934 1963 <param name="slot" type="long" dir="in"/> … … 1938 1967 1939 1968 <method name="removeVmSlotOption"> 1940 <desc> 1941 removes the specified option 1942 <result name="E_INVALIDARG"> 1943 invalid VM, slot, or option id supplied 1944 </result> 1945 </desc> 1969 <desc>6.0 legacy, will be removed in 6.1.</desc> 1946 1970 <param name="vmname" type="wstring" dir="in"/> 1947 1971 <param name="slot" type="long" dir="in"/> … … 1950 1974 1951 1975 <method name="removeVmSlotOptions"> 1952 <desc> 1953 removes all option for the specified adapter 1954 <result name="E_INVALIDARG"> 1955 invalid VM or slot supplied 1956 </result> 1957 </desc> 1976 <desc>6.0 legacy, will be removed in 6.1.</desc> 1958 1977 <param name="vmname" type="wstring" dir="in"/> 1959 1978 <param name="slot" type="long" dir="in"/> … … 1962 1981 <!-- returns array of strings in format: "option_id:value" for a given pair (vm, slot) --> 1963 1982 <method name="getVmSlotOptions"> 1983 <desc>6.0 legacy, will be removed in 6.1.</desc> 1964 1984 <param name="vmname" type="wstring" dir="in"/> 1965 1985 <param name="slot" type="long" dir="in"/> … … 1969 1989 <!-- Returns options by MAC address --> 1970 1990 <method name="getMacOptions"> 1991 <desc>6.0 legacy, will be removed in 6.1.</desc> 1971 1992 <param name="mac" type="wstring" dir="in"/> 1972 1993 <param name="option" type="wstring" safearray="yes" dir="return"/> … … 2074 2095 </method> 2075 2096 2097 <method name="getConfig"> 2098 <desc> 2099 Gets or adds a configuration. 2100 </desc> 2101 <param name="scope" dir="in" type="DHCPConfigScope"> 2102 <desc>The kind of configuration being sought or added.</desc> 2103 </param> 2104 <param name="name" dir="in" type="wstring"> 2105 <desc> 2106 Meaning depends on the @a scope: 2107 - Ignored when the @a scope is <link to="DHCPConfigScope::Global"/>. 2108 - A VM name or UUID for <link to="DHCPConfigScope::MachineNIC"/>. 2109 - A MAC address for <link to="DHCPConfigScope::MAC"/>. 2110 - A group name for <link to="DHCPConfigScope::Group"/>. 2111 </desc> 2112 </param> 2113 <param name="slot" dir="in" type="unsigned long"> 2114 <desc>The NIC slot when @a scope is set to <link to="DHCPConfigScope::MachineNIC"/>, 2115 must be zero for all other scope values. 2116 </desc> 2117 </param> 2118 <param name="mayAdd" dir="in" type="boolean"> 2119 <desc> 2120 Set to @c TRUE if the configuration should be added if not found. 2121 If set to @c FALSE the method will fail with VBOX_E_OBJECT_NOT_FOUND. 2122 </desc> 2123 </param> 2124 <param name="config" dir="return" type="IDHCPConfig"> 2125 <desc>The requested configuration.</desc> 2126 </param> 2127 </method> 2128 2076 2129 <!-- @todo Add variant of queryLeaseByMac that goes by VM name and optionally slot. --> 2077 <!-- @todo Add min/default/max lease time settings -->2078 2130 <!-- @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). --> 2131 2132 </interface> 2133 2134 <interface 2135 name="IDHCPConfig" extends="$unknown" 2136 uuid="38fdb664-f65e-4905-ee56-a8a912871bbf" 2137 wsmap="managed" 2138 reservedMethods="8" reservedAttributes="16" 2139 > 2140 <desc> 2141 The DHCP server has several configuration levels: global, group and 2142 individual MAC. This interface implements the settings common to 2143 each level. 2144 </desc> 2145 2146 <attribute name="scope" type="DHCPConfigScope" readonly="yes"> 2147 <desc> 2148 Indicates the kind of config this is (mostly for IDHCPIndividualConfig). 2149 </desc> 2150 </attribute> 2151 2152 <attribute name="minLeaseTime" type="unsigned long" readonly="no"> 2153 <desc>The minimum lease time in seconds, ignored if zero.</desc> 2154 </attribute> 2155 <attribute name="defaultLeaseTime" type="unsigned long" readonly="no"> 2156 <desc>The default lease time in seconds, ignored if zero.</desc> 2157 </attribute> 2158 <attribute name="maxLeaseTime" type="unsigned long" readonly="no"> 2159 <desc>The maximum lease time in seconds, ignored if zero.</desc> 2160 </attribute> 2161 2162 <method name="setOption"> 2163 <desc> 2164 Sets a DHCP option. 2165 </desc> 2166 <param name="option" dir="in" type="DhcpOpt"> 2167 <desc>The DHCP option.</desc> 2168 </param> 2169 <param name="encoding" dir="in" type="DHCPOptionEncoding"> 2170 <desc>The value encoding.</desc> 2171 </param> 2172 <param name="value" dir="in" type="wstring"> 2173 <desc>The DHCP option value. The exact format depends on the DHCP 2174 option and should be documented in <link to="DhcpOpt"/>. 2175 </desc> 2176 </param> 2177 </method> 2178 2179 <method name="removeOption"> 2180 <desc>Removes the given DHCP option.</desc> 2181 <param name="option" dir="in" type="DhcpOpt"/> 2182 </method> 2183 2184 <method name="removeAllOptions"> 2185 <desc> 2186 Removes all the options. 2187 2188 One exception here is the DhcpOpt_SubnetMask option in the global scope 2189 that is linked to the <link to="IDHCPServer::networkMask"/> attribute 2190 and therefore cannot be removed. 2191 </desc> 2192 </method> 2193 2194 <method name="getOption"> 2195 <desc>Gets the value of a single DHCP option.</desc> 2196 <param name="option" dir="in" type="DhcpOpt"> 2197 <desc>The DHCP option being sought.</desc> 2198 </param> 2199 <param name="encoding" dir="out" type="DHCPOptionEncoding"> 2200 <desc>The value encoding.</desc> 2201 </param> 2202 <param name="value" dir="return" type="wstring"> 2203 <desc>The value of the requested DHCP option.</desc> 2204 </param> 2205 </method> 2206 2207 <method name="getAllOptions"> 2208 <desc>Gets all DHCP options and their values</desc> 2209 <param name="options" dir="out" type="DhcpOpt" safearray="yes"> 2210 <desc>Array containing the DHCP option numbers.</desc> 2211 </param> 2212 <param name="encodings" dir="out" type="DHCPOptionEncoding" safearray="yes"> 2213 <desc>Array of value encodings that runs parallel to @a options.</desc> 2214 </param> 2215 <param name="values" dir="return" type="wstring" safearray="yes"> 2216 <desc>Array of values that runs parallel to @a options and @a encodings.</desc> 2217 </param> 2218 </method> 2219 </interface> 2220 2221 <interface 2222 name="IDHCPGlobalConfig" extends="IDHCPConfig" 2223 uuid="5d7bb1ea-27ed-4e01-3859-4302dd55f796" 2224 wsmap="managed" 2225 reservedMethods="4" reservedAttributes="4" 2226 > 2227 <desc> 2228 The global DHCP server configuration, see <link to="IDHCPServer::globalConfig"/>. 2229 </desc> 2230 2231 <attribute name="midlDoesNotLikeEmptyInterfaces" readonly="yes" type="boolean"/> 2232 </interface> 2233 2234 <interface 2235 name="IDHCPGroupCondition" extends="$unknown" 2236 uuid="5ca9e537-5a1d-43f1-6f27-6a0db298a9a8" 2237 wsmap="managed" 2238 reservedMethods="3" reservedAttributes="3" 2239 > 2240 <attribute name="inclusive" type="boolean" readonly="no"> 2241 <desc>Whether this is an inclusive or exclusive group membership condition</desc> 2242 </attribute> 2243 <attribute name="type" type="DHCPGroupFilterType" readonly="no"> 2244 <desc>Defines how the <link to="IDHCPGroupCondition::value"/> is interpreted.</desc> 2245 </attribute> 2246 <attribute name="value" type="wstring" readonly="no"> 2247 <desc>The condition value.</desc> 2248 </attribute> 2249 <method name="remove"> 2250 <desc>Remove this condition from the group.</desc> 2251 </method> 2252 </interface> 2253 2254 <interface 2255 name="IDHCPGroupConfig" extends="IDHCPConfig" 2256 uuid="406a5eca-d032-4f65-a882-6bb626a424a5" 2257 wsmap="managed" 2258 reservedMethods="8" reservedAttributes="8" 2259 > 2260 <desc> 2261 A configuration that applies to a group of NICs. 2262 </desc> 2263 2264 <attribute name="name" type="wstring" readonly="no"> 2265 <desc>The group name.</desc> 2266 </attribute> 2267 2268 <attribute name="conditions" type="IDHCPGroupCondition" safearray="yes" readonly="yes"> 2269 <desc> 2270 Group membership conditions. 2271 2272 Add new conditions by calling <link to="IDHCPGroupConfig::addCondition"/> 2273 and use <link to="IDHCPGroupCondition::remove"/> to remove. 2274 </desc> 2275 </attribute> 2276 2277 <method name="addCondition"> 2278 <param name="inclusive" dir="in" type="boolean"/> 2279 <param name="type" dir="in" type="DHCPGroupFilterType"/> 2280 <param name="value" dir="in" type="wstring"/> 2281 </method> 2282 2283 </interface> 2284 2285 <interface 2286 name="IDHCPIndividualConfig" extends="IDHCPConfig" 2287 uuid="c40c2b86-73a5-46cc-8227-93fe57d006a6" 2288 wsmap="managed" 2289 reservedMethods="8" reservedAttributes="8" 2290 > 2291 <desc> 2292 Configuration for a single NIC, either given directly by MAC address or by 2293 VM + adaptor slot number. 2294 </desc> 2295 2296 <attribute name="MACAddress" type="wstring" readonly="yes"> 2297 <desc> 2298 The MAC address. If a <link to="DHCPConfigScope::MachineNIC"/> config, this 2299 will be queried via the VM ID. 2300 </desc> 2301 </attribute> 2302 2303 <attribute name="machineId" type="uuid" mod="string" readonly="yes"> 2304 <desc> 2305 The virtual machine ID if a <link to="DHCPConfigScope::MachineNIC"/> config, 2306 null UUID for <link to="DHCPConfigScope::MAC"/>. 2307 </desc> 2308 </attribute> 2309 2310 <attribute name="slot" type="unsigned long" readonly="yes"> 2311 <desc>The NIC slot number of the VM if a <link to="DHCPConfigScope::MachineNIC"/> config.</desc> 2312 </attribute> 2313 2314 <attribute name="fixedAddress" type="wstring" readonly="no"> 2315 <desc>Fixed IPv4 address assignment, dynamic if empty.</desc> 2316 </attribute> 2083 2317 2084 2318 </interface> -
trunk/src/VBox/Main/include/DHCPServerImpl.h
r79644 r79732 32 32 } 33 33 34 class DHCPConfig; 35 class DHCPIndividualConfig; 34 36 35 37 /** 38 * A DHCP server for internal host-only & NAT networks. 39 * 40 * Old notes: 41 * 36 42 * for server configuration needs, it's perhaps better to use (VM,slot) pair 37 43 * (vm-name, slot) <----> (MAC) … … 49 55 { 50 56 public: 57 /** @name Constructors and destructors 58 * @{ */ 59 DECLARE_EMPTY_CTOR_DTOR(DHCPServer) 60 HRESULT FinalConstruct(); 61 void FinalRelease(); 51 62 52 DECLARE_EMPTY_CTOR_DTOR(DHCPServer) 63 HRESULT init(VirtualBox *aVirtualBox, const com::Utf8Str &aName); 64 HRESULT init(VirtualBox *aVirtualBox, const settings::DHCPServer &data); 65 void uninit(); 66 /** @} */ 53 67 54 HRESULT FinalConstruct(); 55 void FinalRelease(); 56 57 HRESULT init(VirtualBox *aVirtualBox, 58 const com::Utf8Str &aName); 59 HRESULT init(VirtualBox *aVirtualBox, 60 const settings::DHCPServer &data); 61 void uninit(); 62 63 // Public internal methids. 68 /** @name Public internal methods. 69 * @{ */ 64 70 HRESULT i_saveSettings(settings::DHCPServer &data); 65 settings::DhcpOptionMap &i_findOptMapByVmNameSlot(const com::Utf8Str &aVmName, LONG Slot);71 /** @} */ 66 72 67 73 private: 68 HRESULT encodeOption(com::Utf8Str &aEncoded, uint32_t aOptCode, const settings::DhcpOptValue &aOptValue); 69 int addOption(settings::DhcpOptionMap &aMap, DhcpOpt_T aOption, const com::Utf8Str &aValue); 74 /** @name IDHCPServer Properties 75 * @{ */ 76 HRESULT getEventSource(ComPtr<IEventSource> &aEventSource) RT_OVERRIDE; 77 HRESULT getEnabled(BOOL *aEnabled) RT_OVERRIDE; 78 HRESULT setEnabled(BOOL aEnabled) RT_OVERRIDE; 79 HRESULT getIPAddress(com::Utf8Str &aIPAddress) RT_OVERRIDE; 80 HRESULT getNetworkMask(com::Utf8Str &aNetworkMask) RT_OVERRIDE; 81 HRESULT getNetworkName(com::Utf8Str &aName) RT_OVERRIDE; 82 HRESULT getLowerIP(com::Utf8Str &aIPAddress) RT_OVERRIDE; 83 HRESULT getUpperIP(com::Utf8Str &aIPAddress) RT_OVERRIDE; 84 HRESULT getGlobalOptions(std::vector<com::Utf8Str> &aGlobalOptions) RT_OVERRIDE; 85 HRESULT getVmConfigs(std::vector<com::Utf8Str> &aVmConfigs) RT_OVERRIDE; 86 HRESULT getMacOptions(const com::Utf8Str &aMAC, std::vector<com::Utf8Str> &aValues) RT_OVERRIDE; 87 HRESULT setConfiguration(const com::Utf8Str &aIPAddress, const com::Utf8Str &aNetworkMask, 88 const com::Utf8Str &aFromIPAddress, const com::Utf8Str &aToIPAddress) RT_OVERRIDE; 89 HRESULT getVmSlotOptions(const com::Utf8Str &aVmName, LONG aSlot, std::vector<com::Utf8Str> &aValues) RT_OVERRIDE; 90 HRESULT getGlobalConfig(ComPtr<IDHCPGlobalConfig> &aGlobalConfig) RT_OVERRIDE; 91 HRESULT getGroupConfigs(std::vector<ComPtr<IDHCPGroupConfig> > &aGroupConfigs) RT_OVERRIDE; 92 HRESULT getIndividualConfigs(std::vector<ComPtr<IDHCPIndividualConfig> > &aIndividualConfigs) ; 93 /** @} */ 70 94 71 // wrapped IDHCPServer properties 72 HRESULT getEventSource(ComPtr<IEventSource> &aEventSource); 73 HRESULT getEnabled(BOOL *aEnabled); 74 HRESULT setEnabled(BOOL aEnabled); 75 HRESULT getIPAddress(com::Utf8Str &aIPAddress); 76 HRESULT getNetworkMask(com::Utf8Str &aNetworkMask); 77 HRESULT getNetworkName(com::Utf8Str &aName); 78 HRESULT getLowerIP(com::Utf8Str &aIPAddress); 79 HRESULT getUpperIP(com::Utf8Str &aIPAddress); 80 HRESULT getGlobalOptions(std::vector<com::Utf8Str> &aGlobalOptions); 81 HRESULT getVmConfigs(std::vector<com::Utf8Str> &aVmConfigs); 82 HRESULT getMacOptions(const com::Utf8Str &aMAC, std::vector<com::Utf8Str> &aValues); 83 HRESULT setConfiguration(const com::Utf8Str &aIPAddress, 84 const com::Utf8Str &aNetworkMask, 85 const com::Utf8Str &aFromIPAddress, 86 const com::Utf8Str &aToIPAddress); 87 HRESULT getVmSlotOptions(const com::Utf8Str &aVmName, 88 LONG aSlot, 89 std::vector<com::Utf8Str> &aValues); 90 91 // Wrapped IDHCPServer Methods 92 HRESULT addGlobalOption(DhcpOpt_T aOption, 93 const com::Utf8Str &aValue); 94 HRESULT removeGlobalOption(DhcpOpt_T aOption); 95 HRESULT removeGlobalOptions(); 96 HRESULT addVmSlotOption(const com::Utf8Str &aVmName, 97 LONG aSlot, 98 DhcpOpt_T aOption, 99 const com::Utf8Str &aValue); 100 HRESULT removeVmSlotOption(const com::Utf8Str &aVmName, 101 LONG aSlot, 102 DhcpOpt_T aOption); 103 HRESULT removeVmSlotOptions(const com::Utf8Str &aVmName, 104 LONG aSlot); 105 HRESULT start(const com::Utf8Str &aNetworkName, 106 const com::Utf8Str &aTrunkName, 107 const com::Utf8Str &aTrunkType); 108 HRESULT stop(); 109 HRESULT restart(); 110 HRESULT findLeaseByMAC(const com::Utf8Str &aMac, LONG aType, 111 com::Utf8Str &aAddress, com::Utf8Str &aState, LONG64 *aIssued, LONG64 *aExpire) RT_OVERRIDE; 95 /** @name IDHCPServer Methods 96 * @{ */ 97 HRESULT addGlobalOption(DhcpOpt_T aOption, const com::Utf8Str &aValue) RT_OVERRIDE; 98 HRESULT removeGlobalOption(DhcpOpt_T aOption) RT_OVERRIDE; 99 HRESULT removeGlobalOptions() RT_OVERRIDE; 100 HRESULT addVmSlotOption(const com::Utf8Str &aVmName, LONG aSlot, DhcpOpt_T aOption, const com::Utf8Str &aValue) RT_OVERRIDE; 101 HRESULT removeVmSlotOption(const com::Utf8Str &aVmName, LONG aSlot, DhcpOpt_T aOption) RT_OVERRIDE; 102 HRESULT removeVmSlotOptions(const com::Utf8Str &aVmName, LONG aSlot) RT_OVERRIDE; 103 HRESULT start(const com::Utf8Str &aNetworkName, const com::Utf8Str &aTrunkName, const com::Utf8Str &aTrunkType) RT_OVERRIDE; 104 HRESULT stop() RT_OVERRIDE; 105 HRESULT restart() RT_OVERRIDE; 106 HRESULT findLeaseByMAC(const com::Utf8Str &aMac, LONG aType, com::Utf8Str &aAddress, com::Utf8Str &aState, 107 LONG64 *aIssued, LONG64 *aExpire) RT_OVERRIDE; 108 HRESULT getConfig(DHCPConfigScope_T aScope, const com::Utf8Str &aName, ULONG aSlot, BOOL aMayAdd, 109 ComPtr<IDHCPConfig> &aConfig) RT_OVERRIDE; 110 /** @} */ 112 111 113 112 /** @name Helpers 114 113 * @{ */ 114 HRESULT i_doSaveSettings(); 115 115 HRESULT i_calcLeasesFilename(const com::Utf8Str &aNetwork) RT_NOEXCEPT; 116 HRESULT i_writeDhcpdConfig(const char *pszFilename, uint32_t uMACAddressVersion) RT_NOEXCEPT; 117 118 HRESULT i_vmNameToIdAndValidateSlot(const com::Utf8Str &aVmName, LONG aSlot, com::Guid &idMachine); 119 HRESULT i_vmNameAndSlotToConfig(const com::Utf8Str &a_strVmName, LONG a_uSlot, bool a_fCreateIfNeeded, 120 ComObjPtr<DHCPIndividualConfig> &a_rPtrConfig); 121 122 HRESULT i_encode60Option(com::Utf8Str &strEncoded, DhcpOpt_T enmOption, 123 DHCPOptionEncoding_T enmEncoding, const com::Utf8Str &strValue); 124 HRESULT i_getAllOptions60(DHCPConfig &aSourceConfig, std::vector<com::Utf8Str> &aValues); 125 HRESULT i_add60Option(DHCPConfig &aTargetConfig, DhcpOpt_T aOption, const com::Utf8Str &aValue); 116 126 /** @} */ 117 127 128 /** Private data */ 118 129 struct Data; 130 /** Private data. */ 119 131 Data *m; 120 /** weak VirtualBox parent */121 VirtualBox *const mVirtualBox;122 const Utf8Str mName;123 132 }; 124 133 -
trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp
r79644 r79732 21 21 *********************************************************************************************************************************/ 22 22 #define LOG_GROUP LOG_GROUP_MAIN_DHCPSERVER 23 #include "NetworkServiceRunner.h"24 23 #include "DHCPServerImpl.h" 25 #include "AutoCaller.h"26 24 #include "LoggingNew.h" 27 25 … … 38 36 #include <VBox/settings.h> 39 37 38 #include "AutoCaller.h" 39 #include "DHCPConfigImpl.h" 40 #include "MachineImpl.h" 41 #include "NetworkServiceRunner.h" 40 42 #include "VirtualBoxImpl.h" 41 43 … … 84 86 { 85 87 Data() 86 : enabled(FALSE) 87 , router(false) 88 : pVirtualBox(NULL) 89 , strName() 90 , enabled(FALSE) 91 // , router(false) 92 , uIndividualMACAddressVersion(1) 88 93 { 89 94 szTempConfigFileName[0] = '\0'; 90 95 } 96 97 /** weak VirtualBox parent */ 98 VirtualBox * const pVirtualBox; 99 /** The DHCP server name (network). 100 * @todo Kind of duplicated by networkName, if I understand it correctly. */ 101 Utf8Str const strName; 91 102 92 103 Utf8Str IPAddress; … … 95 106 96 107 BOOL enabled; 108 #if 0 109 /** Don't quit get WTF this is about, but the old addOption method contained the 110 * following hint: "Indirect way to understand that we're on NAT network." 111 * 112 * Apparently this is a busted with the new dhcpd implementation, so we don't 113 * maintain it with the API overhaul in 6.0.12. 114 */ 97 115 bool router; 116 #endif 98 117 DHCPServerRunner dhcp; 99 100 settings::DhcpOptionMap GlobalDhcpOptions;101 settings::VmSlot2OptionsMap VmSlot2Options;102 118 103 119 char szTempConfigFileName[RTPATH_MAX]; … … 106 122 com::Utf8Str trunkName; 107 123 com::Utf8Str trunkType; 124 125 /** Global configuration. */ 126 ComObjPtr<DHCPGlobalConfig> globalConfig; 127 128 /** Group configuration indexed by name. */ 129 std::map<com::Utf8Str, ComObjPtr<DHCPGroupConfig>> groupConfigs; 130 /** Iterator for groupConfigs. */ 131 typedef std::map<com::Utf8Str, ComObjPtr<DHCPGroupConfig>>::iterator GroupConfigIterator; 132 133 /** Individual (host) configuration indexed by MAC address or VM UUID. */ 134 std::map<com::Utf8Str, ComObjPtr<DHCPIndividualConfig>> individualConfigs; 135 /** Iterator for individualConfigs. */ 136 typedef std::map<com::Utf8Str, ComObjPtr<DHCPIndividualConfig>>::iterator IndividualConfigIterator; 137 138 /** Part of a lock-avoidance hack to resolve the VM ID + slot into MAC 139 * addresses before writing out the Dhcpd configuration file. */ 140 uint32_t uIndividualMACAddressVersion; 108 141 }; 109 142 … … 115 148 DHCPServer::DHCPServer() 116 149 : m(NULL) 117 , mVirtualBox(NULL)118 150 { 119 151 m = new DHCPServer::Data(); … … 139 171 void DHCPServer::FinalRelease() 140 172 { 141 uninit (); 142 173 uninit(); 143 174 BaseFinalRelease(); 144 175 } … … 155 186 stop(); 156 187 157 unconst(m VirtualBox) = NULL;188 unconst(m->pVirtualBox) = NULL; 158 189 } 159 190 … … 167 198 168 199 /* share VirtualBox weakly (parent remains NULL so far) */ 169 unconst(m VirtualBox) = aVirtualBox;170 171 unconst(m Name) = aName;200 unconst(m->pVirtualBox) = aVirtualBox; 201 202 unconst(m->strName) = aName; 172 203 m->IPAddress = "0.0.0.0"; 173 m->GlobalDhcpOptions[DhcpOpt_SubnetMask] = settings::DhcpOptValue("0.0.0.0"); 174 m->enabled = FALSE; 175 176 m->lowerIP = "0.0.0.0"; 177 m->upperIP = "0.0.0.0"; 178 179 /* Confirm a successful initialization */ 180 autoInitSpan.setSucceeded(); 181 182 return S_OK; 183 } 184 185 186 HRESULT DHCPServer::init(VirtualBox *aVirtualBox, const settings::DHCPServer &data) 204 m->lowerIP = "0.0.0.0"; 205 m->upperIP = "0.0.0.0"; 206 m->enabled = FALSE; 207 208 /* Global configuration: */ 209 HRESULT hrc = m->globalConfig.createObject(); 210 if (SUCCEEDED(hrc)) 211 hrc = m->globalConfig->initWithDefaults(aVirtualBox, this); 212 213 /* Confirm a successful initialization or not: */ 214 if (SUCCEEDED(hrc)) 215 autoInitSpan.setSucceeded(); 216 else 217 autoInitSpan.setFailed(hrc); 218 return hrc; 219 } 220 221 222 HRESULT DHCPServer::init(VirtualBox *aVirtualBox, const settings::DHCPServer &rData) 187 223 { 188 224 /* Enclose the state transition NotReady->InInit->Ready */ … … 191 227 192 228 /* share VirtualBox weakly (parent remains NULL so far) */ 193 unconst(mVirtualBox) = aVirtualBox; 194 195 unconst(mName) = data.strNetworkName; 196 m->IPAddress = data.strIPAddress; 197 m->enabled = data.fEnabled; 198 m->lowerIP = data.strIPLower; 199 m->upperIP = data.strIPUpper; 200 201 m->GlobalDhcpOptions.clear(); 202 m->GlobalDhcpOptions.insert(data.GlobalDhcpOptions.begin(), data.GlobalDhcpOptions.end()); 203 204 m->VmSlot2Options.clear(); 205 m->VmSlot2Options.insert(data.VmSlot2OptionsM.begin(), data.VmSlot2OptionsM.end()); 206 207 autoInitSpan.setSucceeded(); 208 209 return S_OK; 210 } 211 212 213 HRESULT DHCPServer::i_saveSettings(settings::DHCPServer &data) 229 unconst(m->pVirtualBox) = aVirtualBox; 230 231 unconst(m->strName) = rData.strNetworkName; 232 m->IPAddress = rData.strIPAddress; 233 m->enabled = rData.fEnabled; 234 m->lowerIP = rData.strIPLower; 235 m->upperIP = rData.strIPUpper; 236 237 /* 238 * Global configuration: 239 */ 240 HRESULT hrc = m->globalConfig.createObject(); 241 if (SUCCEEDED(hrc)) 242 hrc = m->globalConfig->initWithSettings(aVirtualBox, this, rData.GlobalConfig); 243 244 /* 245 * Group configurations: 246 */ 247 248 /* 249 * Individual configuration: 250 */ 251 Assert(m->individualConfigs.size() == 0); 252 if (SUCCEEDED(hrc)) 253 { 254 for (settings::DHCPIndividualConfigMap::const_iterator it = rData.IndividualConfigs.begin(); 255 it != rData.IndividualConfigs.end() && SUCCEEDED(hrc); ++it) 256 { 257 ComObjPtr<DHCPIndividualConfig> ptrIndiCfg; 258 com::Utf8Str strKey; 259 if (!it->second.strVMName.isNotEmpty()) 260 { 261 RTMAC MACAddress; 262 int vrc = RTNetStrToMacAddr(it->second.strMACAddress.c_str(), &MACAddress); 263 if (RT_FAILURE(vrc)) 264 { 265 LogRel(("Ignoring invalid MAC address for individual DHCP config: '%s' - %Rrc\n", it->second.strMACAddress.c_str(), vrc)); 266 continue; 267 } 268 269 vrc = strKey.printfNoThrow("%RTmac", &MACAddress); 270 AssertRCReturn(vrc, E_OUTOFMEMORY); 271 272 hrc = ptrIndiCfg.createObject(); 273 if (SUCCEEDED(hrc)) 274 hrc = ptrIndiCfg->initWithSettingsAndMACAddress(aVirtualBox, this, it->second, &MACAddress); 275 } 276 else 277 { 278 /* This ASSUMES that we're being called after the machines have been 279 loaded so we can resolve VM names into UUID for old settings. */ 280 com::Guid idMachine; 281 hrc = i_vmNameToIdAndValidateSlot(it->second.strVMName, it->second.uSlot, idMachine); 282 if (SUCCEEDED(hrc)) 283 { 284 hrc = ptrIndiCfg.createObject(); 285 if (SUCCEEDED(hrc)) 286 hrc = ptrIndiCfg->initWithSettingsAndMachineIdAndSlot(aVirtualBox, this, it->second, 287 idMachine, it->second.uSlot, 288 m->uIndividualMACAddressVersion - UINT32_MAX / 4); 289 } 290 } 291 if (SUCCEEDED(hrc)) 292 { 293 try 294 { 295 m->individualConfigs[strKey] = ptrIndiCfg; 296 } 297 catch (std::bad_alloc &) 298 { 299 return E_OUTOFMEMORY; 300 } 301 } 302 } 303 } 304 305 /* Confirm a successful initialization or not: */ 306 if (SUCCEEDED(hrc)) 307 autoInitSpan.setSucceeded(); 308 else 309 autoInitSpan.setFailed(hrc); 310 return hrc; 311 } 312 313 314 HRESULT DHCPServer::i_saveSettings(settings::DHCPServer &rData) 214 315 { 215 316 AutoCaller autoCaller(this); … … 218 319 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 219 320 220 data.strNetworkName = mName; 221 data.strIPAddress = m->IPAddress; 222 223 data.fEnabled = !!m->enabled; 224 data.strIPLower = m->lowerIP; 225 data.strIPUpper = m->upperIP; 226 227 data.GlobalDhcpOptions.clear(); 228 data.GlobalDhcpOptions.insert(m->GlobalDhcpOptions.begin(), 229 m->GlobalDhcpOptions.end()); 230 231 data.VmSlot2OptionsM.clear(); 232 data.VmSlot2OptionsM.insert(m->VmSlot2Options.begin(), 233 m->VmSlot2Options.end()); 234 235 return S_OK; 321 rData.strNetworkName = m->strName; 322 rData.strIPAddress = m->IPAddress; 323 rData.fEnabled = m->enabled != FALSE; 324 rData.strIPLower = m->lowerIP; 325 rData.strIPUpper = m->upperIP; 326 327 /* Global configuration: */ 328 HRESULT hrc = m->globalConfig->i_saveSettings(rData.GlobalConfig); 329 330 /* Group configuration: */ 331 332 /* Individual configuration: */ 333 for (Data::IndividualConfigIterator it = m->individualConfigs.begin(); 334 it != m->individualConfigs.end() && SUCCEEDED(hrc); ++it) 335 { 336 try 337 { 338 rData.IndividualConfigs[it->first] = settings::DHCPIndividualConfig(); 339 } 340 catch (std::bad_alloc &) 341 { 342 return E_OUTOFMEMORY; 343 } 344 hrc = it->second->i_saveSettings(rData.IndividualConfigs[it->first]); 345 } 346 347 return hrc; 348 } 349 350 351 /** 352 * Internal worker that saves the settings after a modification was made. 353 * 354 * @returns COM status code. 355 * 356 * @note Caller must not hold any locks! 357 */ 358 HRESULT DHCPServer::i_doSaveSettings() 359 { 360 // save the global settings; for that we should hold only the VirtualBox lock 361 AutoWriteLock vboxLock(m->pVirtualBox COMMA_LOCKVAL_SRC_POS); 362 return m->pVirtualBox->i_saveSettings(); 236 363 } 237 364 … … 239 366 HRESULT DHCPServer::getNetworkName(com::Utf8Str &aName) 240 367 { 368 /* The name is const, so no need to for locking. */ 369 return aName.assignEx(m->strName); 370 } 371 372 373 HRESULT DHCPServer::getEnabled(BOOL *aEnabled) 374 { 241 375 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 242 243 aName = mName;244 return S_OK;245 }246 247 248 HRESULT DHCPServer::getEnabled(BOOL *aEnabled)249 {250 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);251 252 376 *aEnabled = m->enabled; 253 377 return S_OK; … … 257 381 HRESULT DHCPServer::setEnabled(BOOL aEnabled) 258 382 { 259 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 260 m->enabled = aEnabled; 261 262 // save the global settings; for that we should hold only the VirtualBox lock 263 alock.release(); 264 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS); 265 HRESULT rc = mVirtualBox->i_saveSettings(); 266 267 return rc; 383 { 384 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 385 m->enabled = aEnabled; 386 } 387 return i_doSaveSettings(); 268 388 } 269 389 … … 272 392 { 273 393 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 274 275 aIPAddress = Utf8Str(m->IPAddress); 276 return S_OK; 394 return aIPAddress.assignEx(m->IPAddress); 277 395 } 278 396 … … 280 398 HRESULT DHCPServer::getNetworkMask(com::Utf8Str &aNetworkMask) 281 399 { 400 return m->globalConfig->i_getNetworkMask(aNetworkMask); 401 } 402 403 404 HRESULT DHCPServer::getLowerIP(com::Utf8Str &aIPAddress) 405 { 282 406 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 283 284 aNetworkMask = m->GlobalDhcpOptions[DhcpOpt_SubnetMask].text; 285 return S_OK; 286 } 287 288 289 HRESULT DHCPServer::getLowerIP(com::Utf8Str &aIPAddress) 407 return aIPAddress.assignEx(m->lowerIP); 408 } 409 410 411 HRESULT DHCPServer::getUpperIP(com::Utf8Str &aIPAddress) 290 412 { 291 413 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 292 293 aIPAddress = Utf8Str(m->lowerIP); 294 return S_OK; 295 } 296 297 298 HRESULT DHCPServer::getUpperIP(com::Utf8Str &aIPAddress) 299 { 300 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 301 302 aIPAddress = Utf8Str(m->upperIP); 303 return S_OK; 414 return aIPAddress.assignEx(m->upperIP); 304 415 } 305 416 … … 314 425 int vrc = RTNetStrToIPv4Addr(aIPAddress.c_str(), &IPAddress); 315 426 if (RT_FAILURE(vrc)) 316 return mVirtualBox->setErrorBoth(E_INVALIDARG, vrc, "Invalid server address");427 return setErrorBoth(E_INVALIDARG, vrc, tr("Invalid server address: %s"), aIPAddress.c_str()); 317 428 318 429 vrc = RTNetStrToIPv4Addr(aNetworkMask.c_str(), &NetworkMask); 319 430 if (RT_FAILURE(vrc)) 320 return mVirtualBox->setErrorBoth(E_INVALIDARG, vrc, "Invalid netmask");431 return setErrorBoth(E_INVALIDARG, vrc, tr("Invalid netmask: %s"), aNetworkMask.c_str()); 321 432 322 433 vrc = RTNetStrToIPv4Addr(aLowerIP.c_str(), &LowerIP); 323 434 if (RT_FAILURE(vrc)) 324 return mVirtualBox->setErrorBoth(E_INVALIDARG, vrc, "Invalid range lower address");435 return setErrorBoth(E_INVALIDARG, vrc, tr("Invalid range lower address: %s"), aLowerIP.c_str()); 325 436 326 437 vrc = RTNetStrToIPv4Addr(aUpperIP.c_str(), &UpperIP); 327 438 if (RT_FAILURE(vrc)) 328 return mVirtualBox->setErrorBoth(E_INVALIDARG, vrc, "Invalid range upper address");439 return setErrorBoth(E_INVALIDARG, vrc, tr("Invalid range upper address: %s"), aUpperIP.c_str()); 329 440 330 441 /* … … 334 445 vrc = RTNetMaskToPrefixIPv4(&NetworkMask, NULL); 335 446 if (RT_FAILURE(vrc)) 336 return mVirtualBox->setErrorBoth(E_INVALIDARG, vrc, "Invalid netmask");337 338 /* It's more convenient to convert to host order once */339 IPAddress.u = RT_N2H_U32(IPAddress.u);447 return setErrorBoth(E_INVALIDARG, vrc, tr("Invalid netmask: %s"), aNetworkMask.c_str()); 448 449 /* It's more convenient to convert to host order once: */ 450 IPAddress.u = RT_N2H_U32(IPAddress.u); 340 451 NetworkMask.u = RT_N2H_U32(NetworkMask.u); 341 LowerIP.u = RT_N2H_U32(LowerIP.u);342 UpperIP.u = RT_N2H_U32(UpperIP.u);452 LowerIP.u = RT_N2H_U32(LowerIP.u); 453 UpperIP.u = RT_N2H_U32(UpperIP.u); 343 454 344 455 /* … … 348 459 || (IPAddress.u & ~NetworkMask.u) == 0 349 460 || ((IPAddress.u & ~NetworkMask.u) | NetworkMask.u) == UINT32_C(0xffffffff)) 350 return mVirtualBox->setError(E_INVALIDARG, "Invalid server address");461 return setError(E_INVALIDARG, tr("Invalid server address: %s (mask %s)"), aIPAddress.c_str(), aNetworkMask.c_str()); 351 462 352 463 if ( (LowerIP.u & UINT32_C(0xe0000000)) == UINT32_C(0xe0000000) … … 354 465 || (LowerIP.u & ~NetworkMask.u) == 0 355 466 || ((LowerIP.u & ~NetworkMask.u) | NetworkMask.u) == UINT32_C(0xffffffff)) 356 return mVirtualBox->setError(E_INVALIDARG, "Invalid range lower address");467 return setError(E_INVALIDARG, tr("Invalid range lower address: %s (mask %s)"), aLowerIP.c_str(), aNetworkMask.c_str()); 357 468 358 469 if ( (UpperIP.u & UINT32_C(0xe0000000)) == UINT32_C(0xe0000000) … … 360 471 || (UpperIP.u & ~NetworkMask.u) == 0 361 472 || ((UpperIP.u & ~NetworkMask.u) | NetworkMask.u) == UINT32_C(0xffffffff)) 362 return mVirtualBox->setError(E_INVALIDARG, "Invalid range upper address");473 return setError(E_INVALIDARG, tr("Invalid range upper address"), aUpperIP.c_str(), aNetworkMask.c_str()); 363 474 364 475 /* The range should be valid ... */ 365 476 if (LowerIP.u > UpperIP.u) 366 return mVirtualBox->setError(E_INVALIDARG, "Invalid range bounds"); 477 return setError(E_INVALIDARG, tr("Lower bound must be less or eqaul than the upper: %s vs %s"), 478 aLowerIP.c_str(), aUpperIP.c_str()); 367 479 368 480 /* ... and shouldn't contain the server's address */ 369 481 if (LowerIP.u <= IPAddress.u && IPAddress.u <= UpperIP.u) 370 return mVirtualBox->setError(E_INVALIDARG, "Server address within range bounds"); 371 372 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 373 m->IPAddress = aIPAddress; 374 m->GlobalDhcpOptions[DhcpOpt_SubnetMask] = aNetworkMask; 375 376 m->lowerIP = aLowerIP; 377 m->upperIP = aUpperIP; 378 379 // save the global settings; for that we should hold only the VirtualBox lock 380 alock.release(); 381 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS); 382 return mVirtualBox->i_saveSettings(); 383 } 384 385 386 HRESULT DHCPServer::encodeOption(com::Utf8Str &aEncoded, 387 uint32_t aOptCode, 388 const settings::DhcpOptValue &aOptValue) 389 { 390 switch (aOptValue.encoding) 391 { 392 case DhcpOptEncoding_Legacy: 482 return setError(E_INVALIDARG, tr("Server address within range bounds: %s in %s - %s"), 483 aIPAddress.c_str(), aLowerIP.c_str(), aUpperIP.c_str()); 484 485 /* 486 * Input is valid, effect the changes. 487 */ 488 HRESULT hrc; 489 { 490 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 491 m->IPAddress = aIPAddress; 492 m->lowerIP = aLowerIP; 493 m->upperIP = aUpperIP; 494 hrc = m->globalConfig->i_setNetworkMask(aNetworkMask); 495 } 496 if (SUCCEEDED(hrc)) 497 hrc = i_doSaveSettings(); 498 return hrc; 499 } 500 501 502 /** 503 * Used by the legacy 6.0 IDHCPServer::GetVmSlotOptions() and 504 * IDHCPServer::GetGlobalOptions() implementations. 505 * 506 * New interfaces have the option number and option encoding separate from the 507 * value. 508 */ 509 HRESULT DHCPServer::i_encode60Option(com::Utf8Str &strEncoded, DhcpOpt_T enmOption, 510 DHCPOptionEncoding_T enmEncoding, const com::Utf8Str &strValue) 511 { 512 int vrc; 513 switch (enmEncoding) 514 { 515 case DHCPOptionEncoding_Legacy: 393 516 { 394 517 /* … … 400 523 * "6:1.2.3.4 8.8.8.8" # array of ip-address 401 524 */ 402 aEncoded = Utf8StrFmt("%d:%s", aOptCode, aOptValue.text.c_str());525 vrc = strEncoded.printfNoThrow("%d:%s", (int)enmOption, strValue.c_str()); 403 526 break; 404 527 } 405 528 406 case D hcpOptEncoding_Hex:529 case DHCPOptionEncoding_Hex: 407 530 { 408 531 /* … … 413 536 * 234=68:65:6c:6c:6f:2c:20:77:6f:72:6c:64 414 537 */ 415 aEncoded = Utf8StrFmt("%d=%s", aOptCode, aOptValue.text.c_str());538 vrc = strEncoded.printfNoThrow("%d=%s", (int)enmOption, strValue.c_str()); 416 539 break; 417 540 } … … 424 547 * "254@42=i hope you know what this means" 425 548 */ 426 aEncoded = Utf8StrFmt("%d@%d=%s", aOptCode, (int)aOptValue.encoding, 427 aOptValue.text.c_str()); 549 vrc = strEncoded.printfNoThrow("%d@%d=%s", (int)enmOption, (int)enmEncoding, strValue.c_str()); 428 550 break; 429 551 } 430 552 } 431 432 return S_OK; 433 } 434 435 436 int DHCPServer::addOption(settings::DhcpOptionMap &aMap, 437 DhcpOpt_T aOption, const com::Utf8Str &aValue) 438 { 439 settings::DhcpOptValue OptValue; 440 553 return RT_SUCCESS(vrc) ? S_OK : E_OUTOFMEMORY; 554 } 555 556 557 /** 558 * worker for IDHCPServer::GetGlobalOptions. 559 */ 560 HRESULT DHCPServer::i_getAllOptions60(DHCPConfig &aSourceConfig, std::vector<com::Utf8Str> &aValues) 561 { 562 /* Get the values using the new getter: */ 563 std::vector<DhcpOpt_T> Options; 564 std::vector<DHCPOptionEncoding_T> Encodings; 565 std::vector<com::Utf8Str> Values; 566 HRESULT hrc = aSourceConfig.i_getAllOptions(Options, Encodings, Values); 567 if (SUCCEEDED(hrc)) 568 { 569 /* Encoding them using in the 6.0 style: */ 570 size_t const cValues = Values.size(); 571 aValues.resize(cValues); 572 for (size_t i = 0; i < cValues && SUCCEEDED(hrc); i++) 573 hrc = i_encode60Option(aValues[i], Options[i], Encodings[i], Values[i]); 574 } 575 return hrc; 576 } 577 578 579 /** 580 * Worker for legacy <=6.0 interfaces for adding options. 581 * 582 * @throws std::bad_alloc 583 */ 584 HRESULT DHCPServer::i_add60Option(DHCPConfig &aTargetConfig, DhcpOpt_T aOption, const com::Utf8Str &aValue) 585 { 441 586 if (aOption != 0) 442 { 443 OptValue = settings::DhcpOptValue(aValue, DhcpOptEncoding_Legacy); 444 } 587 return aTargetConfig.i_setOption(aOption, DHCPOptionEncoding_Legacy, aValue); 588 445 589 /* 446 590 * This is a kludge to sneak in option encoding information 447 591 * through existing API. We use option 0 and supply the real 448 * option/value in the same format that encodeOption() above592 * option/value in the same format that i_encode60Option() above 449 593 * produces for getter methods. 450 594 */ 451 else 452 { 453 uint8_t u8Code; 454 char *pszNext; 455 int vrc = RTStrToUInt8Ex(aValue.c_str(), &pszNext, 10, &u8Code); 456 if (!RT_SUCCESS(vrc)) 595 uint8_t u8Code; 596 char *pszNext; 597 int vrc = RTStrToUInt8Ex(aValue.c_str(), &pszNext, 10, &u8Code); 598 if (RT_FAILURE(vrc)) 599 return setErrorBoth(E_INVALIDARG, VERR_PARSE_ERROR); 600 601 DHCPOptionEncoding_T enmEncoding; 602 switch (*pszNext) 603 { 604 case ':': /* support legacy format too */ 605 { 606 enmEncoding = DHCPOptionEncoding_Legacy; 607 break; 608 } 609 610 case '=': 611 { 612 enmEncoding = DHCPOptionEncoding_Hex; 613 break; 614 } 615 616 case '@': 617 { 618 uint32_t u32Enc = 0; 619 vrc = RTStrToUInt32Ex(pszNext + 1, &pszNext, 10, &u32Enc); 620 if (RT_FAILURE(vrc)) 621 return setErrorBoth(E_INVALIDARG, VERR_PARSE_ERROR); 622 if (*pszNext != '=') 623 return setErrorBoth(E_INVALIDARG, VERR_PARSE_ERROR); 624 enmEncoding = (DHCPOptionEncoding_T)u32Enc; 625 break; 626 } 627 628 default: 457 629 return VERR_PARSE_ERROR; 458 459 uint32_t u32Enc; 460 switch (*pszNext) 461 { 462 case ':': /* support legacy format too */ 630 } 631 632 return aTargetConfig.i_setOption(aOption, enmEncoding, com::Utf8Str(pszNext + 1)); 633 } 634 635 636 HRESULT DHCPServer::addGlobalOption(DhcpOpt_T aOption, const com::Utf8Str &aValue) 637 { 638 return i_add60Option(*m->globalConfig, aOption, aValue); 639 } 640 641 642 HRESULT DHCPServer::removeGlobalOption(DhcpOpt_T aOption) 643 { 644 return m->globalConfig->i_removeOption(aOption); 645 } 646 647 648 HRESULT DHCPServer::removeGlobalOptions() 649 { 650 return m->globalConfig->i_removeAllOptions(); 651 } 652 653 654 HRESULT DHCPServer::getGlobalOptions(std::vector<com::Utf8Str> &aValues) 655 { 656 return i_getAllOptions60(*m->globalConfig, aValues); 657 } 658 659 660 HRESULT DHCPServer::getVmConfigs(std::vector<com::Utf8Str> &aValues) 661 { 662 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 663 664 try 665 { 666 aValues.resize(m->individualConfigs.size()); 667 size_t i = 0; 668 for (Data::IndividualConfigIterator it = m->individualConfigs.begin(); it != m->individualConfigs.end(); ++it, i++) 669 if (it->second->i_getScope() != DHCPConfigScope_MAC) 670 aValues[i].printf("[%RTuuid]:%d", it->second->i_getMachineId().raw(), it->second->i_getSlot()); 671 else 672 aValues[i].printf("[%RTmac]", it->second->i_getMACAddress()); 673 } 674 catch (std::bad_alloc &) 675 { 676 return E_OUTOFMEMORY; 677 } 678 679 return S_OK; 680 } 681 682 683 HRESULT DHCPServer::i_vmNameToIdAndValidateSlot(const com::Utf8Str &aVmName, LONG aSlot, com::Guid &idMachine) 684 { 685 if ((ULONG)aSlot <= 32) 686 { 687 /* Is it a UUID? */ 688 idMachine = aVmName; 689 if (idMachine.isValid() && !idMachine.isZero()) 690 return S_OK; 691 692 /* No, find the VM and get it's UUID. */ 693 ComObjPtr<Machine> ptrMachine; 694 HRESULT hrc = m->pVirtualBox->i_findMachine(aVmName, false /*fPermitInaccessible*/, true /*aSetError*/, &ptrMachine); 695 if (SUCCEEDED(hrc)) 696 idMachine = ptrMachine->i_getId(); 697 return hrc; 698 } 699 return setError(E_INVALIDARG, tr("NIC slot number (%d) is out of range (0..32)"), aSlot); 700 } 701 702 703 /** 704 * Translates a VM name/id and slot to an individual configuration object. 705 * 706 * @returns COM status code. 707 * @param a_strVmName The VM name or ID. 708 * @param a_uSlot The NIC slot. 709 * @param a_fCreateIfNeeded Whether to create a new entry if not found. 710 * @param a_rPtrConfig Where to return the config object. It's 711 * implicitly referenced, so we don't be returning 712 * with any locks held. 713 * 714 * @note Caller must not be holding any locks! 715 */ 716 HRESULT DHCPServer::i_vmNameAndSlotToConfig(const com::Utf8Str &a_strVmName, LONG a_uSlot, bool a_fCreateIfNeeded, 717 ComObjPtr<DHCPIndividualConfig> &a_rPtrConfig) 718 { 719 /* 720 * Validate the slot and normalize the name into a UUID. 721 */ 722 com::Guid idMachine; 723 HRESULT hrc = i_vmNameToIdAndValidateSlot(a_strVmName, a_uSlot, idMachine); 724 if (SUCCEEDED(hrc)) 725 { 726 Utf8Str strKey; 727 int vrc = strKey.printfNoThrow("%RTuuid/%u", idMachine.raw(), a_uSlot); 728 if (RT_SUCCESS(vrc)) 729 { 730 /* 731 * Look it up. 732 */ 463 733 { 464 u32Enc = DhcpOptEncoding_Legacy; 465 break; 734 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 735 Data::IndividualConfigIterator it = m->individualConfigs.find(strKey); 736 if (it != m->individualConfigs.end()) 737 { 738 a_rPtrConfig = it->second; 739 return S_OK; 740 } 466 741 } 467 468 case '=': 742 if (a_fCreateIfNeeded) 469 743 { 470 u32Enc = DhcpOptEncoding_Hex; 471 break; 744 /* 745 * Create a new slot. 746 */ 747 /* Instantiate the object: */ 748 hrc = a_rPtrConfig.createObject(); 749 if (SUCCEEDED(hrc)) 750 hrc = a_rPtrConfig->initWithMachineIdAndSlot(m->pVirtualBox, this, idMachine, a_uSlot, 751 m->uIndividualMACAddressVersion - UINT32_MAX / 4); 752 if (SUCCEEDED(hrc)) 753 { 754 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 755 756 /* Check for creation race: */ 757 Data::IndividualConfigIterator it = m->individualConfigs.find(strKey); 758 if (it != m->individualConfigs.end()) 759 { 760 a_rPtrConfig.setNull(); 761 a_rPtrConfig = it->second; 762 return S_OK; 763 } 764 765 /* Add it. */ 766 try 767 { 768 m->individualConfigs[strKey] = a_rPtrConfig; 769 return S_OK; 770 } 771 catch (std::bad_alloc &) 772 { 773 hrc = E_OUTOFMEMORY; 774 } 775 a_rPtrConfig.setNull(); 776 } 472 777 } 473 474 case '@': 475 { 476 vrc = RTStrToUInt32Ex(pszNext + 1, &pszNext, 10, &u32Enc); 477 if (!RT_SUCCESS(vrc)) 478 return VERR_PARSE_ERROR; 479 if (*pszNext != '=') 480 return VERR_PARSE_ERROR; 481 break; 482 } 483 484 default: 485 return VERR_PARSE_ERROR; 486 } 487 488 aOption = (DhcpOpt_T)u8Code; 489 OptValue = settings::DhcpOptValue(pszNext + 1, (DhcpOptEncoding_T)u32Enc); 490 } 491 492 aMap[aOption] = OptValue; 493 return VINF_SUCCESS; 494 } 495 496 497 HRESULT DHCPServer::addGlobalOption(DhcpOpt_T aOption, const com::Utf8Str &aValue) 498 { 499 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 500 501 int rc = addOption(m->GlobalDhcpOptions, aOption, aValue); 502 if (!RT_SUCCESS(rc)) 503 return E_INVALIDARG; 504 505 /* Indirect way to understand that we're on NAT network */ 506 if (aOption == DhcpOpt_Router) 507 { 508 m->router = true; 509 } 510 511 alock.release(); 512 513 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS); 514 return mVirtualBox->i_saveSettings(); 515 } 516 517 518 HRESULT DHCPServer::removeGlobalOption(DhcpOpt_T aOption) 519 { 520 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 521 522 settings::DhcpOptionMap::size_type cErased = m->GlobalDhcpOptions.erase(aOption); 523 if (!cErased) 524 return E_INVALIDARG; 525 526 alock.release(); 527 528 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS); 529 return mVirtualBox->i_saveSettings(); 530 } 531 532 533 HRESULT DHCPServer::removeGlobalOptions() 534 { 535 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 536 m->GlobalDhcpOptions.clear(); 537 538 alock.release(); 539 540 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS); 541 return mVirtualBox->i_saveSettings(); 542 } 543 544 545 HRESULT DHCPServer::getGlobalOptions(std::vector<com::Utf8Str> &aValues) 546 { 547 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 548 aValues.resize(m->GlobalDhcpOptions.size()); 549 settings::DhcpOptionMap::const_iterator it; 550 size_t i = 0; 551 for (it = m->GlobalDhcpOptions.begin(); it != m->GlobalDhcpOptions.end(); ++it, ++i) 552 { 553 uint32_t OptCode = (*it).first; 554 const settings::DhcpOptValue &OptValue = (*it).second; 555 556 encodeOption(aValues[i], OptCode, OptValue); 557 } 558 559 return S_OK; 560 } 561 562 HRESULT DHCPServer::getVmConfigs(std::vector<com::Utf8Str> &aValues) 563 { 564 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 565 aValues.resize(m->VmSlot2Options.size()); 566 settings::VmSlot2OptionsMap::const_iterator it; 567 size_t i = 0; 568 for (it = m->VmSlot2Options.begin(); it != m->VmSlot2Options.end(); ++it, ++i) 569 { 570 aValues[i] = Utf8StrFmt("[%s]:%d", it->first.VmName.c_str(), it->first.Slot); 571 } 572 573 return S_OK; 574 } 575 576 577 HRESULT DHCPServer::addVmSlotOption(const com::Utf8Str &aVmName, 578 LONG aSlot, 579 DhcpOpt_T aOption, 580 const com::Utf8Str &aValue) 581 { 582 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 583 584 settings::DhcpOptionMap &map = m->VmSlot2Options[settings::VmNameSlotKey(aVmName, aSlot)]; 585 int rc = addOption(map, aOption, aValue); 586 if (!RT_SUCCESS(rc)) 587 return E_INVALIDARG; 588 589 alock.release(); 590 591 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS); 592 return mVirtualBox->i_saveSettings(); 778 else 779 hrc = VBOX_E_OBJECT_NOT_FOUND; 780 } 781 else 782 hrc = E_OUTOFMEMORY; 783 } 784 return hrc; 785 } 786 787 788 HRESULT DHCPServer::addVmSlotOption(const com::Utf8Str &aVmName, LONG aSlot, DhcpOpt_T aOption, const com::Utf8Str &aValue) 789 { 790 ComObjPtr<DHCPIndividualConfig> ptrConfig; 791 HRESULT hrc = i_vmNameAndSlotToConfig(aVmName, aSlot, true, ptrConfig); 792 if (SUCCEEDED(hrc)) 793 hrc = i_add60Option(*ptrConfig, aOption, aValue); 794 return hrc; 593 795 } 594 796 … … 596 798 HRESULT DHCPServer::removeVmSlotOption(const com::Utf8Str &aVmName, LONG aSlot, DhcpOpt_T aOption) 597 799 { 598 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 599 settings::DhcpOptionMap &map = i_findOptMapByVmNameSlot(aVmName, aSlot); 600 settings::DhcpOptionMap::size_type cErased = map.erase(aOption); 601 if (!cErased) 602 return E_INVALIDARG; 603 604 alock.release(); 605 606 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS); 607 return mVirtualBox->i_saveSettings(); 800 ComObjPtr<DHCPIndividualConfig> ptrConfig; 801 HRESULT hrc = i_vmNameAndSlotToConfig(aVmName, aSlot, false, ptrConfig); 802 if (SUCCEEDED(hrc)) 803 hrc = ptrConfig->i_removeOption(aOption); 804 return hrc; 608 805 } 609 806 … … 611 808 HRESULT DHCPServer::removeVmSlotOptions(const com::Utf8Str &aVmName, LONG aSlot) 612 809 { 613 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 614 settings::DhcpOptionMap &map = i_findOptMapByVmNameSlot(aVmName, aSlot); 615 map.clear(); 616 617 alock.release(); 618 619 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS); 620 return mVirtualBox->i_saveSettings(); 621 } 622 623 /** 624 * this is mapping (vm, slot) 625 */ 626 HRESULT DHCPServer::getVmSlotOptions(const com::Utf8Str &aVmName, 627 LONG aSlot, 628 std::vector<com::Utf8Str> &aValues) 629 { 630 631 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 632 settings::DhcpOptionMap &map = i_findOptMapByVmNameSlot(aVmName, aSlot); 633 aValues.resize(map.size()); 634 size_t i = 0; 635 settings::DhcpOptionMap::const_iterator it; 636 for (it = map.begin(); it != map.end(); ++it, ++i) 637 { 638 uint32_t OptCode = (*it).first; 639 const settings::DhcpOptValue &OptValue = (*it).second; 640 641 encodeOption(aValues[i], OptCode, OptValue); 642 } 643 644 return S_OK; 810 ComObjPtr<DHCPIndividualConfig> ptrConfig; 811 HRESULT hrc = i_vmNameAndSlotToConfig(aVmName, aSlot, false, ptrConfig); 812 if (SUCCEEDED(hrc)) 813 hrc = ptrConfig->i_removeAllOptions(); 814 return hrc; 815 } 816 817 818 HRESULT DHCPServer::getVmSlotOptions(const com::Utf8Str &aVmName, LONG aSlot, std::vector<com::Utf8Str> &aValues) 819 { 820 ComObjPtr<DHCPIndividualConfig> ptrConfig; 821 HRESULT hrc = i_vmNameAndSlotToConfig(aVmName, aSlot, false, ptrConfig); 822 if (SUCCEEDED(hrc)) 823 hrc = i_getAllOptions60(*ptrConfig, aValues); 824 else if (hrc == VBOX_E_OBJECT_NOT_FOUND) 825 { 826 aValues.resize(0); 827 hrc = S_OK; 828 } 829 return hrc; 645 830 } 646 831 … … 648 833 HRESULT DHCPServer::getMacOptions(const com::Utf8Str &aMAC, std::vector<com::Utf8Str> &aOption) 649 834 { 650 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 651 HRESULT hrc = S_OK; 652 ComPtr<IMachine> machine; 653 ComPtr<INetworkAdapter> nic; 654 settings::VmSlot2OptionsIterator it; 655 for(it = m->VmSlot2Options.begin(); it != m->VmSlot2Options.end(); ++it) 656 { 657 alock.release(); 658 hrc = mVirtualBox->FindMachine(Bstr(it->first.VmName).raw(), machine.asOutParam()); 659 alock.acquire(); 660 661 if (FAILED(hrc)) 662 continue; 663 664 alock.release(); 665 hrc = machine->GetNetworkAdapter(it->first.Slot, nic.asOutParam()); 666 alock.acquire(); 667 668 if (FAILED(hrc)) 669 continue; 670 671 com::Bstr mac; 672 673 alock.release(); 674 hrc = nic->COMGETTER(MACAddress)(mac.asOutParam()); 675 alock.acquire(); 676 677 if (FAILED(hrc)) /* no MAC address ??? */ 678 break; 679 if (!RTStrICmp(com::Utf8Str(mac).c_str(), aMAC.c_str())) 680 return getVmSlotOptions(it->first.VmName, 681 it->first.Slot, 682 aOption); 683 } /* end of for */ 684 685 return hrc; 686 } 835 RT_NOREF(aMAC, aOption); 836 AssertFailed(); 837 return setError(E_NOTIMPL, tr("The GetMacOptions method has been discontinued as it was only supposed to be used by the DHCP server and it does not need it any more. sorry")); 838 } 839 687 840 688 841 HRESULT DHCPServer::getEventSource(ComPtr<IEventSource> &aEventSource) … … 693 846 694 847 695 DECLINLINE(void) addOptionChild(xml::ElementNode *pParent, uint32_t OptCode, const settings::DhcpOptValue &OptValue) 696 { 697 xml::ElementNode *pOption = pParent->createChild("Option"); 698 pOption->setAttribute("name", OptCode); 699 pOption->setAttribute("encoding", OptValue.encoding); 700 pOption->setAttribute("value", OptValue.text.c_str()); 848 HRESULT DHCPServer::getGlobalConfig(ComPtr<IDHCPGlobalConfig> &aGlobalConfig) 849 { 850 /* The global configuration is immutable, so no need to lock anything here. */ 851 return m->globalConfig.queryInterfaceTo(aGlobalConfig.asOutParam()); 852 } 853 854 855 HRESULT DHCPServer::getGroupConfigs(std::vector<ComPtr<IDHCPGroupConfig> > &aGroupConfigs) 856 { 857 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 858 #if 0 /** @todo implement group configs */ 859 860 try 861 { 862 aGroupConfigs.resize(m->groupConfigs.size()); 863 } 864 catch (std::bad_alloc &) 865 { 866 return E_OUTOFMEMORY; 867 } 868 869 size_t i = 0; 870 for (Data::GroupConfigIterator it = m->groupConfigs.begin(); it != m->groupConfigs.end(); ++it) 871 { 872 HRESULT hrc = it->second.queryInterfaceTo(aGroupConfigs[i].asOutParam()); 873 if (FAILED(hrc)) 874 return hrc; 875 } 876 877 #else 878 aGroupConfigs.resize(0); 879 #endif 880 return S_OK; 881 } 882 883 884 HRESULT DHCPServer::getIndividualConfigs(std::vector<ComPtr<IDHCPIndividualConfig> > &aIndividualConfigs) 885 { 886 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 887 888 try 889 { 890 aIndividualConfigs.resize(m->individualConfigs.size()); 891 } 892 catch (std::bad_alloc &) 893 { 894 return E_OUTOFMEMORY; 895 } 896 897 size_t i = 0; 898 for (Data::IndividualConfigIterator it = m->individualConfigs.begin(); it != m->individualConfigs.end(); ++it) 899 { 900 HRESULT hrc = it->second.queryInterfaceTo(aIndividualConfigs[i].asOutParam()); 901 if (FAILED(hrc)) 902 return hrc; 903 } 904 905 return S_OK; 701 906 } 702 907 … … 718 923 719 924 720 HRESULT DHCPServer::start(const com::Utf8Str &aNetworkName, 721 const com::Utf8Str &aTrunkName, 722 const com::Utf8Str &aTrunkType) 723 { 925 /** 926 * @throws std::bad_alloc 927 */ 928 HRESULT DHCPServer::i_writeDhcpdConfig(const char *pszFilename, uint32_t uMACAddressVersion) 929 { 930 /* 931 * Produce the DHCP server configuration. 932 */ 933 xml::Document doc; 934 try 935 { 936 xml::ElementNode *pElmRoot = doc.createRootElement("DHCPServer"); 937 pElmRoot->setAttribute("networkName", m->networkName); 938 if (m->trunkName.isNotEmpty()) 939 pElmRoot->setAttribute("trunkName", m->trunkName); 940 pElmRoot->setAttribute("trunkType", m->trunkType); 941 pElmRoot->setAttribute("IPAddress", m->IPAddress); 942 pElmRoot->setAttribute("lowerIP", m->lowerIP); 943 pElmRoot->setAttribute("upperIP", m->upperIP); 944 pElmRoot->setAttribute("leasesFilename", m->strLeasesFilename); 945 Utf8Str strNetworkMask; 946 HRESULT hrc = m->globalConfig->i_getNetworkMask(strNetworkMask); 947 if (FAILED(hrc)) 948 return hrc; 949 pElmRoot->setAttribute("networkMask", strNetworkMask); 950 951 /* 952 * Process global options 953 */ 954 m->globalConfig->i_writeDhcpdConfig(pElmRoot->createChild("Options")); 955 956 /* 957 * Groups. 958 */ 959 //for (Data::GroupConfigIterator it = m->groupConfigs.begin(); it != m->groupConfigs.end(); ++it) 960 // it->second->i_writeDhcpdConfig(pElmRoot->createChild("Config")); 961 962 /* 963 * Individual NIC configurations. 964 */ 965 for (Data::IndividualConfigIterator it = m->individualConfigs.begin(); it != m->individualConfigs.end(); ++it) 966 if (it->second->i_isMACAddressResolved(uMACAddressVersion)) 967 it->second->i_writeDhcpdConfig(pElmRoot->createChild("Config")); 968 else 969 LogRelFunc(("Skipping %RTuuid/%u, no MAC address.\n", it->second->i_getMachineId().raw(), it->second->i_getSlot())); 970 } 971 catch (std::bad_alloc &) 972 { 973 return E_OUTOFMEMORY; 974 } 975 976 /* 977 * Write out the document. 978 */ 979 try 980 { 981 xml::XmlFileWriter writer(doc); 982 writer.write(pszFilename, false); 983 } 984 catch (...) 985 { 986 return E_FAIL; 987 } 988 989 return S_OK; 990 } 991 992 993 /** @todo r=bird: why do we get the network name passed in here? it's the same 994 * as m->strName, isn't it? */ 995 HRESULT DHCPServer::start(const com::Utf8Str &aNetworkName, const com::Utf8Str &aTrunkName, const com::Utf8Str &aTrunkType) 996 { 997 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 998 724 999 /* Silently ignore attempts to run disabled servers. */ 725 1000 if (!m->enabled) 726 1001 return S_OK; 727 1002 728 /** 729 * @todo: the existing code cannot handle concurrent attempts to start DHCP server. 730 * Note that technically it may receive different parameters from different callers. 1003 /* 1004 * Resolve the MAC addresses. This requires us to leave the lock. 1005 */ 1006 uint32_t uMACAddressVersion = m->uIndividualMACAddressVersion; 1007 if (m->individualConfigs.size() > 0) 1008 { 1009 m->uIndividualMACAddressVersion = uMACAddressVersion + 1; 1010 1011 /* Retain pointers to all the individual configuration objects so we 1012 can safely access these after releaseing the lock: */ 1013 std::vector< ComObjPtr<DHCPIndividualConfig> > vecIndividualConfigs; 1014 try 1015 { 1016 vecIndividualConfigs.resize(m->individualConfigs.size()); 1017 } 1018 catch (std::bad_alloc &) 1019 { 1020 return E_OUTOFMEMORY; 1021 } 1022 size_t i = 0; 1023 for (Data::IndividualConfigIterator it = m->individualConfigs.begin(); it != m->individualConfigs.end(); ++it, i++) 1024 vecIndividualConfigs[i] = it->second; 1025 1026 /* Drop the lock and resolve the MAC addresses: */ 1027 alock.release(); 1028 1029 i = vecIndividualConfigs.size(); 1030 while (i-- > 0) 1031 vecIndividualConfigs[i]->i_resolveMACAddress(uMACAddressVersion); 1032 1033 /* Reacquire the lock */ 1034 alock.acquire(); 1035 if (!m->enabled) 1036 return S_OK; 1037 } 1038 1039 /* 1040 * Refuse to start a 2nd DHCP server instance for the same network. 1041 */ 1042 if (m->dhcp.isRunning()) 1043 return setErrorBoth(VBOX_E_OBJECT_IN_USE, VERR_PROCESS_RUNNING, 1044 tr("Cannot start DHCP server because it is already running")); 1045 1046 /* 1047 * Copy the startup parameters. 731 1048 */ 732 1049 m->networkName = aNetworkName; … … 734 1051 m->trunkType = aTrunkType; 735 1052 HRESULT hrc = i_calcLeasesFilename(aNetworkName); 736 if (FAILED(hrc)) 737 return hrc; 738 739 m->dhcp.resetArguments(); 740 741 #ifdef VBOX_WITH_DHCPD 742 743 /* 744 * Create configuration file path. 745 */ 746 /** @todo put this next to the leases file. */ 747 int rc = RTPathTemp(m->szTempConfigFileName, sizeof(m->szTempConfigFileName)); 748 if (RT_SUCCESS(rc)) 749 rc = RTPathAppend(m->szTempConfigFileName, sizeof(m->szTempConfigFileName), "dhcp-config-XXXXX.xml"); 750 if (RT_SUCCESS(rc)) 751 rc = RTFileCreateTemp(m->szTempConfigFileName, 0600); 752 if (RT_FAILURE(rc)) 753 { 1053 if (SUCCEEDED(hrc)) 1054 { 1055 /* 1056 * Create configuration file path and write out the configuration. 1057 */ 1058 /** @todo put this next to the leases file. */ 1059 int vrc = RTPathTemp(m->szTempConfigFileName, sizeof(m->szTempConfigFileName)); 1060 if (RT_SUCCESS(vrc)) 1061 vrc = RTPathAppend(m->szTempConfigFileName, sizeof(m->szTempConfigFileName), "dhcp-config-XXXXX.xml"); 1062 if (RT_SUCCESS(vrc)) 1063 vrc = RTFileCreateTemp(m->szTempConfigFileName, 0600); 1064 if (RT_SUCCESS(vrc)) 1065 { 1066 hrc = i_writeDhcpdConfig(m->szTempConfigFileName, uMACAddressVersion); 1067 if (SUCCEEDED(hrc)) 1068 { 1069 /* 1070 * Setup the arguments and start the DHCP server. 1071 */ 1072 m->dhcp.resetArguments(); 1073 vrc = m->dhcp.addArgPair(DHCPServerRunner::kDsrKeyConfig, m->szTempConfigFileName); 1074 if (RT_SUCCESS(vrc)) 1075 vrc = m->dhcp.addArgPair(DHCPServerRunner::kDsrKeyComment, m->networkName.c_str()); 1076 if (RT_SUCCESS(vrc)) 1077 vrc = m->dhcp.start(true /*aKillProcessOnStop*/); 1078 if (RT_FAILURE(vrc)) 1079 hrc = setErrorVrc(vrc, tr("Failed to start DHCP server for '%s': %Rrc"), m->strName.c_str(), vrc); 1080 } 1081 if (FAILED(hrc)) 1082 { 1083 RTFileDelete(m->szTempConfigFileName); 1084 m->szTempConfigFileName[0] = '\0'; 1085 } 1086 } 1087 else 1088 { 1089 m->szTempConfigFileName[0] = '\0'; 1090 hrc = setErrorVrc(vrc); 1091 } 1092 } 1093 return hrc; 1094 } 1095 1096 1097 HRESULT DHCPServer::stop(void) 1098 { 1099 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1100 1101 if (m->szTempConfigFileName[0]) 1102 { 1103 RTFileDelete(m->szTempConfigFileName); 754 1104 m->szTempConfigFileName[0] = '\0'; 755 return E_FAIL; 756 } 757 758 /* 759 * Produce the DHCP server configuration. 760 */ 761 xml::Document doc; 762 xml::ElementNode *pElmRoot = doc.createRootElement("DHCPServer"); 763 pElmRoot->setAttribute("networkName", m->networkName); 764 if (m->trunkName.isNotEmpty()) 765 pElmRoot->setAttribute("trunkName", m->trunkName); 766 pElmRoot->setAttribute("trunkType", m->trunkType); 767 pElmRoot->setAttribute("IPAddress", m->IPAddress); 768 pElmRoot->setAttribute("networkMask", m->GlobalDhcpOptions[DhcpOpt_SubnetMask].text); 769 pElmRoot->setAttribute("lowerIP", m->lowerIP); 770 pElmRoot->setAttribute("upperIP", m->upperIP); 771 pElmRoot->setAttribute("leasesFilename", m->strLeasesFilename); 772 773 /* Process global options */ 774 xml::ElementNode *pOptions = pElmRoot->createChild("Options"); 775 for (settings::DhcpOptionMap::const_iterator it = m->GlobalDhcpOptions.begin(); it != m->GlobalDhcpOptions.end(); ++it) 776 addOptionChild(pOptions, (*it).first, (*it).second); 777 778 /* Process network-adapter-specific options */ 779 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 780 hrc = S_OK; 781 ComPtr<IMachine> machine; 782 ComPtr<INetworkAdapter> nic; 783 settings::VmSlot2OptionsIterator it; 784 for (it = m->VmSlot2Options.begin(); it != m->VmSlot2Options.end(); ++it) 785 { 786 alock.release(); 787 hrc = mVirtualBox->FindMachine(Bstr(it->first.VmName).raw(), machine.asOutParam()); 788 alock.acquire(); 789 790 if (FAILED(hrc)) 791 continue; 792 793 alock.release(); 794 hrc = machine->GetNetworkAdapter(it->first.Slot, nic.asOutParam()); 795 alock.acquire(); 796 797 if (FAILED(hrc)) 798 continue; 799 800 com::Bstr mac; 801 802 alock.release(); 803 hrc = nic->COMGETTER(MACAddress)(mac.asOutParam()); 804 alock.acquire(); 805 806 if (FAILED(hrc)) /* no MAC address ??? */ 807 continue; 808 809 /* Convert MAC address from XXXXXXXXXXXX to XX:XX:XX:XX:XX:XX */ 810 Utf8Str strMacWithoutColons(mac); 811 const char *pszSrc = strMacWithoutColons.c_str(); 812 RTMAC binaryMac; 813 if (RTStrConvertHexBytes(pszSrc, &binaryMac, sizeof(binaryMac), 0) != VINF_SUCCESS) 814 continue; 815 char szMac[18]; /* "XX:XX:XX:XX:XX:XX" */ 816 if (RTStrPrintHexBytes(szMac, sizeof(szMac), &binaryMac, sizeof(binaryMac), RTSTRPRINTHEXBYTES_F_SEP_COLON) != VINF_SUCCESS) 817 continue; 818 819 xml::ElementNode *pMacConfig = pElmRoot->createChild("Config"); 820 pMacConfig->setAttribute("MACAddress", szMac); 821 822 com::Utf8Str encodedOption; 823 settings::DhcpOptionMap &map = i_findOptMapByVmNameSlot(it->first.VmName, it->first.Slot); 824 settings::DhcpOptionMap::const_iterator itAdapterOption; 825 for (itAdapterOption = map.begin(); itAdapterOption != map.end(); ++itAdapterOption) 826 addOptionChild(pMacConfig, (*itAdapterOption).first, (*itAdapterOption).second); 827 } 828 829 xml::XmlFileWriter writer(doc); 830 writer.write(m->szTempConfigFileName, false); 831 832 m->dhcp.addArgPair(DHCPServerRunner::kDsrKeyConfig, m->szTempConfigFileName); 833 m->dhcp.addArgPair(DHCPServerRunner::kDsrKeyComment, m->networkName.c_str()); 834 835 #else /* !VBOX_WITH_DHCPD */ 836 /* Main is needed for NATNetwork */ 837 if (m->router) 838 m->dhcp.addArgPair(NetworkServiceRunner::kpszKeyNeedMain, "on"); 839 840 /* Commmon Network Settings */ 841 m->dhcp.addArgPair(NetworkServiceRunner::kpszKeyNetwork, aNetworkName.c_str()); 842 if (!aTrunkName.isEmpty()) 843 m->dhcp.addArgPair(NetworkServiceRunner::kpszTrunkName, aTrunkName.c_str()); 844 m->dhcp.addArgPair(NetworkServiceRunner::kpszKeyTrunkType, aTrunkType.c_str()); 845 846 /* XXX: should this MAC default initialization moved to NetworkServiceRunner? */ 847 char strMAC[32]; 848 Guid guid; 849 guid.create(); 850 RTStrPrintf (strMAC, sizeof(strMAC), "08:00:27:%02X:%02X:%02X", 851 guid.raw()->au8[0], guid.raw()->au8[1], guid.raw()->au8[2]); 852 m->dhcp.addArgPair(NetworkServiceRunner::kpszMacAddress, strMAC); 853 m->dhcp.addArgPair(NetworkServiceRunner::kpszIpAddress, m->IPAddress.c_str()); 854 m->dhcp.addArgPair(NetworkServiceRunner::kpszIpNetmask, m->GlobalDhcpOptions[DhcpOpt_SubnetMask].text.c_str()); 855 m->dhcp.addArgPair(DHCPServerRunner::kDsrKeyLowerIp, m->lowerIP.c_str()); 856 m->dhcp.addArgPair(DHCPServerRunner::kDsrKeyUpperIp, m->upperIP.c_str()); 857 #endif /* !VBOX_WITH_DHCPD */ 858 859 /* XXX: This parameters Dhcp Server will fetch via API */ 860 return RT_FAILURE(m->dhcp.start(!m->router /* KillProcOnExit */)) ? E_FAIL : S_OK; 861 //m->dhcp.detachFromServer(); /* need to do this to avoid server shutdown on runner destruction */ 862 } 863 864 865 HRESULT DHCPServer::stop(void) 866 { 867 #ifdef VBOX_WITH_DHCPD 868 if (m->szTempConfigFileName[0]) 869 { 870 RTFileDelete(m->szTempConfigFileName); 871 m->szTempConfigFileName[0] = 0; 872 } 873 #endif /* VBOX_WITH_DHCPD */ 874 return RT_FAILURE(m->dhcp.stop()) ? E_FAIL : S_OK; 1105 } 1106 1107 int vrc = m->dhcp.stop(); 1108 if (RT_SUCCESS(vrc)) 1109 return S_OK; 1110 return setErrorVrc(vrc); 875 1111 } 876 1112 … … 901 1137 if (m->strLeasesFilename.isEmpty()) 902 1138 { 903 HRESULT hrc = i_calcLeasesFilename(m->networkName.isEmpty() ? m Name : m->networkName);1139 HRESULT hrc = i_calcLeasesFilename(m->networkName.isEmpty() ? m->strName : m->networkName); 904 1140 if (FAILED(hrc)) 905 1141 return hrc; … … 1020 1256 1021 1257 1258 HRESULT DHCPServer::getConfig(DHCPConfigScope_T aScope, const com::Utf8Str &aName, ULONG aSlot, BOOL aMayAdd, 1259 ComPtr<IDHCPConfig> &aConfig) 1260 { 1261 if (aSlot != 0 && aScope != DHCPConfigScope_MachineNIC) 1262 return setError(E_INVALIDARG, tr("The 'slot' argument must be zero for all but the MachineNIC scope!")); 1263 1264 switch (aScope) 1265 { 1266 case DHCPConfigScope_Global: 1267 if (aName.isNotEmpty()) 1268 return setError(E_INVALIDARG, tr("The name must be empty or NULL for the Global scope!")); 1269 /* No locking required here. */ 1270 return m->globalConfig.queryInterfaceTo(aConfig.asOutParam()); 1271 1272 case DHCPConfigScope_Group: 1273 return setError(E_NOTIMPL, tr("Groups are not yet implemented, sorry.")); 1274 1275 case DHCPConfigScope_MachineNIC: 1276 { 1277 ComObjPtr<DHCPIndividualConfig> ptrIndividualConfig; 1278 HRESULT hrc = i_vmNameAndSlotToConfig(aName, aSlot, aMayAdd != FALSE, ptrIndividualConfig); 1279 if (SUCCEEDED(hrc)) 1280 hrc = ptrIndividualConfig.queryInterfaceTo(aConfig.asOutParam()); 1281 return hrc; 1282 } 1283 1284 case DHCPConfigScope_MAC: 1285 { 1286 /* Check and Normalize the MAC address into a key: */ 1287 RTMAC MACAddress; 1288 int vrc = RTNetStrToMacAddr(aName.c_str(), &MACAddress); 1289 if (RT_SUCCESS(vrc)) 1290 { 1291 Utf8Str strKey; 1292 vrc = strKey.printfNoThrow("%RTmac", &MACAddress); 1293 if (RT_SUCCESS(vrc)) 1294 { 1295 /* Look up the MAC address: */ 1296 { 1297 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 1298 Data::IndividualConfigIterator it = m->individualConfigs.find(strKey); 1299 if (it != m->individualConfigs.end()) 1300 return it->second.queryInterfaceTo(aConfig.asOutParam()); 1301 } 1302 if (aMayAdd) 1303 { 1304 /* Create a new individiual configuration: */ 1305 ComObjPtr<DHCPIndividualConfig> ptrIndividualConfig; 1306 HRESULT hrc = ptrIndividualConfig.createObject(); 1307 if (SUCCEEDED(hrc)) 1308 hrc = ptrIndividualConfig->initWithMACAddress(m->pVirtualBox, this, &MACAddress); 1309 if (SUCCEEDED(hrc)) 1310 { 1311 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1312 1313 /* Check for insertion race: */ 1314 Data::IndividualConfigIterator it = m->individualConfigs.find(strKey); 1315 if (it != m->individualConfigs.end()) 1316 return it->second.queryInterfaceTo(aConfig.asOutParam()); /* creation race*/ 1317 1318 /* Try insert it: */ 1319 try 1320 { 1321 m->individualConfigs[strKey] = ptrIndividualConfig; 1322 } 1323 catch (std::bad_alloc &) 1324 { 1325 return E_OUTOFMEMORY; 1326 } 1327 return ptrIndividualConfig.queryInterfaceTo(aConfig.asOutParam()); 1328 } 1329 } 1330 else 1331 return setError(VBOX_E_OBJECT_NOT_FOUND, tr("Found no configuration for MAC address %s"), strKey.c_str()); 1332 } 1333 return E_OUTOFMEMORY; 1334 } 1335 return setErrorBoth(E_INVALIDARG, vrc, tr("Invalid MAC address: %s"), aName.c_str()); 1336 } 1337 1338 default: 1339 return E_FAIL; 1340 } 1341 } 1342 1343 1022 1344 /** 1023 1345 * Calculates and updates the value of strLeasesFilename given @a aNetwork. … … 1028 1350 1029 1351 /* The lease file must be the same as we used the last time, so careful when changing this code. */ 1030 int vrc = m->strLeasesFilename.assignNoThrow(m VirtualBox->i_homeDir());1352 int vrc = m->strLeasesFilename.assignNoThrow(m->pVirtualBox->i_homeDir()); 1031 1353 if (RT_SUCCESS(vrc)) 1032 1354 vrc = RTPathAppendCxx(m->strLeasesFilename, aNetwork); … … 1042 1364 } 1043 1365 1044 settings::DhcpOptionMap &DHCPServer::i_findOptMapByVmNameSlot(const com::Utf8Str &aVmName,1045 LONG aSlot)1046 {1047 return m->VmSlot2Options[settings::VmNameSlotKey(aVmName, aSlot)];1048 }1049 -
trunk/src/VBox/Main/xml/Settings.cpp
r78632 r79732 1614 1614 * Constructor. Needs to set sane defaults which stand the test of time. 1615 1615 */ 1616 DhcpOptValue::DhcpOptValue() :1617 text(),1618 encoding(DhcpOptEncoding_Legacy)1616 DhcpOptValue::DhcpOptValue() 1617 : strValue() 1618 , enmEncoding(DHCPOptionEncoding_Legacy) 1619 1619 { 1620 1620 } … … 1623 1623 * Non-standard constructor. 1624 1624 */ 1625 DhcpOptValue::DhcpOptValue(const com::Utf8Str &aText, DhcpOptEncoding_T aEncoding) : 1626 text(aText), 1627 encoding(aEncoding) 1628 { 1629 } 1630 1631 /** 1632 * Non-standard constructor. 1633 */ 1634 VmNameSlotKey::VmNameSlotKey(const com::Utf8Str& aVmName, LONG aSlot) : 1635 VmName(aVmName), 1636 Slot(aSlot) 1637 { 1638 } 1639 1640 /** 1641 * Non-standard comparison operator. 1642 */ 1643 bool VmNameSlotKey::operator< (const VmNameSlotKey& that) const 1644 { 1645 if (VmName == that.VmName) 1646 return Slot < that.Slot; 1647 else 1648 return VmName < that.VmName; 1625 DhcpOptValue::DhcpOptValue(const com::Utf8Str &aText, DHCPOptionEncoding_T aEncoding) 1626 : strValue(aText) 1627 , enmEncoding(aEncoding) 1628 { 1629 } 1630 1631 1632 /** 1633 * Default constructor. 1634 */ 1635 DHCPConfig::DHCPConfig() 1636 : OptionMap() 1637 , secMinLeaseTime(0) 1638 , secDefaultLeaseTime(0) 1639 , secMaxLeaseTime(0) 1640 { 1641 } 1642 1643 /** 1644 * Default constructor. 1645 */ 1646 DHCPIndividualConfig::DHCPIndividualConfig() 1647 : DHCPConfig() 1648 , strMACAddress() 1649 , strVMName() 1650 , uSlot(0) 1651 { 1649 1652 } 1650 1653 … … 1652 1655 * Constructor. Needs to set sane defaults which stand the test of time. 1653 1656 */ 1654 DHCPServer::DHCPServer() :1655 fEnabled(false)1657 DHCPServer::DHCPServer() 1658 : fEnabled(false) 1656 1659 { 1657 1660 } … … 1705 1708 1706 1709 /** 1710 * Builds the XML tree for the DHCP servers. 1711 */ 1712 void MainConfigFile::buildDHCPServers(xml::ElementNode &elmDHCPServers, DHCPServersList const &ll) 1713 { 1714 for (DHCPServersList::const_iterator it = ll.begin(); it != ll.end(); ++it) 1715 { 1716 const DHCPServer &srv = *it; 1717 xml::ElementNode *pElmThis = elmDHCPServers.createChild("DHCPServer"); 1718 1719 pElmThis->setAttribute("networkName", srv.strNetworkName); 1720 pElmThis->setAttribute("IPAddress", srv.strIPAddress); 1721 DhcpOptConstIterator itOpt = srv.GlobalConfig.OptionMap.find(DhcpOpt_SubnetMask); 1722 if (itOpt != srv.GlobalConfig.OptionMap.end()) 1723 pElmThis->setAttribute("networkMask", itOpt->second.strValue); 1724 pElmThis->setAttribute("lowerIP", srv.strIPLower); 1725 pElmThis->setAttribute("upperIP", srv.strIPUpper); 1726 pElmThis->setAttribute("enabled", (srv.fEnabled) ? 1 : 0); // too bad we chose 1 vs. 0 here 1727 1728 /* We don't want duplicate validation check of networkMask here*/ 1729 if (srv.GlobalConfig.OptionMap.size() > (itOpt != srv.GlobalConfig.OptionMap.end() ? 1 : 0)) 1730 { 1731 xml::ElementNode *pElmOptions = pElmThis->createChild("Options"); 1732 buildDHCPOptions(*pElmOptions, srv.GlobalConfig, true); 1733 } 1734 1735 if (srv.IndividualConfigs.size() > 0) 1736 { 1737 for (DHCPIndividualConfigMap::const_iterator itHost = srv.IndividualConfigs.begin(); 1738 itHost != srv.IndividualConfigs.end(); ++itHost) 1739 { 1740 DHCPIndividualConfig const &rIndividualConfig = itHost->second; 1741 1742 xml::ElementNode *pElmConfig = pElmThis->createChild("Config"); 1743 if (rIndividualConfig.strMACAddress.isNotEmpty()) 1744 pElmConfig->setAttribute("MACAddress", rIndividualConfig.strMACAddress); 1745 if (rIndividualConfig.strVMName.isNotEmpty()) 1746 pElmConfig->setAttribute("vm-name", rIndividualConfig.strVMName); 1747 if (rIndividualConfig.uSlot != 0 || rIndividualConfig.strVMName.isNotEmpty()) 1748 pElmConfig->setAttribute("slot", rIndividualConfig.strVMName); 1749 if (rIndividualConfig.strFixedAddress.isNotEmpty()) 1750 pElmConfig->setAttribute("fixedAddress", rIndividualConfig.strFixedAddress); 1751 buildDHCPOptions(*pElmConfig, rIndividualConfig, false); 1752 } 1753 } 1754 } 1755 } 1756 1757 /** 1758 * Worker for buildDHCPServers() that builds Options or Config element trees. 1759 */ 1760 void MainConfigFile::buildDHCPOptions(xml::ElementNode &elmOptions, DHCPConfig const &rConfig, bool fSkipSubnetMask) 1761 { 1762 /* Generic (and optional) attributes on the Options or Config element: */ 1763 if (rConfig.secMinLeaseTime > 0) 1764 elmOptions.setAttribute("secMinLeaseTime", rConfig.secMinLeaseTime); 1765 if (rConfig.secDefaultLeaseTime > 0) 1766 elmOptions.setAttribute("secDefaultLeaseTime", rConfig.secDefaultLeaseTime); 1767 if (rConfig.secMaxLeaseTime > 0) 1768 elmOptions.setAttribute("secMaxLeaseTime", rConfig.secMaxLeaseTime); 1769 1770 /* The DHCP options are <Option> child elements: */ 1771 for (DhcpOptConstIterator it = rConfig.OptionMap.begin(); it != rConfig.OptionMap.end(); ++it) 1772 if (it->first != DhcpOpt_SubnetMask || !fSkipSubnetMask) 1773 { 1774 xml::ElementNode *pElmOption = elmOptions.createChild("Option"); 1775 pElmOption->setAttribute("name", it->first); 1776 pElmOption->setAttribute("value", it->second.strValue); 1777 if (it->second.enmEncoding != DHCPOptionEncoding_Legacy) 1778 pElmOption->setAttribute("encoding", (int32_t)it->second.enmEncoding); 1779 } 1780 } 1781 1782 /** 1707 1783 * Reads in the \<DHCPServers\> chunk. 1708 1784 * @param elmDHCPServers … … 1719 1795 if ( pelmServer->getAttributeValue("networkName", srv.strNetworkName) 1720 1796 && pelmServer->getAttributeValue("IPAddress", srv.strIPAddress) 1721 && pelmServer->getAttributeValue("networkMask", srv.Global DhcpOptions[DhcpOpt_SubnetMask].text)1797 && pelmServer->getAttributeValue("networkMask", srv.GlobalConfig.OptionMap[DhcpOpt_SubnetMask].strValue) 1722 1798 && pelmServer->getAttributeValue("lowerIP", srv.strIPLower) 1723 1799 && pelmServer->getAttributeValue("upperIP", srv.strIPUpper) 1724 1800 && pelmServer->getAttributeValue("enabled", srv.fEnabled) ) 1725 1801 { 1726 xml::NodesLoop nlOptions(*pelmServer, "Options"); 1727 const xml::ElementNode *options; 1728 /* XXX: Options are in 1:1 relation to DHCPServer */ 1729 1730 while ((options = nlOptions.forAllNodes())) 1802 /* Global options: */ 1803 const xml::ElementNode *pElmOptions; 1804 xml::NodesLoop nlOptions(*pelmServer, "Options"); 1805 while ((pElmOptions = nlOptions.forAllNodes()) != NULL) /** @todo this loop makes no sense, there can only be one <Options> child. */ 1806 readDHCPOptions(srv.GlobalConfig, *pElmOptions, true /*fIgnoreSubnetMask*/); 1807 1808 /* host specific configuration: */ 1809 xml::NodesLoop nlConfig(*pelmServer, "Config"); 1810 const xml::ElementNode *pElmConfig; 1811 while ((pElmConfig = nlConfig.forAllNodes()) != NULL) 1731 1812 { 1732 readDhcpOptions(srv.GlobalDhcpOptions, *options); 1733 } /* end of forall("Options") */ 1734 xml::NodesLoop nlConfig(*pelmServer, "Config"); 1735 const xml::ElementNode *cfg; 1736 while ((cfg = nlConfig.forAllNodes())) 1737 { 1738 com::Utf8Str strVmName; 1739 uint32_t u32Slot; 1740 cfg->getAttributeValue("vm-name", strVmName); 1741 cfg->getAttributeValue("slot", u32Slot); 1742 readDhcpOptions(srv.VmSlot2OptionsM[VmNameSlotKey(strVmName, u32Slot)], *cfg); 1813 com::Utf8Str strMACAddress; 1814 if (!pElmConfig->getAttributeValue("MACAddress", strMACAddress)) 1815 strMACAddress.setNull(); 1816 1817 com::Utf8Str strVMName; 1818 if (!pElmConfig->getAttributeValue("vm-name", strVMName)) 1819 strVMName.setNull(); 1820 1821 uint32_t uSlot; 1822 if (!pElmConfig->getAttributeValue("slot", uSlot)) 1823 uSlot = 0; 1824 1825 com::Utf8Str strKey; 1826 if (strVMName.isNotEmpty()) 1827 strKey.printf("%s/%u", strVMName.c_str(), uSlot); 1828 else 1829 strKey.printf("%s/%u", strMACAddress.c_str(), uSlot); 1830 1831 DHCPIndividualConfig &rIndividualConfig = srv.IndividualConfigs[strKey]; 1832 rIndividualConfig.strMACAddress = strMACAddress; 1833 rIndividualConfig.strVMName = strVMName; 1834 rIndividualConfig.uSlot = uSlot; 1835 pElmConfig->getAttributeValue("fixedAddress", rIndividualConfig.strFixedAddress); 1836 1837 readDHCPOptions(rIndividualConfig, *pElmConfig, false /*fIgnoreSubnetMask*/); 1743 1838 } 1744 1839 llDhcpServers.push_back(srv); … … 1750 1845 } 1751 1846 1752 void MainConfigFile::readDhcpOptions(DhcpOptionMap& map, 1753 const xml::ElementNode& options) 1754 { 1755 xml::NodesLoop nl2(options, "Option"); 1756 const xml::ElementNode *opt; 1757 while ((opt = nl2.forAllNodes())) 1847 /** 1848 * Worker for readDHCPServers that reads a configuration, either global, 1849 * group or host (VM+NIC) specific. 1850 */ 1851 void MainConfigFile::readDHCPOptions(DHCPConfig &rConfig, const xml::ElementNode &elmConfig, bool fIgnoreSubnetMask) 1852 { 1853 /* Generic (and optional) attributes on the Options or Config element: */ 1854 if (!elmConfig.getAttributeValue("secMinLeaseTime", rConfig.secMinLeaseTime)) 1855 rConfig.secMinLeaseTime = 0; 1856 if (!elmConfig.getAttributeValue("secDefaultLeaseTime", rConfig.secDefaultLeaseTime)) 1857 rConfig.secDefaultLeaseTime = 0; 1858 if (!elmConfig.getAttributeValue("secMaxLeaseTime", rConfig.secMaxLeaseTime)) 1859 rConfig.secMaxLeaseTime = 0; 1860 1861 /* The DHCP options are <Option> child elements: */ 1862 xml::NodesLoop nl2(elmConfig, "Option"); 1863 const xml::ElementNode *pElmOption; 1864 while ((pElmOption = nl2.forAllNodes()) != NULL) 1758 1865 { 1759 1866 DhcpOpt_T OptName; 1760 com::Utf8Str OptText; 1761 int32_t OptEnc = DhcpOptEncoding_Legacy; 1762 1763 opt->getAttributeValue("name", (uint32_t&)OptName); 1764 1765 if (OptName == DhcpOpt_SubnetMask) 1867 pElmOption->getAttributeValue("name", (uint32_t&)OptName); 1868 if (OptName == DhcpOpt_SubnetMask && fIgnoreSubnetMask) 1766 1869 continue; 1767 1870 1768 opt->getAttributeValue("value", OptText); 1769 opt->getAttributeValue("encoding", OptEnc); 1770 1771 map[OptName] = DhcpOptValue(OptText, (DhcpOptEncoding_T)OptEnc); 1871 com::Utf8Str strValue; 1872 pElmOption->getAttributeValue("value", strValue); 1873 1874 int32_t iOptEnc; 1875 if (!pElmOption->getAttributeValue("encoding", iOptEnc)) 1876 iOptEnc = DHCPOptionEncoding_Legacy; 1877 1878 rConfig.OptionMap[OptName] = DhcpOptValue(strValue, (DHCPOptionEncoding_T)iOptEnc); 1772 1879 } /* end of forall("Option") */ 1773 1880 … … 2074 2181 { 2075 2182 DHCPServer srv; 2076 srv.strNetworkName =2077 2183 #ifdef RT_OS_WINDOWS 2078 2184 srv.strNetworkName = "HostInterfaceNetworking-VirtualBox Host-Only Ethernet Adapter"; 2079 2185 #else 2080 2186 srv.strNetworkName = "HostInterfaceNetworking-vboxnet0"; 2081 2187 #endif 2082 2188 srv.strIPAddress = "192.168.56.100"; 2083 srv.Global DhcpOptions[DhcpOpt_SubnetMask] = DhcpOptValue("255.255.255.0");2189 srv.GlobalConfig.OptionMap[DhcpOpt_SubnetMask] = DhcpOptValue("255.255.255.0"); 2084 2190 srv.strIPLower = "192.168.56.101"; 2085 2191 srv.strIPUpper = "192.168.56.254"; … … 2137 2243 buildMediaRegistry(*pelmGlobal, mediaRegistry); 2138 2244 2139 xml::ElementNode *pelmNetserviceRegistry = pelmGlobal->createChild("NetserviceRegistry"); 2140 xml::ElementNode *pelmDHCPServers = pelmNetserviceRegistry->createChild("DHCPServers"); 2141 for (DHCPServersList::const_iterator it = llDhcpServers.begin(); 2142 it != llDhcpServers.end(); 2143 ++it) 2144 { 2145 const DHCPServer &d = *it; 2146 xml::ElementNode *pelmThis = pelmDHCPServers->createChild("DHCPServer"); 2147 DhcpOptConstIterator itOpt; 2148 itOpt = d.GlobalDhcpOptions.find(DhcpOpt_SubnetMask); 2149 2150 pelmThis->setAttribute("networkName", d.strNetworkName); 2151 pelmThis->setAttribute("IPAddress", d.strIPAddress); 2152 if (itOpt != d.GlobalDhcpOptions.end()) 2153 pelmThis->setAttribute("networkMask", itOpt->second.text); 2154 pelmThis->setAttribute("lowerIP", d.strIPLower); 2155 pelmThis->setAttribute("upperIP", d.strIPUpper); 2156 pelmThis->setAttribute("enabled", (d.fEnabled) ? 1 : 0); // too bad we chose 1 vs. 0 here 2157 /* We assume that if there're only 1 element it means that */ 2158 size_t cOpt = d.GlobalDhcpOptions.size(); 2159 /* We don't want duplicate validation check of networkMask here*/ 2160 if ( ( itOpt == d.GlobalDhcpOptions.end() 2161 && cOpt > 0) 2162 || cOpt > 1) 2163 { 2164 xml::ElementNode *pelmOptions = pelmThis->createChild("Options"); 2165 for (itOpt = d.GlobalDhcpOptions.begin(); 2166 itOpt != d.GlobalDhcpOptions.end(); 2167 ++itOpt) 2168 { 2169 if (itOpt->first == DhcpOpt_SubnetMask) 2170 continue; 2171 2172 xml::ElementNode *pelmOpt = pelmOptions->createChild("Option"); 2173 2174 if (!pelmOpt) 2175 break; 2176 2177 pelmOpt->setAttribute("name", itOpt->first); 2178 pelmOpt->setAttribute("value", itOpt->second.text); 2179 if (itOpt->second.encoding != DhcpOptEncoding_Legacy) 2180 pelmOpt->setAttribute("encoding", (int)itOpt->second.encoding); 2181 } 2182 } /* end of if */ 2183 2184 if (d.VmSlot2OptionsM.size() > 0) 2185 { 2186 VmSlot2OptionsConstIterator itVmSlot; 2187 DhcpOptConstIterator itOpt1; 2188 for(itVmSlot = d.VmSlot2OptionsM.begin(); 2189 itVmSlot != d.VmSlot2OptionsM.end(); 2190 ++itVmSlot) 2191 { 2192 xml::ElementNode *pelmCfg = pelmThis->createChild("Config"); 2193 pelmCfg->setAttribute("vm-name", itVmSlot->first.VmName); 2194 pelmCfg->setAttribute("slot", (int32_t)itVmSlot->first.Slot); 2195 2196 for (itOpt1 = itVmSlot->second.begin(); 2197 itOpt1 != itVmSlot->second.end(); 2198 ++itOpt1) 2199 { 2200 xml::ElementNode *pelmOpt = pelmCfg->createChild("Option"); 2201 pelmOpt->setAttribute("name", itOpt1->first); 2202 pelmOpt->setAttribute("value", itOpt1->second.text); 2203 if (itOpt1->second.encoding != DhcpOptEncoding_Legacy) 2204 pelmOpt->setAttribute("encoding", (int)itOpt1->second.encoding); 2205 } 2206 } 2207 } /* and of if */ 2208 2209 } 2245 xml::ElementNode *pelmNetServiceRegistry = pelmGlobal->createChild("NetserviceRegistry"); /** @todo r=bird: wrong capitalization of NetServiceRegistry. sigh. */ 2246 buildDHCPServers(*pelmNetServiceRegistry->createChild("DHCPServers"), llDhcpServers); 2210 2247 2211 2248 xml::ElementNode *pelmNATNetworks; … … 2213 2250 if (!llNATNetworks.empty()) 2214 2251 { 2215 pelmNATNetworks = pelmNet serviceRegistry->createChild("NATNetworks");2252 pelmNATNetworks = pelmNetServiceRegistry->createChild("NATNetworks"); 2216 2253 for (NATNetworksList::const_iterator it = llNATNetworks.begin(); 2217 2254 it != llNATNetworks.end();
Note:
See TracChangeset
for help on using the changeset viewer.