Changeset 46969 in vbox
- Timestamp:
- Jul 4, 2013 6:35:01 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 4 deleted
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/settings.h
r46959 r46969 286 286 typedef std::list<MachineRegistryEntry> MachinesRegistry; 287 287 288 typedef std::map<DhcpOpt_T, com::Utf8Str> DhcpOptionMap;289 typedef DhcpOptionMap::value_type DhcpOptValuePair;290 typedef DhcpOptionMap::iterator DhcpOptIterator;291 typedef DhcpOptionMap::const_iterator DhcpOptConstIterator;292 293 typedef struct VmNameSlotKey294 {295 VmNameSlotKey(const com::Utf8Str& aVmName, LONG aSlot): VmName(aVmName),296 Slot(aSlot){}297 const com::Utf8Str VmName;298 LONG Slot;299 bool operator< (const VmNameSlotKey& that) const300 {301 if (VmName == that.VmName)302 return Slot < that.Slot;303 else return VmName < that.VmName;304 }305 } VmNameSlotKey;306 typedef std::map<VmNameSlotKey, DhcpOptionMap> VmSlot2OptionsMap;307 typedef VmSlot2OptionsMap::value_type VmSlot2OptionsPair;308 typedef VmSlot2OptionsMap::iterator VmSlot2OptionsIterator;309 typedef VmSlot2OptionsMap::const_iterator VmSlot2OptionsConstIterator;310 311 288 struct DHCPServer 312 289 { … … 317 294 com::Utf8Str strNetworkName, 318 295 strIPAddress, 296 strIPNetworkMask, 319 297 strIPLower, 320 298 strIPUpper; 321 299 bool fEnabled; 322 std::map<DhcpOpt_T, com::Utf8Str> GlobalDhcpOptions;323 VmSlot2OptionsMap VmSlot2OptionsM;324 300 }; 325 301 typedef std::list<DHCPServer> DHCPServersList; … … 361 337 void readMachineRegistry(const xml::ElementNode &elmMachineRegistry); 362 338 void readDHCPServers(const xml::ElementNode &elmDHCPServers); 363 void readDhcpOptions(DhcpOptionMap& map, const xml::ElementNode& options);364 339 void readNATNetworks(const xml::ElementNode &elmNATNetworks); 365 340 -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp
r46967 r46969 40 40 #include "VBoxManage.h" 41 41 42 #include <string>43 #include <vector>44 #include <map>45 46 42 #ifndef VBOX_ONLY_DOCS 47 43 using namespace com; … … 53 49 OP_MODIFY 54 50 } OPCODE; 55 56 typedef std::map<DhcpOpt_T, std::string> DhcpOptMap;57 typedef DhcpOptMap::iterator DhcpOptIterator;58 typedef DhcpOptMap::value_type DhcpOptValuePair;59 60 struct VmNameSlotKey;61 typedef struct VmNameSlotKey VmNameSlotKey;62 63 struct VmNameSlotKey64 {65 std::string VmName;66 uint8_t u8Slot;67 68 VmNameSlotKey(std::string aVmName, uint8_t aSlot) :69 VmName(aVmName),70 u8Slot(aSlot) {}71 72 bool operator< (const VmNameSlotKey& that) const73 {74 if (VmName == that.VmName)75 return u8Slot < that.u8Slot;76 else77 return VmName < that.VmName;78 }79 };80 81 typedef std::map<VmNameSlotKey, DhcpOptMap> VmSlot2OptionsM;82 typedef VmSlot2OptionsM::iterator VmSlot2OptionsIterator;83 typedef VmSlot2OptionsM::value_type VmSlot2OptionsPair;84 85 typedef std::vector<VmNameSlotKey> VmConfigs;86 51 87 52 static const RTGETOPTDEF g_aDHCPIPOptions[] … … 107 72 { "-enable", 'e', RTGETOPT_REQ_NOTHING }, // deprecated 108 73 { "--disable", 'd', RTGETOPT_REQ_NOTHING }, 109 { "-disable", 'd', RTGETOPT_REQ_NOTHING }, // deprecated 110 { "--options", 'o', RTGETOPT_REQ_NOTHING }, 111 {"--vm", 'n', RTGETOPT_REQ_STRING}, /* only with -o */ 112 {"--slot", 's', RTGETOPT_REQ_UINT8}, /* only with -o and -n */ 113 {"--id", 'i', RTGETOPT_REQ_UINT8}, /* only with -o */ 114 {"--value", 'p', RTGETOPT_REQ_STRING} /* only with -i */ 115 74 { "-disable", 'd', RTGETOPT_REQ_NOTHING } // deprecated 116 75 }; 117 76 … … 123 82 int index = iStart; 124 83 HRESULT rc; 125 bool fOptionsRead = false; 126 bool fVmOptionRead = false; 127 128 const char *pszVmName = NULL; 84 129 85 const char *pNetName = NULL; 130 86 const char *pIfName = NULL; … … 133 89 const char * pLowerIp = NULL; 134 90 const char * pUpperIp = NULL; 135 136 uint8_t u8OptId = -1;137 uint8_t u8Slot = -1;138 139 91 int enable = -1; 140 141 DhcpOptMap GlobalDhcpOptions;142 VmSlot2OptionsM VmSlot2Options;143 VmConfigs VmConfigs2Delete;144 92 145 93 int c; … … 228 176 return errorSyntax(USAGE_DHCPSERVER, "unhandled parameter: %s", ValueUnion.psz); 229 177 break; 230 231 case 'o': // --options232 {233 // {"--vm", 'n', RTGETOPT_REQ_STRING}, /* only with -o */234 // {"--slot", 's', RTGETOPT_REQ_UINT8}, /* only with -o and -n*/235 // {"--id", 'i', RTGETOPT_REQ_UINT8}, /* only with -o */236 // {"--value", 'p', RTGETOPT_REQ_STRING} /* only with -i */237 if (fOptionsRead)238 return errorSyntax(USAGE_DHCPSERVER,239 "previos option edition wasn't finished");240 fOptionsRead = true;241 fVmOptionRead = false; /* we want specify new global or vm option*/242 u8Slot = (uint8_t)~0;243 u8OptId = (uint8_t)~0;244 pszVmName = NULL;245 } /* end of --options */246 break;247 248 case 'n': // --vm-name249 {250 if (fVmOptionRead)251 return errorSyntax(USAGE_DHCPSERVER,252 "previous vm option edition wasn't finished");253 else254 fVmOptionRead = true;255 u8Slot = (uint8_t)~0; /* clear slor */256 pszVmName = RTStrDup(ValueUnion.psz);257 }258 break; /* end of --vm-name */259 260 case 's': // --slot261 {262 if (!fVmOptionRead)263 return errorSyntax(USAGE_DHCPSERVER,264 "vm name wasn't specified");265 266 u8Slot = ValueUnion.u8;267 }268 break; /* end of --slot */269 270 case 'i': // --id271 {272 if (!fOptionsRead)273 return errorSyntax(USAGE_DHCPSERVER,274 "-o wasn't found");275 276 u8OptId = ValueUnion.u8;277 }278 break; /* end of --id */279 280 case 'p': // --value281 {282 if (!fOptionsRead)283 return errorSyntax(USAGE_DHCPSERVER,284 "-o wasn't found");285 286 if (u8OptId == (uint8_t)~0)287 return errorSyntax(USAGE_DHCPSERVER,288 "--id wasn't found");289 if ( fVmOptionRead290 && u8Slot == (uint8_t)~0)291 return errorSyntax(USAGE_DHCPSERVER,292 "--slot wasn't found");293 294 DhcpOptMap& map = (fVmOptionRead ?295 VmSlot2Options[296 VmNameSlotKey::VmNameSlotKey(pszVmName,297 u8Slot)]298 : GlobalDhcpOptions);299 std::string strVal = ValueUnion.psz;300 map.insert(DhcpOptValuePair((DhcpOpt_T)u8OptId, strVal));301 302 }303 break; // --end of value304 305 178 default: 306 179 if (c > 0) … … 323 196 return errorSyntax(USAGE_DHCPSERVER, "You need to specify either --netname or --ifname to identify the DHCP server"); 324 197 325 if( enmCode != OP_REMOVE 326 && GlobalDhcpOptions.size() == 0 327 && VmSlot2Options.size() == 0) 198 if(enmCode != OP_REMOVE) 328 199 { 329 200 if(enable < 0 || pIp || pNetmask || pLowerIp || pUpperIp) … … 383 254 if (pIp || pNetmask || pLowerIp || pUpperIp) 384 255 { 385 CHECK_ERROR(svr, SetConfiguration ( 386 Bstr(pIp).mutableRaw(), 387 Bstr(pNetmask).mutableRaw(), 388 Bstr(pLowerIp).mutableRaw(), 389 Bstr(pUpperIp).mutableRaw())); 256 CHECK_ERROR(svr, SetConfiguration (Bstr(pIp).mutableRaw(), Bstr(pNetmask).mutableRaw(), Bstr(pLowerIp).mutableRaw(), Bstr(pUpperIp).mutableRaw())); 390 257 if(FAILED(rc)) 391 258 return errorArgument("Failed to set configuration"); … … 395 262 { 396 263 CHECK_ERROR(svr, COMSETTER(Enabled) ((BOOL)enable)); 397 }398 399 /* option processing */400 DhcpOptIterator itOpt;401 VmSlot2OptionsIterator it;402 403 /* Global Options */404 for(itOpt = GlobalDhcpOptions.begin();405 itOpt != GlobalDhcpOptions.end();406 ++itOpt)407 {408 CHECK_ERROR(svr,409 AddGlobalOption(410 itOpt->first,411 com::Bstr(itOpt->second.c_str()).raw()));412 }413 414 /* heh, vm slot options. */415 416 for (it = VmSlot2Options.begin();417 it != VmSlot2Options.end();418 ++it)419 {420 for(itOpt = it->second.begin();421 itOpt != it->second.end();422 ++itOpt)423 {424 CHECK_ERROR(svr,425 AddVmSlotOption(Bstr(it->first.VmName.c_str()).raw(),426 it->first.u8Slot,427 itOpt->first,428 com::Bstr(itOpt->second.c_str()).raw()));429 }430 264 } 431 265 } -
trunk/src/VBox/Main/Makefile.kmk
r46959 r46969 335 335 src-server/BIOSSettingsImpl.cpp \ 336 336 src-server/DHCPServerImpl.cpp \ 337 src-server/ NetworkServiceRunner.cpp \337 src-server/DHCPServerRunner.cpp \ 338 338 src-server/NATNetworkImpl.cpp \ 339 $(if $(VBOX_WITH_NAT_SERVICE),src-server/NATNetworkServiceRunner.cpp,) \ 339 340 src-server/GuestOSTypeImpl.cpp \ 340 341 src-server/HostImpl.cpp \ -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r46959 r46969 1466 1466 </interface> 1467 1467 1468 <enum1469 name="DhcpOpt"1470 uuid="40d99bd3-3ece-44d2-a07e-1085fe9c4f0b">1471 <const name="SubnetMask" value="1"/>1472 <const name="TimeOffset" value="2"/>1473 <const name="Router" value="3"/>1474 <const name="TimeServer" value="4"/>1475 <const name="NameServer" value="5"/>1476 <const name="DomainNameServer" value="6"/>1477 <const name="LogServer" value="7"/>1478 <const name="Cookie" value="8"/>1479 <const name="LPRServer" value="9"/>1480 <const name="ImpressServer" value="10"/>1481 <const name="ResourseLocationServer" value="11"/>1482 <const name="HostName" value="12"/>1483 <const name="BootFileSize" value="13"/>1484 <const name="MeritDumpFile" value="14"/>1485 <const name="DomainName" value="15"/>1486 <const name="SwapServer" value="16"/>1487 <const name="RootPath" value="17"/>1488 <const name="ExtensionPath" value="18"/>1489 <const name="IPForwardingEnableDisable" value="19"/>1490 <const name="NonLocalSourceRoutingEnableDisable" value="20"/>1491 <const name="PolicyFilter" value="21"/>1492 <const name="MaximumDatagramReassemblySize" value="22"/>1493 <const name="DefaultIPTime2Live" value="23"/>1494 <const name="PathMTUAgingTimeout" value="24"/>1495 <const name="IPLayerParametersPerInterface" value="25"/>1496 <const name="InterfaceMTU" value="26"/>1497 <const name="AllSubnetsAreLocal" value="27"/>1498 <const name="BroadcastAddress" value="28"/>1499 <const name="PerformMaskDiscovery" value="29"/>1500 <const name="MaskSupplier" value="30"/>1501 <const name="PerformRouteDiscovery" value="31"/>1502 <const name="RouterSolicitationAddress" value="32"/>1503 <const name="StaticRoute" value="33"/>1504 <const name="TrailerEncapsulation" value="34"/>1505 <const name="ARPCacheTimeout" value="35"/>1506 <const name="EthernetEncapsulation" value="36"/>1507 <const name="TCPDefaultTTL" value="37"/>1508 <const name="TCPKeepAliveInterval" value="38"/>1509 <const name="TCPKeepAliveGarbage" value="39"/>1510 <const name="NetworkInformationServiceDomain" value="40"/>1511 <const name="NetworkInformationServiceServers" value="41"/>1512 <const name="NetworkTimeProtocolServers" value="42"/>1513 <const name="VendorSpecificInformation" value="43"/>1514 <const name="Option_44" value="44"/>1515 <const name="Option_45" value="45"/>1516 <const name="Option_46" value="46"/>1517 <const name="Option_47" value="47"/>1518 <const name="Option_48" value="48"/>1519 <const name="Option_49" value="49"/>1520 <const name="IPAddressLeaseTime" value="51"/>1521 <const name="Option_64" value="64"/>1522 <const name="Option_65" value="65"/>1523 <const name="TFTPServerName" value="66"/>1524 <const name="BootfileName" value="67"/>1525 <const name="Option_68" value="68"/>1526 <const name="Option_69" value="69"/>1527 <const name="Option_70" value="70"/>1528 <const name="Option_71" value="71"/>1529 <const name="Option_72" value="72"/>1530 <const name="Option_73" value="73"/>1531 <const name="Option_74" value="74"/>1532 <const name="Option_75" value="75"/>1533 <const name="Option_119" value="119"/>1534 </enum>1535 1536 1468 <interface 1537 1469 name="IDHCPServer" extends="$unknown" 1538 uuid=" ff0774c5-1f62-4bc3-919c-7fc942bf1d25"1470 uuid="6cfe387c-74fb-4ca7-bff6-973bec8af7a3" 1539 1471 wsmap="managed" 1540 1472 > … … 1545 1477 <link to="IVirtualBox::DHCPServers"/> attribute. 1546 1478 </desc> 1547 <!-- We want to keep our "real" servers updated about configuration changes --> 1548 <attribute name="eventSource" type="IEventSource" readonly="yes"/> 1479 1549 1480 <attribute name="enabled" type="boolean"> 1550 1481 <desc> … … 1582 1513 </desc> 1583 1514 </attribute> 1584 1585 <method name="addGlobalOption">1586 <param name="option" type="DhcpOpt" dir="in"/>1587 <param name="value" type="wstring" dir="in" />1588 </method>1589 1590 <!-- string in format: "option_id:value" -->1591 <attribute name="globalOptions" type="wstring" safearray="yes" readonly="yes"/>1592 1593 <!-- string in format: "[vm name]:slot" -->1594 <attribute name="vmConfigs" type="wstring" safearray="yes" readonly="yes"/>1595 1596 <!-- VM-slot settings1597 It's corresponds to dhcpd.conf entries, like:1598 1599 host ncd1 { hardware ethernet 0:c0:c3:11:90:23; }1600 1601 - in Main we can match (vm name, slot) to ethernet address1602 that why it's easy to configure dhcp server in such way,1603 then ask user to to enter valid name,1604 1605 - mac address might change because of adapter type (e1k <-> pcnet) or because1606 of import/export1607 1608 - it's easy to provide vm-name.rom in boot filename VM with network boot.1609 1610 XXX: do we need classic getOptionValueByMAC?1611 1612 XML: O-o-oh, this settings are per VM, so perhaps they should be stored in1613 VM configuration files. And we haven't got the attachment type for1614 NATNetwork.1615 -->1616 <method name="addVmSlotOption">1617 <param name="vmname" type="wstring" dir="in"/>1618 <param name="slot" type="long" dir="in"/>1619 <param name="option" type="DhcpOpt" dir="in"/>1620 <param name="value" type="wstring" dir="in" />1621 </method>1622 1623 <method name="removeVmSlotOptions">1624 <param name="vmname" type="wstring" dir="in"/>1625 <param name="slot" type="long" dir="in"/>1626 </method>1627 1628 <!-- returns array of strings in format: "option_id:value" for a given pair (vm, slot) -->1629 <method name="getVmSlotOptions">1630 <param name="vmname" type="wstring" dir="in"/>1631 <param name="slot" type="long" dir="in"/>1632 <param name="option" type="wstring" safearray="yes" dir="return"/>1633 </method>1634 1635 <!-- Returns options by MAC address -->1636 <method name="getMacOptions">1637 <param name="mac" type="wstring" dir="in"/>1638 <param name="option" type="wstring" safearray="yes" dir="return"/>1639 </method>1640 1515 1641 1516 <method name="setConfiguration"> … … 8163 8038 <interface 8164 8039 name="IHost" extends="$unknown" 8165 uuid=" a6107246-f939-42c4-82b6-8aca40327b6d"8040 uuid="30678943-32df-4830-b413-931b25ac86a0" 8166 8041 wsmap="managed" 8167 8042 > … … 8224 8099 <attribute name="networkInterfaces" type="IHostNetworkInterface" safearray="yes" readonly="yes"> 8225 8100 <desc>List of host network interfaces currently defined on the host.</desc> 8226 </attribute>8227 8228 <attribute name="nameServers" type="wstring" safearray="yes" readonly="yes">8229 <desc> The list of nameservers registered in host's name resolving system.</desc>8230 </attribute>8231 8232 <attribute name="domainName" type="wstring" readonly="yes">8233 <desc>Domain name used for name resoving.</desc>8234 </attribute>8235 8236 <attribute name="searchStrings" type="wstring" safearray="yes" readonly="yes">8237 <desc>Search string registered for name resoving.</desc>8238 8101 </attribute> 8239 8102 -
trunk/src/VBox/Main/include/DHCPServerImpl.h
r46959 r46969 30 30 { 31 31 struct DHCPServer; 32 struct VmNameSlotKey;33 32 } 34 #ifdef RT_OS_WINDOWS35 # define DHCP_EXECUTABLE_NAME "VBoxNetDHCP.exe"36 #else37 # define DHCP_EXECUTABLE_NAME "VBoxNetDHCP"38 #endif39 40 class DHCPServerRunner: public NetworkServiceRunner41 {42 public:43 DHCPServerRunner():NetworkServiceRunner(DHCP_EXECUTABLE_NAME){}44 virtual ~DHCPServerRunner(){};45 };46 47 /**48 * for server configuration needs, it's perhaps better to use (VM,slot) pair49 * (vm-name, slot) <----> (MAC)50 *51 * but for client configuration, when server will have MACs at hand, it'd be52 * easier to requiest options by MAC.53 * (MAC) <----> (option-list)54 *55 * Doubts: What should be done if MAC changed for (vm-name, slot), when syncing should?56 * XML: serialization of dependecy (DHCP options) - (VM,slot) shouldn't be done via MAC in57 * the middle.58 */59 60 typedef std::map<DhcpOpt_T, com::Utf8Str> DhcpOptionMap;61 typedef DhcpOptionMap::value_type DhcpOptValuePair;62 typedef DhcpOptionMap::const_iterator DhcpOptConstIterator;63 typedef DhcpOptionMap::iterator DhcpOptIterator;64 65 typedef std::map<settings::VmNameSlotKey, DhcpOptionMap> VmSlot2OptionsMap;66 typedef VmSlot2OptionsMap::value_type VmSlot2OptionsPair;67 typedef VmSlot2OptionsMap::iterator VmSlot2OptionsIterator;68 69 33 70 34 class ATL_NO_VTABLE DHCPServer : … … 106 70 STDMETHOD(COMGETTER(UpperIP))(BSTR *aIPAddress); 107 71 108 STDMETHOD(AddGlobalOption)(DhcpOpt_T aOption, IN_BSTR aValue);109 STDMETHOD(COMGETTER(GlobalOptions))(ComSafeArrayOut(BSTR, aValue));110 STDMETHOD(COMGETTER(VmConfigs))(ComSafeArrayOut(BSTR, aValue));111 STDMETHOD(AddVmSlotOption)(IN_BSTR aVmName, LONG aSlot, DhcpOpt_T aOption, IN_BSTR aValue);112 STDMETHOD(RemoveVmSlotOptions)(IN_BSTR aVmName, LONG aSlot);113 STDMETHOD(GetVmSlotOptions)(IN_BSTR aVmName, LONG aSlot, ComSafeArrayOut(BSTR, aValues));114 STDMETHOD(GetMacOptions)(IN_BSTR aMAC, ComSafeArrayOut(BSTR, aValues));115 STDMETHOD(COMGETTER(EventSource))(IEventSource **aEventSource);116 117 118 72 STDMETHOD(SetConfiguration)(IN_BSTR aIPAddress, IN_BSTR aNetworkMask, IN_BSTR aFromIPAddress, IN_BSTR aToIPAddress); 119 73 … … 132 86 133 87 Bstr IPAddress; 88 Bstr networkMask; 134 89 Bstr lowerIP; 135 90 Bstr upperIP; 91 BOOL enabled; 136 92 137 BOOL enabled;138 93 DHCPServerRunner dhcp; 139 140 DhcpOptionMap GlobalDhcpOptions;141 VmSlot2OptionsMap VmSlot2Options;142 94 } m; 143 144 DhcpOptionMap& findOptMapByVmNameSlot(const com::Utf8Str& aVmName, 145 LONG Slot); 95 146 96 }; 147 97 -
trunk/src/VBox/Main/include/HostImpl.h
r46959 r46969 62 62 STDMETHOD(COMGETTER(USBDeviceFilters))(ComSafeArrayOut(IHostUSBDeviceFilter *, aUSBDeviceFilters)); 63 63 STDMETHOD(COMGETTER(NetworkInterfaces))(ComSafeArrayOut(IHostNetworkInterface *, aNetworkInterfaces)); 64 STDMETHOD(COMGETTER(NameServers))(ComSafeArrayOut(BSTR, aNameServers));65 STDMETHOD(COMGETTER(DomainName))(BSTR *aDomainName);66 STDMETHOD(COMGETTER(SearchStrings))(ComSafeArrayOut(BSTR, aSearchStrings));67 68 64 STDMETHOD(COMGETTER(ProcessorCount))(ULONG *count); 69 65 STDMETHOD(COMGETTER(ProcessorOnlineCount))(ULONG *count); … … 151 147 HRESULT updateNetIfList(); 152 148 153 #ifndef RT_OS_WINDOWS154 HRESULT parseResolvConf();155 #else156 HRESULT fetchNameResolvingInformation();157 #endif158 159 149 #ifdef VBOX_WITH_RESOURCE_USAGE_API 160 150 void registerMetrics(PerformanceCollector *aCollector); -
trunk/src/VBox/Main/include/NATNetworkImpl.h
r46959 r46969 37 37 } 38 38 39 #ifdef RT_OS_WINDOWS40 # define NATSR_EXECUTABLE_NAME "VBoxNetLwipNAT.exe"41 #else42 # define NATSR_EXECUTABLE_NAME "VBoxNetLwipNAT"43 #endif44 45 class NATNetworkServiceRunner: public NetworkServiceRunner46 {47 public:48 NATNetworkServiceRunner(): NetworkServiceRunner(NATSR_EXECUTABLE_NAME){}49 virtual ~NATNetworkServiceRunner(){}50 };51 39 52 40 class ATL_NO_VTABLE NATNetwork : -
trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
r46959 r46969 115 115 #endif /* VBOX_WITH_NETFLT */ 116 116 117 #include " NetworkServiceRunner.h"117 #include "DHCPServerRunner.h" 118 118 #include "BusAssignmentManager.h" 119 119 #ifdef VBOX_WITH_EXTPACK -
trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp
r46961 r46969 18 18 */ 19 19 20 #include " NetworkServiceRunner.h"20 #include "DHCPServerRunner.h" 21 21 #include "DHCPServerImpl.h" 22 22 #include "AutoCaller.h" … … 25 25 #include <iprt/cpp/utils.h> 26 26 27 #include <VBox/com/array.h>28 27 #include <VBox/settings.h> 29 28 … … 38 37 } 39 38 40 41 39 DHCPServer::~DHCPServer() 42 40 { 43 41 } 44 42 45 46 43 HRESULT DHCPServer::FinalConstruct() 47 44 { … … 49 46 } 50 47 51 52 48 void DHCPServer::FinalRelease() 53 49 { … … 56 52 BaseFinalRelease(); 57 53 } 58 59 54 60 55 void DHCPServer::uninit() … … 68 63 } 69 64 70 71 65 HRESULT DHCPServer::init(VirtualBox *aVirtualBox, IN_BSTR aName) 72 66 { … … 81 75 unconst(mName) = aName; 82 76 m.IPAddress = "0.0.0.0"; 83 m. GlobalDhcpOptions.insert(DhcpOptValuePair(DhcpOpt_SubnetMask, Bstr("0.0.0.0")));77 m.networkMask = "0.0.0.0"; 84 78 m.enabled = FALSE; 85 86 79 m.lowerIP = "0.0.0.0"; 87 80 m.upperIP = "0.0.0.0"; … … 92 85 return S_OK; 93 86 } 94 95 87 96 88 HRESULT DHCPServer::init(VirtualBox *aVirtualBox, … … 106 98 unconst(mName) = data.strNetworkName; 107 99 m.IPAddress = data.strIPAddress; 100 m.networkMask = data.strIPNetworkMask; 108 101 m.enabled = data.fEnabled; 109 102 m.lowerIP = data.strIPLower; 110 103 m.upperIP = data.strIPUpper; 111 104 112 113 m.GlobalDhcpOptions.clear();114 m.GlobalDhcpOptions.insert(data.GlobalDhcpOptions.begin(),115 data.GlobalDhcpOptions.end());116 117 m.VmSlot2Options.clear();118 m.VmSlot2Options.insert(data.VmSlot2OptionsM.begin(),119 data.VmSlot2OptionsM.end());120 121 105 autoInitSpan.setSucceeded(); 122 106 123 107 return S_OK; 124 108 } 125 126 109 127 110 HRESULT DHCPServer::saveSettings(settings::DHCPServer &data) … … 134 117 data.strNetworkName = mName; 135 118 data.strIPAddress = m.IPAddress; 136 119 data.strIPNetworkMask = m.networkMask; 137 120 data.fEnabled = !!m.enabled; 138 121 data.strIPLower = m.lowerIP; 139 122 data.strIPUpper = m.upperIP; 140 123 141 data.GlobalDhcpOptions.clear(); 142 data.GlobalDhcpOptions.insert(m.GlobalDhcpOptions.begin(), 143 m.GlobalDhcpOptions.end()); 144 145 data.VmSlot2OptionsM.clear(); 146 data.VmSlot2OptionsM.insert(m.VmSlot2Options.begin(), 147 m.VmSlot2Options.end()); 148 149 return S_OK; 150 } 151 124 return S_OK; 125 } 152 126 153 127 STDMETHODIMP DHCPServer::COMGETTER(NetworkName) (BSTR *aName) … … 163 137 } 164 138 165 166 139 STDMETHODIMP DHCPServer::COMGETTER(Enabled) (BOOL *aEnabled) 167 140 { … … 175 148 return S_OK; 176 149 } 177 178 150 179 151 STDMETHODIMP DHCPServer::COMSETTER(Enabled) (BOOL aEnabled) … … 193 165 } 194 166 195 196 167 STDMETHODIMP DHCPServer::COMGETTER(IPAddress) (BSTR *aIPAddress) 197 168 { … … 206 177 } 207 178 208 209 179 STDMETHODIMP DHCPServer::COMGETTER(NetworkMask) (BSTR *aNetworkMask) 210 180 { … … 214 184 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 215 185 216 m.GlobalDhcpOptions[DhcpOpt_SubnetMask].cloneTo(aNetworkMask); 217 218 return S_OK; 219 } 220 186 m.networkMask.cloneTo(aNetworkMask); 187 188 return S_OK; 189 } 221 190 222 191 STDMETHODIMP DHCPServer::COMGETTER(LowerIP) (BSTR *aIPAddress) … … 226 195 AutoCaller autoCaller(this); 227 196 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 228 197 229 198 m.lowerIP.cloneTo(aIPAddress); 230 199 … … 232 201 } 233 202 234 235 203 STDMETHODIMP DHCPServer::COMGETTER(UpperIP) (BSTR *aIPAddress) 236 204 { … … 244 212 return S_OK; 245 213 } 246 247 214 248 215 STDMETHODIMP DHCPServer::SetConfiguration (IN_BSTR aIPAddress, IN_BSTR aNetworkMask, IN_BSTR aLowerIP, IN_BSTR aUpperIP) … … 258 225 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 259 226 m.IPAddress = aIPAddress; 260 m.GlobalDhcpOptions[DhcpOpt_SubnetMask] = aNetworkMask; 261 227 m.networkMask = aNetworkMask; 262 228 m.lowerIP = aLowerIP; 263 229 m.upperIP = aUpperIP; … … 269 235 } 270 236 271 272 STDMETHODIMP DHCPServer::AddGlobalOption(DhcpOpt_T aOption, IN_BSTR aValue)273 {274 CheckComArgStr(aValue);275 /* store global option */276 AutoCaller autoCaller(this);277 if (FAILED(autoCaller.rc())) return autoCaller.rc();278 279 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);280 281 m.GlobalDhcpOptions.insert(282 DhcpOptValuePair(aOption, Utf8Str(aValue)));283 284 alock.release();285 286 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);287 return mVirtualBox->saveSettings();288 }289 290 291 STDMETHODIMP DHCPServer::COMGETTER(GlobalOptions)(ComSafeArrayOut(BSTR, aValue))292 {293 CheckComArgOutSafeArrayPointerValid(aValue);294 295 AutoCaller autoCaller(this);296 if (FAILED(autoCaller.rc())) return autoCaller.rc();297 298 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);299 300 SafeArray<BSTR> sf(m.GlobalDhcpOptions.size());301 int i = 0;302 303 for (DhcpOptIterator it = m.GlobalDhcpOptions.begin();304 it != m.GlobalDhcpOptions.end(); ++it)305 {306 Bstr(Utf8StrFmt("%d:%s", (*it).first, (*it).second.c_str())).detachTo(&sf[i]);307 i++;308 }309 310 sf.detachTo(ComSafeArrayOutArg(aValue));311 312 return S_OK;313 }314 315 316 STDMETHODIMP DHCPServer::COMGETTER(VmConfigs)(ComSafeArrayOut(BSTR, aValue))317 {318 CheckComArgOutSafeArrayPointerValid(aValue);319 320 AutoCaller autoCaller(this);321 if (FAILED(autoCaller.rc())) return autoCaller.rc();322 323 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);324 325 SafeArray<BSTR> sf(m.VmSlot2Options.size());326 VmSlot2OptionsIterator it = m.VmSlot2Options.begin();327 int i = 0;328 for (;it != m.VmSlot2Options.end(); ++it)329 {330 Bstr(Utf8StrFmt("[%s]:%d",331 it->first.VmName.c_str(),332 it->first.Slot)).detachTo(&sf[i]);333 i++;334 }335 336 sf.detachTo(ComSafeArrayOutArg(aValue));337 338 return S_OK;339 }340 341 342 STDMETHODIMP DHCPServer::AddVmSlotOption(IN_BSTR aVmName, LONG aSlot, DhcpOpt_T aOption, IN_BSTR aValue)343 {344 AutoCaller autoCaller(this);345 if (FAILED(autoCaller.rc())) return autoCaller.rc();346 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);347 348 m.VmSlot2Options[settings::VmNameSlotKey(349 com::Utf8Str(aVmName),350 aSlot)][aOption] = com::Utf8Str(aValue);351 352 353 alock.release();354 355 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);356 return mVirtualBox->saveSettings();357 }358 359 360 STDMETHODIMP DHCPServer::RemoveVmSlotOptions(IN_BSTR aVmName, LONG aSlot)361 {362 AutoCaller autoCaller(this);363 if (FAILED(autoCaller.rc())) return autoCaller.rc();364 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);365 366 DhcpOptionMap& map = findOptMapByVmNameSlot(com::Utf8Str(aVmName), aSlot);367 368 map.clear();369 370 alock.release();371 372 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS);373 return mVirtualBox->saveSettings();374 }375 376 377 /**378 * this is mapping (vm, slot)379 */380 STDMETHODIMP DHCPServer::GetVmSlotOptions(IN_BSTR aVmName, LONG aSlot, ComSafeArrayOut(BSTR, aValues))381 {382 CheckComArgOutSafeArrayPointerValid(aValues);383 AutoCaller autoCaller(this);384 if (FAILED(autoCaller.rc())) return autoCaller.rc();385 386 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);387 388 DhcpOptionMap& map = findOptMapByVmNameSlot(com::Utf8Str(aVmName), aSlot);389 390 SafeArray<BSTR> sf(map.size());391 int i = 0;392 393 for (DhcpOptIterator it = map.begin();394 it != map.end(); ++it)395 {396 Bstr(Utf8StrFmt("%d:%s", (*it).first, (*it).second.c_str())).detachTo(&sf[i]);397 i++;398 }399 400 sf.detachTo(ComSafeArrayOutArg(aValues));401 402 return S_OK;403 }404 405 406 STDMETHODIMP DHCPServer::GetMacOptions(IN_BSTR aMAC, ComSafeArrayOut(BSTR, aValues))407 {408 CheckComArgOutSafeArrayPointerValid(aValues);409 410 AutoCaller autoCaller(this);411 if (FAILED(autoCaller.rc())) return autoCaller.rc();412 413 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);414 HRESULT hrc;415 416 ComPtr<IMachine> machine;417 ComPtr<INetworkAdapter> nic;418 419 VmSlot2OptionsIterator it;420 for(it = m.VmSlot2Options.begin();421 it != m.VmSlot2Options.end();422 ++it)423 {424 425 alock.release();426 hrc = mVirtualBox->FindMachine(Bstr(it->first.VmName).raw(), machine.asOutParam());427 alock.acquire();428 429 if (FAILED(hrc))430 continue;431 432 alock.release();433 hrc = machine->GetNetworkAdapter(it->first.Slot, nic.asOutParam());434 alock.acquire();435 436 if (FAILED(hrc))437 continue;438 439 com::Bstr mac;440 441 alock.release();442 hrc = nic->COMGETTER(MACAddress)(mac.asOutParam());443 alock.acquire();444 445 if (FAILED(hrc)) /* no MAC address ??? */446 break;447 448 if (!RTStrICmp(com::Utf8Str(mac).c_str(), com::Utf8Str(aMAC).c_str()))449 return GetVmSlotOptions(Bstr(it->first.VmName).raw(),450 it->first.Slot,451 ComSafeArrayOutArg(aValues));452 } /* end of for */453 454 return hrc;455 }456 457 458 STDMETHODIMP DHCPServer::COMGETTER(EventSource)(IEventSource **aEventSource)459 {460 ReturnComNotImplemented();461 }462 463 464 237 STDMETHODIMP DHCPServer::Start(IN_BSTR aNetworkName, IN_BSTR aTrunkName, IN_BSTR aTrunkType) 465 238 { … … 467 240 if (!m.enabled) 468 241 return S_OK; 469 470 /* Commmon Network Settings */ 471 m.dhcp.setOption(NETCFG_NETNAME, Utf8Str(aNetworkName), true); 472 242 243 m.dhcp.setOption(DHCPCFG_NETNAME, Utf8Str(aNetworkName), true); 473 244 Bstr tmp(aTrunkName); 474 475 245 if (!tmp.isEmpty()) 476 m.dhcp.setOption( NETCFG_TRUNKNAME, Utf8Str(tmp), true);477 m.dhcp.setOption( NETCFG_TRUNKTYPE, Utf8Str(aTrunkType), true);478 479 / * XXX: should this MAC default initialization moved to NetworkServiceRunner? */246 m.dhcp.setOption(DHCPCFG_TRUNKNAME, Utf8Str(tmp), true); 247 m.dhcp.setOption(DHCPCFG_TRUNKTYPE, Utf8Str(aTrunkType), true); 248 //temporary hack for testing 249 // DHCPCFG_NAME 480 250 char strMAC[32]; 481 251 Guid guid; 482 252 guid.create(); 483 253 RTStrPrintf (strMAC, sizeof(strMAC), "08:00:27:%02X:%02X:%02X", 484 guid.raw()->au8[0], 485 guid.raw()->au8[1], 486 guid.raw()->au8[2]); 487 m.dhcp.setOption(NETCFG_MACADDRESS, strMAC, true); 488 m.dhcp.setOption(NETCFG_IPADDRESS, Utf8Str(m.IPAddress), true); 489 m.dhcp.setOption(NETCFG_NETMASK, Utf8Str(m.GlobalDhcpOptions[DhcpOpt_SubnetMask]), true); 490 491 /* XXX: This parameters Dhcp Server will fetch via API */ 254 guid.raw()->au8[0], guid.raw()->au8[1], guid.raw()->au8[2]); 255 m.dhcp.setOption(DHCPCFG_MACADDRESS, strMAC, true); 256 m.dhcp.setOption(DHCPCFG_IPADDRESS, Utf8Str(m.IPAddress), true); 257 // DHCPCFG_LEASEDB, 258 // DHCPCFG_VERBOSE, 259 // DHCPCFG_GATEWAY, 260 m.dhcp.setOption(DHCPCFG_LOWERIP, Utf8Str(m.lowerIP), true); 261 m.dhcp.setOption(DHCPCFG_UPPERIP, Utf8Str(m.upperIP), true); 262 m.dhcp.setOption(DHCPCFG_NETMASK, Utf8Str(m.networkMask), true); 263 264 // DHCPCFG_HELP, 265 // DHCPCFG_VERSION, 266 // DHCPCFG_NOTOPT_MAXVAL 267 m.dhcp.setOption(DHCPCFG_BEGINCONFIG, "", true); 268 492 269 return RT_FAILURE(m.dhcp.start()) ? E_FAIL : S_OK; 493 270 //m.dhcp.detachFromServer(); /* need to do this to avoid server shutdown on runner destruction */ 494 271 } 495 272 496 497 273 STDMETHODIMP DHCPServer::Stop (void) 498 274 { 499 275 return RT_FAILURE(m.dhcp.stop()) ? E_FAIL : S_OK; 500 276 } 501 502 DhcpOptionMap& DHCPServer::findOptMapByVmNameSlot(const com::Utf8Str& aVmName,503 LONG aSlot)504 {505 return m.VmSlot2Options[settings::VmNameSlotKey(506 com::Utf8Str(aVmName),507 aSlot)];508 } -
trunk/src/VBox/Main/src-server/HostImpl.cpp
r46959 r46969 134 134 #include <iprt/mem.h> 135 135 #include <iprt/system.h> 136 #if ndef RT_OS_WINDOWS136 #ifdef RT_OS_SOLARIS 137 137 # include <iprt/path.h> 138 #endif139 #ifdef RT_OS_SOLARIS140 138 # include <iprt/ctype.h> 141 139 #endif … … 217 215 218 216 HostPowerService *pHostPowerService; 219 220 /* Name resolving */221 std::list<com::Bstr> llNameServers;222 std::list<com::Bstr> llSearchStrings;223 Bstr DomainName;224 /* XXX: we need timestamp when these values were set, on repeate in some225 * (~1h?, 5 min?) period, this values should be refetched from host syetem.226 */227 217 }; 228 218 229 #ifndef RT_OS_WINDOWS230 static char g_aszResolvConf[RTPATH_MAX];231 232 static inline char *getResolvConfPath()233 {234 int rc = VINF_SUCCESS;235 if (!g_aszResolvConf[0]) return g_aszResolvConf;236 # ifdef RT_OS_OS2237 /*238 * This was in an old Slirp code:239 * IBM's "Technical Document # - 16070238", clearly says \MPTN\ETC\RESOLV2240 * no redolv.conf (remark to code in old Slirp code)241 */242 if (RTEnvExists("ETC"))243 {244 RTStrmPrintf(g_aszResolvConf, MAX_PATH, "%/RESOLV2", RTEnvGet("ETC"));245 rc = RTFileExists(g_aszResolvConf);246 if (RT_SUCCESS(rc))247 return g_aszResolvConf;248 }249 250 RT_ZERO(g_aszResolvConf);251 RTStrmPrintf(g_aszResolvConf, MAX_PATH, "%/RESOLV2", _PATH_ETC);252 # else253 strcmp(g_aszResolvConf, "/etc/resolv.conf");254 # endif255 return g_aszResolvConf;256 }257 #endif258 219 259 220 //////////////////////////////////////////////////////////////////////////////// … … 836 797 #endif 837 798 } 838 839 840 /**841 * This method return the list of registered name servers842 */843 STDMETHODIMP Host::COMGETTER(NameServers)(ComSafeArrayOut(BSTR, aNameServers))844 {845 return E_NOTIMPL;846 }847 848 849 /**850 * This method returns the domain name of the host851 */852 STDMETHODIMP Host::COMGETTER(DomainName)(BSTR *aDomainName)853 {854 return E_NOTIMPL;855 }856 857 858 /**859 * This method returns the search string.860 */861 STDMETHODIMP Host::COMGETTER(SearchStrings)(ComSafeArrayOut(BSTR, aSearchStrings))862 {863 return E_NOTIMPL;864 }865 866 799 867 800 STDMETHODIMP Host::COMGETTER(USBDeviceFilters)(ComSafeArrayOut(IHostUSBDeviceFilter*, aUSBDeviceFilters)) -
trunk/src/VBox/Main/src-server/NATNetworkImpl.cpp
r46959 r46969 18 18 */ 19 19 20 #include " NetworkServiceRunner.h"20 #include "DHCPServerRunner.h" 21 21 #include "DHCPServerImpl.h" 22 22 #include "NATNetworkImpl.h" … … 35 35 #include "VBoxEvents.h" 36 36 37 #include "NATNetworkServiceRunner.h" 37 38 #include "VirtualBoxImpl.h" 38 39 … … 631 632 632 633 if (!m->fEnabled) return S_OK; 633 634 m->NATRunner.setOption(NETCFG_NETNAME, mName, true); 635 m->NATRunner.setOption(NETCFG_TRUNKTYPE, Utf8Str(aTrunkType), true); 636 m->NATRunner.setOption(NETCFG_IPADDRESS, m->IPv4Gateway, true); 637 m->NATRunner.setOption(NETCFG_NETMASK, m->IPv4NetworkMask, true); 638 639 /* No portforwarding rules from command-line, all will be fetched via API */ 634 m->NATRunner.setOption(NATSCCFG_NAME, mName, true); 635 m->NATRunner.setOption(NATSCCFG_TRUNKTYPE, Utf8Str(aTrunkType), true); 636 m->NATRunner.setOption(NATSCCFG_IPADDRESS, m->IPv4Gateway, true); 637 m->NATRunner.setOption(NATSCCFG_NETMASK, m->IPv4NetworkMask, true); 638 639 /* port-forwarding */ 640 641 for (constNATRuleMapIterator it = m->mapName2PortForwardRule4.begin(); 642 it != m->mapName2PortForwardRule4.end(); ++it) 643 { 644 settings::NATRule r = it->second; 645 m->NATRunner.setOption(NATSCCFG_PORTFORWARD4, 646 Bstr(Utf8StrFmt("%s:%d:[%s]:%d:[%s]:%d", 647 r.strName.c_str(), 648 r.proto, 649 r.strHostIP.isEmpty() ? 650 "0.0.0.0" : 651 r.strHostIP.c_str(), 652 r.u16HostPort, 653 r.strGuestIP.c_str(), 654 r.u16GuestPort)), true); 655 } 640 656 641 657 if (m->fNeedDhcpServer) … … 666 682 return E_FAIL; 667 683 /* breakthrough */ 668 684 case S_OK: 669 685 { 670 686 LogFunc(("gateway: %s, dhcpserver:%s, dhcplowerip:%s, dhcpupperip:%s\n", … … 673 689 Utf8Str(m->IPv4DhcpServerLowerIp.raw()).c_str(), 674 690 Utf8Str(m->IPv4DhcpServerUpperIp.raw()).c_str())); 675 676 m->dhcpServer->AddGlobalOption(DhcpOpt_Router, m->IPv4Gateway.raw()); 691 677 692 678 693 rc = m->dhcpServer->SetEnabled(true); 679 680 694 BSTR dhcpip = NULL; 681 695 BSTR netmask = NULL; 682 696 BSTR lowerip = NULL; 683 697 BSTR upperip = NULL; 684 685 698 m->IPv4DhcpServer.cloneTo(&dhcpip); 686 699 m->IPv4NetworkMask.cloneTo(&netmask); 700 687 701 m->IPv4DhcpServerLowerIp.cloneTo(&lowerip); 688 702 m->IPv4DhcpServerUpperIp.cloneTo(&upperip); … … 691 705 lowerip, 692 706 upperip); 707 break; 693 708 } 694 case S_OK: 695 break; 696 697 default: 698 return E_FAIL; 709 710 default: 711 return E_FAIL; 699 712 } 700 713 … … 715 728 #else 716 729 NOREF(aTrunkType); 717 ReturnComNotImplemented();730 return E_NOTIMPL; 718 731 #endif 719 732 } … … 728 741 } 729 742 else return E_FAIL; 743 730 744 #else 731 ReturnComNotImplemented();745 return E_NOTIMPL; 732 746 #endif 733 747 } … … 804 818 m->IPv4DhcpServerLowerIp = aszDhcpLowerIp; 805 819 m->IPv4DhcpServerUpperIp = aszDhcpUpperIp; 806 807 LogFunc(("network: %RTnaipv4, dhcpserver:%RTnaipv4, dhcplowerip:%RTnaipv4, dhcpupperip:%RTnaipv4\n", 808 network, 809 dhcpserver, 810 dhcplowerip, 811 dhcpupperip)); 820 LogFunc(("network: %RTnaipv4, dhcpserver:%RTnaipv4, dhcplowerip:%RTnaipv4, dhcpupperip:%RTnaipv4\n", network, dhcpserver, dhcplowerip, dhcpupperip)); 812 821 } 813 822 /* we need IPv4NetworkMask for NAT's gw service start */ -
trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp
r46959 r46969 61 61 #include "SystemPropertiesImpl.h" 62 62 #include "GuestOSTypeImpl.h" 63 #include " NetworkServiceRunner.h"63 #include "DHCPServerRunner.h" 64 64 #include "DHCPServerImpl.h" 65 65 #include "NATNetworkImpl.h" -
trunk/src/VBox/Main/src-server/xpcom/server.cpp
r46959 r46969 67 67 #include "BandwidthControlImpl.h" 68 68 #include "BandwidthGroupImpl.h" 69 #include " NetworkServiceRunner.h"69 #include "DHCPServerRunner.h" 70 70 #include "DHCPServerImpl.h" 71 71 #include "GuestOSTypeImpl.h" -
trunk/src/VBox/Main/xml/Settings.cpp
r46959 r46969 1302 1302 if ( (pelmServer->getAttributeValue("networkName", srv.strNetworkName)) 1303 1303 && (pelmServer->getAttributeValue("IPAddress", srv.strIPAddress)) 1304 && (pelmServer->getAttributeValue("networkMask", srv.GlobalDhcpOptions[DhcpOpt_SubnetMask]))1304 && (pelmServer->getAttributeValue("networkMask", srv.strIPNetworkMask)) 1305 1305 && (pelmServer->getAttributeValue("lowerIP", srv.strIPLower)) 1306 1306 && (pelmServer->getAttributeValue("upperIP", srv.strIPUpper)) 1307 1307 && (pelmServer->getAttributeValue("enabled", srv.fEnabled)) 1308 1308 ) 1309 {1310 xml::NodesLoop nlOptions(*pelmServer, "Options");1311 const xml::ElementNode *options;1312 /* XXX: Options are in 1:1 relation to DHCPServer */1313 1314 while ((options = nlOptions.forAllNodes()))1315 {1316 readDhcpOptions(srv.GlobalDhcpOptions, *options);1317 } /* end of forall("Options") */1318 xml::NodesLoop nlConfig(*pelmServer, "Config");1319 const xml::ElementNode *cfg;1320 while ((cfg = nlConfig.forAllNodes()))1321 {1322 com::Utf8Str strVmName;1323 uint32_t u32Slot;1324 cfg->getAttributeValue("vm-name", strVmName);1325 cfg->getAttributeValue("slot", (uint32_t&)u32Slot);1326 readDhcpOptions(srv.VmSlot2OptionsM[VmNameSlotKey(strVmName, u32Slot)],1327 *cfg);1328 }1329 1309 llDhcpServers.push_back(srv); 1330 }1331 1310 else 1332 1311 throw ConfigFileError(this, pelmServer, N_("Required DHCPServer/@networkName, @IPAddress, @networkMask, @lowerIP, @upperIP or @enabled attribute is missing")); 1333 1312 } 1334 1313 } 1335 }1336 1337 void MainConfigFile::readDhcpOptions(DhcpOptionMap& map,1338 const xml::ElementNode& options)1339 {1340 xml::NodesLoop nl2(options, "Option");1341 const xml::ElementNode *opt;1342 while((opt = nl2.forAllNodes()))1343 {1344 DhcpOpt_T OptName;1345 com::Utf8Str OptValue;1346 opt->getAttributeValue("name", (uint32_t&)OptName);1347 1348 if (OptName == DhcpOpt_SubnetMask)1349 continue;1350 1351 opt->getAttributeValue("value", OptValue);1352 1353 map.insert(1354 std::map<DhcpOpt_T, Utf8Str>::value_type(OptName, OptValue));1355 } /* end of forall("Option") */1356 1357 1314 } 1358 1315 … … 1489 1446 #endif 1490 1447 srv.strIPAddress = "192.168.56.100"; 1491 srv. GlobalDhcpOptions[DhcpOpt_SubnetMask]= "255.255.255.0";1448 srv.strIPNetworkMask = "255.255.255.0"; 1492 1449 srv.strIPLower = "192.168.56.101"; 1493 1450 srv.strIPUpper = "192.168.56.254"; … … 1532 1489 const DHCPServer &d = *it; 1533 1490 xml::ElementNode *pelmThis = pelmDHCPServers->createChild("DHCPServer"); 1534 DhcpOptConstIterator itOpt;1535 itOpt = d.GlobalDhcpOptions.find(DhcpOpt_SubnetMask);1536 1537 1491 pelmThis->setAttribute("networkName", d.strNetworkName); 1538 1492 pelmThis->setAttribute("IPAddress", d.strIPAddress); 1539 if (itOpt != d.GlobalDhcpOptions.end()) 1540 pelmThis->setAttribute("networkMask", itOpt->second); 1493 pelmThis->setAttribute("networkMask", d.strIPNetworkMask); 1541 1494 pelmThis->setAttribute("lowerIP", d.strIPLower); 1542 1495 pelmThis->setAttribute("upperIP", d.strIPUpper); 1543 1496 pelmThis->setAttribute("enabled", (d.fEnabled) ? 1 : 0); // too bad we chose 1 vs. 0 here 1544 /* We assume that if there're only 1 element it means that */ 1545 int cOpt = d.GlobalDhcpOptions.size(); 1546 /* We don't want duplicate validation check of networkMask here*/ 1547 if ( ( itOpt == d.GlobalDhcpOptions.end() 1548 && cOpt > 0) 1549 || cOpt > 1) 1550 { 1551 xml::ElementNode *pelmOptions = pelmThis->createChild("Options"); 1552 for (itOpt = d.GlobalDhcpOptions.begin(); 1553 itOpt != d.GlobalDhcpOptions.end(); 1554 ++itOpt) 1555 { 1556 if (itOpt->first == DhcpOpt_SubnetMask) 1557 continue; 1558 1559 xml::ElementNode *pelmOpt = pelmOptions->createChild("Option"); 1560 1561 if (!pelmOpt) 1562 break; 1563 1564 pelmOpt->setAttribute("name", itOpt->first); 1565 pelmOpt->setAttribute("value", itOpt->second); 1566 } 1567 } /* end of if */ 1568 1569 if (d.VmSlot2OptionsM.size() > 0) 1570 { 1571 VmSlot2OptionsConstIterator itVmSlot; 1572 DhcpOptConstIterator itOpt1; 1573 for(itVmSlot = d.VmSlot2OptionsM.begin(); 1574 itVmSlot != d.VmSlot2OptionsM.end(); 1575 ++itVmSlot) 1576 { 1577 xml::ElementNode *pelmCfg = pelmThis->createChild("Config"); 1578 pelmCfg->setAttribute("vm-name", itVmSlot->first.VmName); 1579 pelmCfg->setAttribute("slot", itVmSlot->first.Slot); 1580 1581 for (itOpt1 = itVmSlot->second.begin(); 1582 itOpt1 != itVmSlot->second.end(); 1583 ++itOpt1) 1584 { 1585 xml::ElementNode *pelmOpt = pelmCfg->createChild("Option"); 1586 pelmOpt->setAttribute("name", itOpt1->first); 1587 pelmOpt->setAttribute("value", itOpt1->second); 1588 } 1589 } 1590 } /* and of if */ 1591 1592 } 1497 } 1593 1498 1594 1499 /* TODO: bump main version ? */ -
trunk/src/VBox/NetworkServices/DHCP/Makefile.kmk
r46968 r46969 33 33 # Hardened VBoxNetDHCP. 34 34 # 35 VBoxNetDHCPHardened_TEMPLATE = VBOX MAINCLIENTEXE35 VBoxNetDHCPHardened_TEMPLATE = VBOXR3HARDENEDEXE 36 36 VBoxNetDHCPHardened_SOURCES = VBoxNetDHCPHardened.cpp 37 37 VBoxNetDHCPHardened_NAME = VBoxNetDHCP … … 41 41 # VBoxNetDHCP 42 42 # 43 VBoxNetDHCP_TEMPLATE = VBOXMAINCLIENTEXE44 #VBoxNetDHCP_TEMPLATE := VBOXR3$(if-expr defined(VBOX_WITH_HARDENING),,EXE)43 VBoxNetDHCP_TEMPLATE = 44 VBoxNetDHCP_TEMPLATE := VBOXR3$(if-expr defined(VBOX_WITH_HARDENING),,EXE) 45 45 VBoxNetDHCP_SOURCES = \ 46 46 VBoxNetDHCP.cpp \ 47 Config.cpp \48 47 ../NetLib/VBoxNetIntIf.cpp \ 49 48 ../NetLib/VBoxNetUDP.cpp \ 50 ../NetLib/VBoxNetARP.cpp \ 51 ../NetLib/VBoxNetBaseService.cpp 49 ../NetLib/VBoxNetARP.cpp 52 50 VBoxNetDHCP_LIBS = \ 53 51 $(LIB_RUNTIME) 54 52 VBoxNetDHCP_LDFLAGS.win = /SUBSYSTEM:windows 55 53 56 ifeq ($(USERNAME),vvl)57 PROGRAMS += tstDhcpConfig58 59 #60 # VBOXMAINCLIENT here only to use DhcpOpt_T type.61 tstDhcpConfig_TEMPLATE = VBOXMAINCLIENTEXE62 #XXX: enable condtionally if user is vvl63 #tstDhcpConfig_INSTTYPE = none64 tstDhcpConfig_SOURCES = test/tstDhcpConfig.cpp65 endif66 67 54 68 55 include $(FILE_KBUILD_SUB_FOOTER) -
trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp
r46962 r46969 25 25 * Header Files * 26 26 *******************************************************************************/ 27 #include <VBox/com/com.h>28 #include <VBox/com/listeners.h>29 #include <VBox/com/string.h>30 #include <VBox/com/Guid.h>31 #include <VBox/com/array.h>32 #include <VBox/com/ErrorInfo.h>33 #include <VBox/com/errorprint.h>34 #include <VBox/com/EventQueue.h>35 #include <VBox/com/VirtualBox.h>36 37 27 #include <iprt/alloca.h> 38 28 #include <iprt/buildconfig.h> … … 54 44 #include <VBox/version.h> 55 45 56 57 46 #include "../NetLib/VBoxNetLib.h" 58 47 59 48 #include <vector> 60 #include <list>61 49 #include <string> 62 #include <map>63 64 #include "../NetLib/VBoxNetBaseService.h"65 50 66 51 #ifdef RT_OS_WINDOWS /* WinMain */ … … 69 54 #endif 70 55 71 #ifndef INET4_ADDRLEN 72 # define INET4_ADDRLEN 17 73 #endif 74 75 #include "Config.h" 56 76 57 /******************************************************************************* 77 58 * Structures and Typedefs * 78 59 *******************************************************************************/ 60 61 /** 62 * DHCP configuration item. 63 * 64 * This is all public data because I'm too lazy to do it properly right now. 65 */ 66 class VBoxNetDhcpCfg 67 { 68 public: 69 /** The etheret addresses this matches config applies to. 70 * An empty vector means 'ANY'. */ 71 std::vector<RTMAC> m_MacAddresses; 72 /** The upper address in the range. */ 73 RTNETADDRIPV4 m_UpperAddr; 74 /** The lower address in the range. */ 75 RTNETADDRIPV4 m_LowerAddr; 76 77 /** Option 1: The net mask. */ 78 RTNETADDRIPV4 m_SubnetMask; 79 /* * Option 2: The time offset. */ 80 /** Option 3: Routers for the subnet. */ 81 std::vector<RTNETADDRIPV4> m_Routers; 82 /* * Option 4: Time server. */ 83 /* * Option 5: Name server. */ 84 /** Option 6: Domain Name Server (DNS) */ 85 std::vector<RTNETADDRIPV4> m_DNSes; 86 /* * Option 7: Log server. */ 87 /* * Option 8: Cookie server. */ 88 /* * Option 9: LPR server. */ 89 /* * Option 10: Impress server. */ 90 /* * Option 11: Resource location server. */ 91 /* * Option 12: Host name. */ 92 std::string m_HostName; 93 /* * Option 13: Boot file size option. */ 94 /* * Option 14: Merit dump file. */ 95 /** Option 15: Domain name. */ 96 std::string m_DomainName; 97 /* * Option 16: Swap server. */ 98 /* * Option 17: Root path. */ 99 /* * Option 18: Extension path. */ 100 /* * Option 19: IP forwarding enable/disable. */ 101 /* * Option 20: Non-local routing enable/disable. */ 102 /* * Option 21: Policy filter. */ 103 /* * Option 22: Maximum datagram reassembly size (MRS). */ 104 /* * Option 23: Default IP time-to-live. */ 105 /* * Option 24: Path MTU aging timeout. */ 106 /* * Option 25: Path MTU plateau table. */ 107 /* * Option 26: Interface MTU. */ 108 /* * Option 27: All subnets are local. */ 109 /* * Option 28: Broadcast address. */ 110 /* * Option 29: Perform maximum discovery. */ 111 /* * Option 30: Mask supplier. */ 112 /* * Option 31: Perform route discovery. */ 113 /* * Option 32: Router solicitation address. */ 114 /* * Option 33: Static route. */ 115 /* * Option 34: Trailer encapsulation. */ 116 /* * Option 35: ARP cache timeout. */ 117 /* * Option 36: Ethernet encapsulation. */ 118 /* * Option 37: TCP Default TTL. */ 119 /* * Option 38: TCP Keepalive Interval. */ 120 /* * Option 39: TCP Keepalive Garbage. */ 121 /* * Option 40: Network Information Service (NIS) Domain. */ 122 /* * Option 41: Network Information Servers. */ 123 /* * Option 42: Network Time Protocol Servers. */ 124 /* * Option 43: Vendor Specific Information. */ 125 /* * Option 44: NetBIOS over TCP/IP Name Server (NBNS). */ 126 /* * Option 45: NetBIOS over TCP/IP Datagram distribution Server (NBDD). */ 127 /* * Option 46: NetBIOS over TCP/IP Node Type. */ 128 /* * Option 47: NetBIOS over TCP/IP Scope. */ 129 /* * Option 48: X Window System Font Server. */ 130 /* * Option 49: X Window System Display Manager. */ 131 132 /** Option 51: IP Address Lease Time. */ 133 uint32_t m_cSecLease; 134 135 /* * Option 64: Network Information Service+ Domain. */ 136 /* * Option 65: Network Information Service+ Servers. */ 137 /** Option 66: TFTP server name. */ 138 std::string m_TftpServer; 139 /** Address for the bp_siaddr field corresponding to m_TftpServer. */ 140 RTNETADDRIPV4 m_TftpServerAddr; 141 /** Option 67: Bootfile name. */ 142 std::string m_BootfileName; 143 144 /* * Option 68: Mobile IP Home Agent. */ 145 /* * Option 69: Simple Mail Transport Protocol (SMPT) Server. */ 146 /* * Option 70: Post Office Protocol (POP3) Server. */ 147 /* * Option 71: Network News Transport Protocol (NNTP) Server. */ 148 /* * Option 72: Default World Wide Web (WWW) Server. */ 149 /* * Option 73: Default Finger Server. */ 150 /* * Option 74: Default Internet Relay Chat (IRC) Server. */ 151 /* * Option 75: StreetTalk Server. */ 152 153 /* * Option 119: Domain Search. */ 154 155 156 VBoxNetDhcpCfg() 157 { 158 m_UpperAddr.u = UINT32_MAX; 159 m_LowerAddr.u = UINT32_MAX; 160 m_SubnetMask.u = UINT32_MAX; 161 m_cSecLease = 60*60; /* 1 hour */ 162 } 163 164 /** Validates the configuration. 165 * @returns 0 on success, exit code + error message to stderr on failure. */ 166 int validate(void) 167 { 168 if ( m_UpperAddr.u == UINT32_MAX 169 || m_LowerAddr.u == UINT32_MAX 170 || m_SubnetMask.u == UINT32_MAX) 171 { 172 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: Config is missing:"); 173 if (m_UpperAddr.u == UINT32_MAX) 174 RTStrmPrintf(g_pStdErr, " --upper-ip"); 175 if (m_LowerAddr.u == UINT32_MAX) 176 RTStrmPrintf(g_pStdErr, " --lower-ip"); 177 if (m_SubnetMask.u == UINT32_MAX) 178 RTStrmPrintf(g_pStdErr, " --netmask"); 179 return 2; 180 } 181 182 if (RT_N2H_U32(m_UpperAddr.u) < RT_N2H_U32(m_LowerAddr.u)) 183 { 184 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: The --upper-ip value is lower than the --lower-ip one!\n" 185 " %d.%d.%d.%d < %d.%d.%d.%d\n", 186 m_UpperAddr.au8[0], m_UpperAddr.au8[1], m_UpperAddr.au8[2], m_UpperAddr.au8[3], 187 m_LowerAddr.au8[0], m_LowerAddr.au8[1], m_LowerAddr.au8[2], m_LowerAddr.au8[3]); 188 return 3; 189 } 190 191 /* the code goes insane if we have too many atm. lazy bird */ 192 uint32_t cIPs = RT_N2H_U32(m_UpperAddr.u) - RT_N2H_U32(m_LowerAddr.u); 193 if (cIPs > 1024) 194 { 195 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: Too many IPs between --upper-ip and --lower-ip! %d (max 1024)\n" 196 " %d.%d.%d.%d < %d.%d.%d.%d\n", 197 cIPs, 198 m_UpperAddr.au8[0], m_UpperAddr.au8[1], m_UpperAddr.au8[2], m_UpperAddr.au8[3], 199 m_LowerAddr.au8[0], m_LowerAddr.au8[1], m_LowerAddr.au8[2], m_LowerAddr.au8[3]); 200 return 3; 201 } 202 return 0; 203 } 204 205 /** 206 * Is this config for one specific client? 207 * 208 * @return true / false. 209 */ 210 bool isOneSpecificClient(void) const 211 { 212 return m_LowerAddr.u == m_UpperAddr.u 213 && m_MacAddresses.size() > 0; 214 } 215 216 /** 217 * Checks if this config matches the specified MAC address. 218 * 219 * @returns true / false. 220 * 221 * @param pMac The MAC address to match. 222 */ 223 bool matchesMacAddress(PCRTMAC pMac) const 224 { 225 size_t i = m_MacAddresses.size(); 226 if (RT_LIKELY(i < 1)) 227 return true; /* no entries == ALL wildcard match */ 228 229 while (i--) 230 { 231 PCRTMAC pCur = &m_MacAddresses[i]; 232 if ( pCur->au16[0] == pMac->au16[0] 233 && pCur->au16[1] == pMac->au16[1] 234 && pCur->au16[2] == pMac->au16[2]) 235 return true; 236 } 237 return false; 238 } 239 240 }; 241 242 /** 243 * DHCP lease. 244 */ 245 class VBoxNetDhcpLease 246 { 247 public: 248 typedef enum State 249 { 250 /** Invalid. */ 251 kState_Invalid = 0, 252 /** The lease is free / released. */ 253 kState_Free, 254 /** An offer has been made. 255 * Expire time indicates when the offer expires. */ 256 kState_Offer, 257 /** The lease is active. 258 * Expire time indicates when the lease expires. */ 259 kState_Active 260 } State; 261 262 /** The client MAC address. */ 263 RTMAC m_MacAddress; 264 /** The IPv4 address. */ 265 RTNETADDRIPV4 m_IPv4Address; 266 267 /** The current lease state. */ 268 State m_enmState; 269 /** The lease expiration time. */ 270 RTTIMESPEC m_ExpireTime; 271 /** Transaction ID. */ 272 uint32_t m_xid; 273 /** The configuration for this lease. */ 274 VBoxNetDhcpCfg *m_pCfg; 275 276 public: 277 /** Constructor taking an IPv4 address and a Config. */ 278 VBoxNetDhcpLease(RTNETADDRIPV4 IPv4Addr, VBoxNetDhcpCfg *pCfg) 279 { 280 m_pCfg = pCfg; 281 m_IPv4Address = IPv4Addr; 282 283 m_MacAddress.au16[0] = m_MacAddress.au16[1] = m_MacAddress.au16[2] = 0xff; 284 m_enmState = kState_Free; 285 RTTimeSpecSetSeconds(&m_ExpireTime, 0); 286 m_xid = UINT32_MAX; 287 } 288 289 /** Destructor. */ 290 ~VBoxNetDhcpLease() 291 { 292 m_IPv4Address.u = UINT32_MAX; 293 m_pCfg = NULL; 294 m_MacAddress.au16[0] = m_MacAddress.au16[1] = m_MacAddress.au16[2] = 0xff; 295 m_enmState = kState_Free; 296 m_xid = UINT32_MAX; 297 } 298 299 void offer(uint32_t xid); 300 void activate(void); 301 void activate(uint32_t xid); 302 void release(void); 303 bool hasExpired(void) const; 304 305 /** 306 * Checks if the lease is in use or not. 307 * 308 * @returns true if active, false if free or expired. 309 * 310 * @param pNow The current time to use. Optional. 311 */ 312 bool isInUse(PCRTTIMESPEC pNow = NULL) const 313 { 314 if ( m_enmState == kState_Offer 315 || m_enmState == kState_Active) 316 { 317 RTTIMESPEC Now; 318 if (!pNow) 319 pNow = RTTimeNow(&Now); 320 return RTTimeSpecGetSeconds(&m_ExpireTime) > RTTimeSpecGetSeconds(pNow); 321 } 322 return false; 323 } 324 325 /** 326 * Is this lease for one specific client? 327 * 328 * @return true/false. 329 */ 330 bool isOneSpecificClient(void) const 331 { 332 return m_pCfg 333 && m_pCfg->isOneSpecificClient(); 334 } 335 336 /** 337 * Is this lease currently being offered to a client. 338 * 339 * @returns true / false. 340 */ 341 bool isBeingOffered(void) const 342 { 343 return m_enmState == kState_Offer 344 && isInUse(); 345 } 346 347 /** 348 * Is the lease in the current config or not. 349 * 350 * When updating the config we might leave active leases behind which aren't 351 * included in the new config. These will have m_pCfg set to NULL and should be 352 * freed up when they expired. 353 * 354 * @returns true / false. 355 */ 356 bool isInCurrentConfig(void) const 357 { 358 return m_pCfg != NULL; 359 } 360 }; 361 79 362 /** 80 363 * DHCP server instance. 81 364 */ 82 class VBoxNetDhcp : public VBoxNetBaseService365 class VBoxNetDhcp 83 366 { 84 367 public: … … 86 369 virtual ~VBoxNetDhcp(); 87 370 88 int init(); 371 int parseArgs(int argc, char **argv); 372 int tryGoOnline(void); 89 373 int run(void); 90 void usage(void) { /* XXX: document options */ };91 int parseOpt(int rc, const RTGETOPTUNION& getOptVal);92 374 93 375 protected: 376 int addConfig(VBoxNetDhcpCfg *pCfg); 377 void explodeConfig(void); 378 94 379 bool handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t cb); 95 380 bool handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb); … … 97 382 bool handleDhcpReqDecline(PCRTNETBOOTP pDhcpMsg, size_t cb); 98 383 bool handleDhcpReqRelease(PCRTNETBOOTP pDhcpMsg, size_t cb); 99 384 void makeDhcpReply(uint8_t uMsgType, VBoxNetDhcpLease *pLease, PCRTNETBOOTP pDhcpMsg, size_t cb); 385 386 VBoxNetDhcpLease *findLeaseByMacAddress(PCRTMAC pMacAddress, bool fAnyState); 387 VBoxNetDhcpLease *findLeaseByIpv4AndMacAddresses(RTNETADDRIPV4 IPv4Addr, PCRTMAC pMacAddress, bool fAnyState); 388 VBoxNetDhcpLease *newLease(PCRTNETBOOTP pDhcpMsg, size_t cb); 389 390 static uint8_t const *findOption(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cb, size_t *pcbMaxOpt); 391 static bool findOptionIPv4Addr(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cb, PRTNETADDRIPV4 pIPv4Addr); 392 393 inline void debugPrint( int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const; 100 394 void debugPrintV(int32_t iMinLevel, bool fMsg, const char *pszFmt, va_list va) const; 101 395 static const char *debugDhcpName(uint8_t uMsgType); 102 396 103 397 protected: 104 /** @name The DHCP server specificconfiguration data members.398 /** @name The server configuration data members. 105 399 * @{ */ 106 /* 107 * XXX: what was the plan? SQL3 or plain text file? 108 * How it will coexists with managment from VBoxManagement, who should manage db 109 * in that case (VBoxManage, VBoxSVC ???) 110 */ 400 std::string m_Name; 401 std::string m_Network; 402 std::string m_TrunkName; 403 INTNETTRUNKTYPE m_enmTrunkType; 404 RTMAC m_MacAddress; 405 RTNETADDRIPV4 m_Ipv4Address; 111 406 std::string m_LeaseDBName; 112 113 407 /** @} */ 114 408 115 /* corresponding dhcp server description in Main */ 116 ComPtr<IDHCPServer> m_DhcpServer; 117 118 ComPtr<INATNetwork> m_NATNetwork; 119 120 /* 121 * We will ignore cmd line parameters IFF there will be some DHCP specific arguments 122 * otherwise all paramters will come from Main. 123 */ 124 bool m_fIgnoreCmdLineParameters; 125 126 /* 127 * -b -n 10.0.1.2 -m 255.255.255.0 -> to the list processing in 128 */ 129 typedef struct 130 { 131 char Key; 132 std::string strValue; 133 } CMDLNPRM; 134 std::list<CMDLNPRM> CmdParameterll; 135 typedef std::list<CMDLNPRM>::iterator CmdParameterIterator; 409 /** The current configs. */ 410 std::vector<VBoxNetDhcpCfg *> m_Cfgs; 411 412 /** The current leases. */ 413 std::vector<VBoxNetDhcpLease> m_Leases; 414 415 /** @name The network interface 416 * @{ */ 417 PSUPDRVSESSION m_pSession; 418 uint32_t m_cbSendBuf; 419 uint32_t m_cbRecvBuf; 420 INTNETIFHANDLE m_hIf; /**< The handle to the network interface. */ 421 PINTNETBUF m_pIfBuf; /**< Interface buffer. */ 422 /** @} */ 136 423 137 424 /** @name Debug stuff … … 144 431 /** @} */ 145 432 }; 146 #if 0 147 /* XXX: clean up it. */ 148 typedef std::vector<VBoxNetDhcpLease> DhcpLeaseContainer; 149 typedef DhcpLeaseContainer::iterator DhcpLeaseIterator; 150 typedef DhcpLeaseContainer::reverse_iterator DhcpLeaseRIterator; 151 typedef DhcpLeaseContainer::const_iterator DhcpLeaseCIterator; 152 #endif 433 153 434 154 435 /******************************************************************************* … … 158 439 static VBoxNetDhcp *g_pDhcp; 159 440 160 /* DHCP server specific options */ 161 static const RTGETOPTDEF g_aOptionDefs[] = 162 { 163 { "--lease-db", 'D', RTGETOPT_REQ_STRING }, 164 { "--begin-config", 'b', RTGETOPT_REQ_NOTHING }, 165 { "--gateway", 'g', RTGETOPT_REQ_IPV4ADDR }, 166 { "--lower-ip", 'l', RTGETOPT_REQ_IPV4ADDR }, 167 { "--upper-ip", 'u', RTGETOPT_REQ_IPV4ADDR }, 168 }; 169 170 #if 0 171 /* XXX this will gone */ 441 172 442 /** 173 443 * Offer this lease to a client. … … 235 505 return RTTimeSpecGetSeconds(&m_ExpireTime) > RTTimeSpecGetSeconds(RTTimeNow(&Now)); 236 506 } 237 #endif 507 508 509 238 510 239 511 /** … … 266 538 memset(&m_CurHdrs, '\0', sizeof(m_CurHdrs)); 267 539 268 m_fIgnoreCmdLineParameters = true;269 270 540 #if 0 /* enable to hack the code without a mile long argument list. */ 271 541 VBoxNetDhcpCfg *pDefCfg = new VBoxNetDhcpCfg(); … … 279 549 pDefCfg->m_DNSes.push_back(Addr); 280 550 pDefCfg->m_DomainName = "vboxnetdhcp.org"; 281 # 551 #if 0 282 552 pDefCfg->m_cSecLease = 60*60; /* 1 hour */ 283 # 553 #else 284 554 pDefCfg->m_cSecLease = 30; /* sec */ 285 # 555 #endif 286 556 pDefCfg->m_TftpServer = "10.0.2.3"; //?? 287 557 this->addConfig(pDefCfg); … … 295 565 VBoxNetDhcp::~VBoxNetDhcp() 296 566 { 297 } 298 299 300 301 302 /** 303 * Parse the DHCP specific arguments. 304 * 305 * This callback caled for each paramenter so 306 * .... 307 * we nee post analisys of the parameters, at least 308 * for -b, -g, -l, -u, -m 309 */ 310 int VBoxNetDhcp::parseOpt(int rc, const RTGETOPTUNION& Val) 311 { 312 CMDLNPRM prm; 313 314 /* Ok, we've entered here, thus we can't ignore cmd line parameters anymore */ 315 m_fIgnoreCmdLineParameters = false; 316 317 prm.Key = rc; 318 319 switch (rc) 320 { 567 /* 568 * Close the interface connection. 569 */ 570 if (m_hIf != INTNET_HANDLE_INVALID) 571 { 572 INTNETIFCLOSEREQ CloseReq; 573 CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC; 574 CloseReq.Hdr.cbReq = sizeof(CloseReq); 575 CloseReq.pSession = m_pSession; 576 CloseReq.hIf = m_hIf; 577 m_hIf = INTNET_HANDLE_INVALID; 578 int rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr); 579 AssertRC(rc); 580 } 581 582 if (m_pSession) 583 { 584 SUPR3Term(false /*fForced*/); 585 m_pSession = NIL_RTR0PTR; 586 } 587 } 588 589 590 /** 591 * Adds a config to the tail. 592 * 593 * @returns See VBoxNetDHCP::validate(). 594 * @param pCfg The config too add. 595 * This object will be consumed by this call! 596 */ 597 int VBoxNetDhcp::addConfig(VBoxNetDhcpCfg *pCfg) 598 { 599 int rc = 0; 600 if (pCfg) 601 { 602 rc = pCfg->validate(); 603 if (!rc) 604 m_Cfgs.push_back(pCfg); 605 else 606 delete pCfg; 607 } 608 return rc; 609 } 610 611 612 /** 613 * Explodes the config into leases. 614 * 615 * @remarks This code is brute force and not very fast nor memory efficient. 616 * We will have to revisit this later. 617 * 618 * @remarks If an IP has been reconfigured for a fixed mac address and it's 619 * already leased to a client, we it won't be available until the 620 * client releases its lease or it expires. 621 */ 622 void VBoxNetDhcp::explodeConfig(void) 623 { 624 RTTIMESPEC Now; 625 RTTimeNow(&Now); 626 627 /* 628 * Remove all non-active leases from the vector and zapping the 629 * config pointers of the once left behind. 630 */ 631 std::vector<VBoxNetDhcpLease>::iterator Itr = m_Leases.begin(); 632 while (Itr != m_Leases.end()) 633 { 634 if (!Itr->isInUse(&Now)) 635 Itr = m_Leases.erase(Itr); 636 else 637 { 638 Itr->m_pCfg = NULL; 639 Itr++; 640 } 641 } 642 643 /* 644 * Loop thru the configurations in reverse order, giving the last 645 * configs priority of the newer ones. 646 */ 647 size_t iCfg = m_Cfgs.size(); 648 while (iCfg-- > 0) 649 { 650 VBoxNetDhcpCfg *pCfg = m_Cfgs[iCfg]; 651 652 /* Expand the IP lease range. */ 653 uint32_t const uLast = RT_N2H_U32(pCfg->m_UpperAddr.u); 654 for (uint32_t i = RT_N2H_U32(pCfg->m_LowerAddr.u); i <= uLast; i++) 655 { 656 RTNETADDRIPV4 IPv4Addr; 657 IPv4Addr.u = RT_H2N_U32(i); 658 659 /* Check if it exists and is configured. */ 660 VBoxNetDhcpLease *pLease = NULL; 661 for (size_t j = 0; j < m_Leases.size(); j++) 662 if (m_Leases[j].m_IPv4Address.u == IPv4Addr.u) 663 { 664 pLease = &m_Leases[j]; 665 break; 666 } 667 if (pLease) 668 { 669 if (!pLease->m_pCfg) 670 pLease->m_pCfg = pCfg; 671 } 672 else 673 { 674 /* add it. */ 675 VBoxNetDhcpLease NewLease(IPv4Addr, pCfg); 676 m_Leases.push_back(NewLease); 677 debugPrint(10, false, "exploseConfig: new lease %d.%d.%d.%d", 678 IPv4Addr.au8[0], IPv4Addr.au8[1], IPv4Addr.au8[2], IPv4Addr.au8[3]); 679 } 680 } 681 } 682 } 683 684 685 /** 686 * Parse the arguments. 687 * 688 * @returns 0 on success, fully bitched exit code on failure. 689 * 690 * @param argc Argument count. 691 * @param argv Argument vector. 692 */ 693 int VBoxNetDhcp::parseArgs(int argc, char **argv) 694 { 695 static const RTGETOPTDEF s_aOptionDefs[] = 696 { 697 { "--name", 'N', RTGETOPT_REQ_STRING }, 698 { "--network", 'n', RTGETOPT_REQ_STRING }, 699 { "--trunk-name", 't', RTGETOPT_REQ_STRING }, 700 { "--trunk-type", 'T', RTGETOPT_REQ_STRING }, 701 { "--mac-address", 'a', RTGETOPT_REQ_MACADDR }, 702 { "--ip-address", 'i', RTGETOPT_REQ_IPV4ADDR }, 703 { "--lease-db", 'D', RTGETOPT_REQ_STRING }, 704 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 705 706 { "--begin-config", 'b', RTGETOPT_REQ_NOTHING }, 707 { "--gateway", 'g', RTGETOPT_REQ_IPV4ADDR }, 708 { "--lower-ip", 'l', RTGETOPT_REQ_IPV4ADDR }, 709 { "--upper-ip", 'u', RTGETOPT_REQ_IPV4ADDR }, 710 { "--netmask", 'm', RTGETOPT_REQ_IPV4ADDR }, 711 }; 712 713 RTGETOPTSTATE State; 714 int rc = RTGetOptInit(&State, argc, argv, &s_aOptionDefs[0], RT_ELEMENTS(s_aOptionDefs), 0, 0 /*fFlags*/); 715 AssertRCReturn(rc, 49); 716 717 VBoxNetDhcpCfg *pCurCfg = NULL; 718 for (;;) 719 { 720 RTGETOPTUNION Val; 721 rc = RTGetOpt(&State, &Val); 722 if (!rc) 723 break; 724 switch (rc) 725 { 726 case 'N': 727 m_Name = Val.psz; 728 break; 729 case 'n': 730 m_Network = Val.psz; 731 break; 732 case 't': 733 m_TrunkName = Val.psz; 734 break; 735 case 'T': 736 if (!strcmp(Val.psz, "none")) 737 m_enmTrunkType = kIntNetTrunkType_None; 738 else if (!strcmp(Val.psz, "whatever")) 739 m_enmTrunkType = kIntNetTrunkType_WhateverNone; 740 else if (!strcmp(Val.psz, "netflt")) 741 m_enmTrunkType = kIntNetTrunkType_NetFlt; 742 else if (!strcmp(Val.psz, "netadp")) 743 m_enmTrunkType = kIntNetTrunkType_NetAdp; 744 else if (!strcmp(Val.psz, "srvnat")) 745 m_enmTrunkType = kIntNetTrunkType_SrvNat; 746 else 747 { 748 RTStrmPrintf(g_pStdErr, "Invalid trunk type '%s'\n", Val.psz); 749 return 1; 750 } 751 break; 752 case 'a': 753 m_MacAddress = Val.MacAddr; 754 break; 755 case 'i': 756 m_Ipv4Address = Val.IPv4Addr; 757 break; 758 case 'd': 759 m_LeaseDBName = Val.psz; 760 break; 761 762 case 'v': 763 m_cVerbosity++; 764 break; 765 321 766 /* Begin config. */ 322 case 'b': 323 CmdParameterll.push_back(prm); 324 break; 325 326 case 'l': 327 case 'u': 328 case 'm': 329 case 'g': 330 prm.strValue = std::string(Val.psz); 331 CmdParameterll.push_back(prm); 332 break; 333 334 case 'D': 335 break; 336 337 default: 338 rc = RTGetOptPrintError(rc, &Val); 339 RTPrintf("Use --help for more information.\n"); 340 return rc; 341 } 767 case 'b': 768 rc = addConfig(pCurCfg); 769 if (rc) 770 break; 771 pCurCfg = NULL; 772 /* fall thru */ 773 774 /* config specific ones. */ 775 case 'g': 776 case 'l': 777 case 'u': 778 case 'm': 779 if (!pCurCfg) 780 { 781 pCurCfg = new VBoxNetDhcpCfg(); 782 if (!pCurCfg) 783 { 784 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: new VBoxDhcpCfg failed\n"); 785 return 1; 786 } 787 } 788 789 switch (rc) 790 { 791 case 'g': 792 pCurCfg->m_Routers.push_back(Val.IPv4Addr); 793 break; 794 795 case 'l': 796 pCurCfg->m_LowerAddr = Val.IPv4Addr; 797 break; 798 799 case 'u': 800 pCurCfg->m_UpperAddr = Val.IPv4Addr; 801 break; 802 803 case 'm': 804 pCurCfg->m_SubnetMask = Val.IPv4Addr; 805 break; 806 807 case 0: /* ignore */ break; 808 default: 809 AssertMsgFailed(("%d", rc)); 810 return 1; 811 } 812 break; 813 814 case 'V': 815 RTPrintf("%sr%u\n", RTBldCfgVersion(), RTBldCfgRevision()); 816 return 1; 817 818 case 'h': 819 RTPrintf("VBoxNetDHCP Version %s\n" 820 "(C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n" 821 "All rights reserved.\n" 822 "\n" 823 "Usage: VBoxNetDHCP <options>\n" 824 "\n" 825 "Options:\n", 826 RTBldCfgVersion()); 827 for (size_t i = 0; i < RT_ELEMENTS(s_aOptionDefs); i++) 828 RTPrintf(" -%c, %s\n", s_aOptionDefs[i].iShort, s_aOptionDefs[i].pszLong); 829 return 1; 830 831 default: 832 rc = RTGetOptPrintError(rc, &Val); 833 RTPrintf("Use --help for more information.\n"); 834 return rc; 835 } 836 } 837 838 /* 839 * Do the reconfig. (move this later) 840 */ 841 if (!rc) 842 explodeConfig(); 342 843 343 844 return rc; 344 845 } 345 846 346 int VBoxNetDhcp::init() 347 { 348 HRESULT hrc = S_OK; 349 /* ok, here we should initiate instance of dhcp server 350 * and listener for Dhcp configuration events 351 */ 352 AssertRCReturn(virtualbox.isNull(), VERR_INTERNAL_ERROR); 353 354 hrc = virtualbox->FindDHCPServerByNetworkName(com::Bstr(m_Network.c_str()).raw(), 355 m_DhcpServer.asOutParam()); 356 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR); 357 358 hrc = virtualbox->FindNATNetworkByName(com::Bstr(m_Network.c_str()).raw(), 359 m_NATNetwork.asOutParam()); 360 361 /* This isn't fatal in general case. 362 * AssertComRCReturn(hrc, VERR_INTERNAL_ERROR); 363 */ 364 365 ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager(); 366 AssertPtrReturn(confManager, VERR_INTERNAL_ERROR); 367 368 /** 369 * if we have nat netework of the same name 370 * this is good chance that we are assigned to this network. 371 */ 372 BOOL fNeedDhcpServer = false; 373 if ( !m_NATNetwork.isNull() 374 && SUCCEEDED(m_NATNetwork->COMGETTER(NeedDhcpServer)(&fNeedDhcpServer)) 375 && fNeedDhcpServer) 376 { 377 /* 90% we are servicing NAT network */ 378 RTNETADDRIPV4 gateway; 379 com::Bstr strGateway; 380 hrc = m_NATNetwork->GetGateway(strGateway.asOutParam()); 381 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR); 382 RTNetStrToIPv4Addr(com::Utf8Str(strGateway).c_str(), &gateway); 383 384 confManager->addToAddressList(RTNET_DHCP_OPT_ROUTERS, gateway); 385 } 386 387 NetworkManager *netManager = NetworkManager::getNetworkManager(); 388 389 netManager->setOurAddress(m_Ipv4Address); 390 netManager->setOurNetmask(m_Ipv4Netmask); 391 netManager->setOurMac(m_MacAddress); 392 393 /* Configuration fetching */ 394 if (m_fIgnoreCmdLineParameters) 395 { 396 /* just fetch option array and add options to config */ 397 /* per VM-settings ??? 398 * 399 * - we have vms with attached adapters with known mac-addresses 400 * - mac-addresses might be changed as well as names, how keep our config cleaned ???? 847 848 /** 849 * Tries to connect to the internal network. 850 * 851 * @returns 0 on success, exit code + error message to stderr on failure. 852 */ 853 int VBoxNetDhcp::tryGoOnline(void) 854 { 855 /* 856 * Open the session, load ring-0 and issue the request. 857 */ 858 int rc = SUPR3Init(&m_pSession); 859 if (RT_FAILURE(rc)) 860 { 861 m_pSession = NIL_RTR0PTR; 862 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPR3Init -> %Rrc", rc); 863 return 1; 864 } 865 866 char szPath[RTPATH_MAX]; 867 rc = RTPathExecDir(szPath, sizeof(szPath) - sizeof("/VMMR0.r0")); 868 if (RT_FAILURE(rc)) 869 { 870 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: RTPathProgram -> %Rrc", rc); 871 return 1; 872 } 873 874 rc = SUPR3LoadVMM(strcat(szPath, "/VMMR0.r0")); 875 if (RT_FAILURE(rc)) 876 { 877 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPR3LoadVMM(\"%s\") -> %Rrc", szPath, rc); 878 return 1; 879 } 880 881 /* 882 * Create the open request. 883 */ 884 INTNETOPENREQ OpenReq; 885 OpenReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC; 886 OpenReq.Hdr.cbReq = sizeof(OpenReq); 887 OpenReq.pSession = m_pSession; 888 strncpy(OpenReq.szNetwork, m_Network.c_str(), sizeof(OpenReq.szNetwork)); 889 OpenReq.szNetwork[sizeof(OpenReq.szNetwork) - 1] = '\0'; 890 strncpy(OpenReq.szTrunk, m_TrunkName.c_str(), sizeof(OpenReq.szTrunk)); 891 OpenReq.szTrunk[sizeof(OpenReq.szTrunk) - 1] = '\0'; 892 OpenReq.enmTrunkType = m_enmTrunkType; 893 OpenReq.fFlags = 0; /** @todo check this */ 894 OpenReq.cbSend = m_cbSendBuf; 895 OpenReq.cbRecv = m_cbRecvBuf; 896 OpenReq.hIf = INTNET_HANDLE_INVALID; 897 898 /* 899 * Issue the request. 900 */ 901 debugPrint(2, false, "attempting to open/create network \"%s\"...", OpenReq.szNetwork); 902 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_OPEN, 0, &OpenReq.Hdr); 903 if (RT_SUCCESS(rc)) 904 { 905 m_hIf = OpenReq.hIf; 906 debugPrint(1, false, "successfully opened/created \"%s\" - hIf=%#x", OpenReq.szNetwork, m_hIf); 907 908 /* 909 * Get the ring-3 address of the shared interface buffer. 401 910 */ 402 com::SafeArray<BSTR> sf; 403 hrc = m_DhcpServer->GetGlobalOptions(ComSafeArrayAsOutParam(sf)); 404 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR); 405 406 #if 0 407 for (int i = 0; i < sf.size(); ++i) 408 { 409 RTPrintf("%d: %s\n", i, com::Utf8Str(sf[i]).c_str()); 410 } 411 412 #endif 413 com::Bstr strUpperIp, strLowerIp; 414 415 RTNETADDRIPV4 LowerAddress; 416 RTNETADDRIPV4 UpperAddress; 417 418 hrc = m_DhcpServer->GetUpperIP(strUpperIp.asOutParam()); 419 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR); 420 RTNetStrToIPv4Addr(com::Utf8Str(strUpperIp).c_str(), &UpperAddress); 421 422 423 hrc = m_DhcpServer->GetLowerIP(strLowerIp.asOutParam()); 424 AssertComRCReturn(hrc, VERR_INTERNAL_ERROR); 425 RTNetStrToIPv4Addr(com::Utf8Str(strLowerIp).c_str(), &LowerAddress); 426 427 RTNETADDRIPV4 networkId; 428 networkId.u = m_Ipv4Address.u & m_Ipv4Netmask.u; 429 std::string name = std::string("default"); 430 431 NetworkConfigEntity *pCfg = confManager->addNetwork(unconst(g_RootConfig), 432 networkId, 433 m_Ipv4Netmask, 434 LowerAddress, 435 UpperAddress); 436 437 } /* if(m_fIgnoreCmdLineParameters) */ 911 INTNETIFGETBUFFERPTRSREQ GetBufferPtrsReq; 912 GetBufferPtrsReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC; 913 GetBufferPtrsReq.Hdr.cbReq = sizeof(GetBufferPtrsReq); 914 GetBufferPtrsReq.pSession = m_pSession; 915 GetBufferPtrsReq.hIf = m_hIf; 916 GetBufferPtrsReq.pRing3Buf = NULL; 917 GetBufferPtrsReq.pRing0Buf = NIL_RTR0PTR; 918 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS, 0, &GetBufferPtrsReq.Hdr); 919 if (RT_SUCCESS(rc)) 920 { 921 PINTNETBUF pBuf = GetBufferPtrsReq.pRing3Buf; 922 debugPrint(1, false, "pBuf=%p cbBuf=%d cbSend=%d cbRecv=%d", 923 pBuf, pBuf->cbBuf, pBuf->cbSend, pBuf->cbRecv); 924 m_pIfBuf = pBuf; 925 926 /* 927 * Activate the interface. 928 */ 929 INTNETIFSETACTIVEREQ ActiveReq; 930 ActiveReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC; 931 ActiveReq.Hdr.cbReq = sizeof(ActiveReq); 932 ActiveReq.pSession = m_pSession; 933 ActiveReq.hIf = m_hIf; 934 ActiveReq.fActive = true; 935 rc = SUPR3CallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr); 936 if (RT_SUCCESS(rc)) 937 return 0; 938 939 /* bail out */ 940 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,) failed, rc=%Rrc\n", rc); 941 } 942 else 943 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,) failed, rc=%Rrc\n", rc); 944 } 438 945 else 439 { 440 CmdParameterIterator it; 441 442 RTNETADDRIPV4 networkId; 443 networkId.u = m_Ipv4Address.u & m_Ipv4Netmask.u; 444 RTNETADDRIPV4 netmask = m_Ipv4Netmask; 445 RTNETADDRIPV4 LowerAddress; 446 RTNETADDRIPV4 UpperAddress; 447 448 LowerAddress = networkId; 449 UpperAddress.u = RT_H2N_U32(RT_N2H_U32(LowerAddress.u) | RT_N2H_U32(netmask.u)); 450 451 int idx = 0; 452 char name[64]; 453 454 455 for (it = CmdParameterll.begin(); it != CmdParameterll.end(); ++it) 456 { 457 idx++; 458 RTStrPrintf(name, RT_ELEMENTS(name), "network-%d", idx); 459 std::string strname(name); 460 461 switch(it->Key) 462 { 463 case 'b': 464 /* config */ 465 NetworkConfigEntity(strname, 466 g_RootConfig, 467 g_AnyClient, 468 5, 469 networkId, 470 netmask, 471 LowerAddress, 472 UpperAddress); 473 case 'l': 474 case 'u': 475 case 'm': 476 case 'g': 477 /* XXX: TBD */ 478 break; 479 } 480 } 481 } 482 return VINF_SUCCESS; 483 } 946 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: SUPR3CallVMMR0Ex(,VMMR0_DO_INTNET_OPEN,) failed, rc=%Rrc\n", rc); 947 948 return RT_SUCCESS(rc) ? 0 : 1; 949 } 950 484 951 485 952 /** … … 491 958 int VBoxNetDhcp::run(void) 492 959 { 493 494 /* XXX: shortcut should be hidden from network manager */495 NetworkManager *netManager = NetworkManager::getNetworkManager();496 netManager->m_pSession = m_pSession;497 netManager->m_hIf = m_hIf;498 netManager->m_pIfBuf = m_pIfBuf;499 500 960 /* 501 961 * The loop. … … 614 1074 bool VBoxNetDhcp::handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb) 615 1075 { 616 617 /* let's main first */ 618 if (!m_DhcpServer.isNull()) 619 { 620 HRESULT hrc; 621 com::SafeArray<BSTR> sf; 622 hrc = m_DhcpServer->GetMacOptions(com::BstrFmt("%02X%02X%02X%02X%02X%02X", 623 pDhcpMsg->bp_chaddr.Mac.au8[0], 624 pDhcpMsg->bp_chaddr.Mac.au8[1], 625 pDhcpMsg->bp_chaddr.Mac.au8[2], 626 pDhcpMsg->bp_chaddr.Mac.au8[3], 627 pDhcpMsg->bp_chaddr.Mac.au8[4], 628 pDhcpMsg->bp_chaddr.Mac.au8[5], 629 pDhcpMsg->bp_chaddr.Mac.au8[6]).raw(), 630 ComSafeArrayAsOutParam(sf)); 631 if (SUCCEEDED(hrc)) 632 { 633 /* XXX: per-host configuration */ 634 } 635 636 SessionManager *sesionManager = SessionManager::getSessionManager(); 637 Session& session = sesionManager->getClientSessionByDhcpPacket(pDhcpMsg, cb); 638 /* XXX: switch -> private */ 639 session.switchTo(DHCPDISCOVERRECEIEVED); 640 641 ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager(); 642 int rc = confManager->findConfiguration4Session(session); 643 AssertRCReturn(rc, rc); 644 645 rc = confManager->allocateConfiguration4Session(session); 646 AssertRCReturn(rc, rc); 647 648 NetworkManager *netManager = NetworkManager::getNetworkManager(); 649 rc = netManager->offer4Session(session); 650 AssertRCReturn(rc, rc); 651 652 653 } /* end of if(!m_DhcpServer.isNull()) */ 654 655 return VINF_SUCCESS; 1076 /* 1077 * The newLease() method contains logic for finding current leases 1078 * and reusing them in case the client is forgetful. 1079 */ 1080 VBoxNetDhcpLease *pLease = newLease(pDhcpMsg, cb); 1081 if (!pLease) 1082 return false; 1083 debugPrint(1, true, "Offering %d.%d.%d.%d to %.6Rhxs xid=%#x", 1084 pLease->m_IPv4Address.au8[0], 1085 pLease->m_IPv4Address.au8[1], 1086 pLease->m_IPv4Address.au8[2], 1087 pLease->m_IPv4Address.au8[3], 1088 &pDhcpMsg->bp_chaddr.Mac, 1089 pDhcpMsg->bp_xid); 1090 pLease->offer(pDhcpMsg->bp_xid); 1091 1092 makeDhcpReply(RTNET_DHCP_MT_OFFER, pLease, pDhcpMsg, cb); 1093 return true; 656 1094 } 657 1095 … … 667 1105 bool VBoxNetDhcp::handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb) 668 1106 { 669 SessionManager *sesionManager = SessionManager::getSessionManager(); 670 Session& session = sesionManager->getClientSessionByDhcpPacket(pDhcpMsg, cb); 671 /* XXX: switch -> private */ 672 session.switchTo(DHCPREQUESTRECEIVED); 673 674 ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager(); 675 int rc = confManager->findConfiguration4Session(session); 676 AssertRCReturn(rc, false); 677 678 rc = confManager->commitConfiguration4ClientSession(session); 679 680 NetworkManager *netManager = NetworkManager::getNetworkManager(); 681 if (RT_SUCCESS(rc)) 682 rc = netManager->ack(session); 1107 /** @todo Probably need to match the server IP here to work correctly with 1108 * other servers. */ 1109 /** @todo This code isn't entirely correct and quite a bit of a hack, but it 1110 * will have to do for now as the right thing (tm) is very complex. 1111 * Part of the fun is verifying that the request is something we can 1112 * and should handle. */ 1113 1114 /* 1115 * Try find the lease by the requested address + client MAC address. 1116 */ 1117 VBoxNetDhcpLease *pLease = NULL; 1118 RTNETADDRIPV4 IPv4Addr; 1119 bool fReqAddr = findOptionIPv4Addr(RTNET_DHCP_OPT_REQ_ADDR, pDhcpMsg, cb, &IPv4Addr); 1120 if (fReqAddr) 1121 { 1122 fReqAddr = true; 1123 pLease = findLeaseByIpv4AndMacAddresses(IPv4Addr, &pDhcpMsg->bp_chaddr.Mac, true /* fAnyState */); 1124 } 1125 1126 /* 1127 * Try find the lease by the client IP address + client MAC address. 1128 */ 1129 if ( !pLease 1130 && pDhcpMsg->bp_ciaddr.u) 1131 pLease = findLeaseByIpv4AndMacAddresses(pDhcpMsg->bp_ciaddr, &pDhcpMsg->bp_chaddr.Mac, true /* fAnyState */); 1132 1133 #if 0 /** @todo client id stuff - it doesn't make sense here imho, we need IP + MAC. What would make sense 1134 though is to compare the client id with what we've got in the lease and use it to root out 1135 bad requests. */ 1136 /* 1137 * Try find the lease by using the client id. 1138 */ 1139 if (!pLease) 1140 { 1141 size_t cbClientID = 0; 1142 uint8_t const *pbClientID = findOption(RTNET_DHCP_OPT_CLIENT_ID, pDhcpMsg, cb, &cbClientID); 1143 if ( pbClientID 1144 && cbClientID == sizeof(RTMAC) + 1 1145 && pbClientID[0] == RTNET_ARP_ETHER 1146 && 1147 ) 1148 { 1149 pLease = findLeaseByIpv4AndMacAddresses(pDhcpMsg->bp_ciaddr, &pDhcpMsg->bp_chaddr.Mac, true /* fAnyState */); 1150 } 1151 } 1152 #endif 1153 1154 /* 1155 * Validate the lease that's requested. 1156 * We've already check the MAC and IP addresses. 1157 */ 1158 bool fAckIt = false; 1159 if (pLease) 1160 { 1161 if (pLease->isBeingOffered()) 1162 { 1163 if (pLease->m_xid == pDhcpMsg->bp_xid) 1164 debugPrint(2, true, "REQUEST for offered lease."); 1165 else 1166 debugPrint(2, true, "REQUEST for offered lease, xid mismatch. Expected %#x, got %#x.", 1167 pLease->m_xid, pDhcpMsg->bp_xid); 1168 pLease->activate(pDhcpMsg->bp_xid); 1169 fAckIt = true; 1170 } 1171 else if (!pLease->isInCurrentConfig()) 1172 debugPrint(1, true, "REQUEST for obsolete lease -> NAK"); 1173 else if (fReqAddr != (pDhcpMsg->bp_ciaddr.u != 0)) // ??? 1174 { 1175 /** @todo this ain't safe. */ 1176 debugPrint(1, true, "REQUEST for lease not on offer, assuming renewal. lease_xid=%#x bp_xid=%#x", 1177 pLease->m_xid, pDhcpMsg->bp_xid); 1178 fAckIt = true; 1179 pLease->activate(pDhcpMsg->bp_xid); 1180 } 1181 else 1182 debugPrint(1, true, "REQUEST for lease not on offer, NAK it."); 1183 } 1184 1185 /* 1186 * NAK if if no lease was found. 1187 */ 1188 if (fAckIt) 1189 { 1190 debugPrint(1, false, "ACK'ing DHCP_REQUEST"); 1191 makeDhcpReply(RTNET_DHCP_MT_ACK, pLease, pDhcpMsg, cb); 1192 } 683 1193 else 684 rc = netManager->nak(session); 685 686 AssertRCReturn(rc, false); 1194 { 1195 debugPrint(1, false, "NAK'ing DHCP_REQUEST"); 1196 makeDhcpReply(RTNET_DHCP_MT_NAC, NULL, pDhcpMsg, cb); 1197 } 687 1198 688 1199 return true; … … 749 1260 debugPrint(1, true, "RELEASE is not implemented"); 750 1261 return true; 1262 } 1263 1264 1265 /** 1266 * Helper class for stuffing DHCP options into a reply packet. 1267 */ 1268 class VBoxNetDhcpWriteCursor 1269 { 1270 private: 1271 uint8_t *m_pbCur; /**< The current cursor position. */ 1272 uint8_t *m_pbEnd; /**< The end the current option space. */ 1273 uint8_t *m_pfOverload; /**< Pointer to the flags of the overload option. */ 1274 uint8_t m_fUsed; /**< Overload fields that have been used. */ 1275 PRTNETDHCPOPT m_pOpt; /**< The current option. */ 1276 PRTNETBOOTP m_pDhcp; /**< The DHCP packet. */ 1277 bool m_fOverflowed; /**< Set if we've overflowed, otherwise false. */ 1278 1279 public: 1280 /** Instantiate an option cursor for the specified DHCP message. */ 1281 VBoxNetDhcpWriteCursor(PRTNETBOOTP pDhcp, size_t cbDhcp) : 1282 m_pbCur(&pDhcp->bp_vend.Dhcp.dhcp_opts[0]), 1283 m_pbEnd((uint8_t *)pDhcp + cbDhcp), 1284 m_pfOverload(NULL), 1285 m_fUsed(0), 1286 m_pOpt(NULL), 1287 m_pDhcp(pDhcp), 1288 m_fOverflowed(false) 1289 { 1290 AssertPtr(pDhcp); 1291 Assert(cbDhcp > RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts[10])); 1292 } 1293 1294 /** Destructor. */ 1295 ~VBoxNetDhcpWriteCursor() 1296 { 1297 m_pbCur = m_pbEnd = m_pfOverload = NULL; 1298 m_pOpt = NULL; 1299 m_pDhcp = NULL; 1300 } 1301 1302 /** 1303 * Try use the bp_file field. 1304 * @returns true if not overloaded, false otherwise. 1305 */ 1306 bool useBpFile(void) 1307 { 1308 if ( m_pfOverload 1309 && (*m_pfOverload & 1)) 1310 return false; 1311 m_fUsed |= 1 /* bp_file flag*/; 1312 return true; 1313 } 1314 1315 1316 /** 1317 * Try overload more BOOTP fields 1318 */ 1319 bool overloadMore(void) 1320 { 1321 /* switch option area. */ 1322 uint8_t *pbNew; 1323 uint8_t *pbNewEnd; 1324 uint8_t fField; 1325 if (!(m_fUsed & 1)) 1326 { 1327 fField = 1; 1328 pbNew = &m_pDhcp->bp_file[0]; 1329 pbNewEnd = &m_pDhcp->bp_file[sizeof(m_pDhcp->bp_file)]; 1330 } 1331 else if (!(m_fUsed & 2)) 1332 { 1333 fField = 2; 1334 pbNew = &m_pDhcp->bp_sname[0]; 1335 pbNewEnd = &m_pDhcp->bp_sname[sizeof(m_pDhcp->bp_sname)]; 1336 } 1337 else 1338 return false; 1339 1340 if (!m_pfOverload) 1341 { 1342 /* Add an overload option. */ 1343 *m_pbCur++ = RTNET_DHCP_OPT_OPTION_OVERLOAD; 1344 *m_pbCur++ = fField; 1345 m_pfOverload = m_pbCur; 1346 *m_pbCur++ = 1; /* bp_file flag */ 1347 } 1348 else 1349 *m_pfOverload |= fField; 1350 1351 /* pad current option field */ 1352 while (m_pbCur != m_pbEnd) 1353 *m_pbCur++ = RTNET_DHCP_OPT_PAD; /** @todo not sure if this stuff is at all correct... */ 1354 1355 /* switch */ 1356 m_pbCur = pbNew; 1357 m_pbEnd = pbNewEnd; 1358 return true; 1359 } 1360 1361 /** 1362 * Begin an option. 1363 * 1364 * @returns true on success, false if we're out of space. 1365 * 1366 * @param uOption The option number. 1367 * @param cb The amount of data. 1368 */ 1369 bool begin(uint8_t uOption, size_t cb) 1370 { 1371 /* Check that the data of the previous option has all been written. */ 1372 Assert( !m_pOpt 1373 || (m_pbCur - m_pOpt->dhcp_len == (uint8_t *)(m_pOpt + 1))); 1374 AssertMsg(cb <= 255, ("%#x\n", cb)); 1375 1376 /* Check if we need to overload more stuff. */ 1377 if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + (m_pfOverload ? 1 : 3)) 1378 { 1379 m_pOpt = NULL; 1380 if (!overloadMore()) 1381 { 1382 m_fOverflowed = true; 1383 AssertMsgFailedReturn(("%u %#x\n", uOption, cb), false); 1384 } 1385 if ((uintptr_t)(m_pbEnd - m_pbCur) < cb + 2 + 1) 1386 { 1387 m_fOverflowed = true; 1388 AssertMsgFailedReturn(("%u %#x\n", uOption, cb), false); 1389 } 1390 } 1391 1392 /* Emit the option header. */ 1393 m_pOpt = (PRTNETDHCPOPT)m_pbCur; 1394 m_pOpt->dhcp_opt = uOption; 1395 m_pOpt->dhcp_len = (uint8_t)cb; 1396 m_pbCur += 2; 1397 return true; 1398 } 1399 1400 /** 1401 * Puts option data. 1402 * 1403 * @param pvData The data. 1404 * @param cb The amount to put. 1405 */ 1406 void put(void const *pvData, size_t cb) 1407 { 1408 Assert(m_pOpt || m_fOverflowed); 1409 if (RT_LIKELY(m_pOpt)) 1410 { 1411 Assert((uintptr_t)m_pbCur - (uintptr_t)(m_pOpt + 1) + cb <= (size_t)m_pOpt->dhcp_len); 1412 memcpy(m_pbCur, pvData, cb); 1413 m_pbCur += cb; 1414 } 1415 } 1416 1417 /** 1418 * Puts an IPv4 Address. 1419 * 1420 * @param IPv4Addr The address. 1421 */ 1422 void putIPv4Addr(RTNETADDRIPV4 IPv4Addr) 1423 { 1424 put(&IPv4Addr, 4); 1425 } 1426 1427 /** 1428 * Adds an IPv4 address option. 1429 * 1430 * @returns true/false just like begin(). 1431 * 1432 * @param uOption The option number. 1433 * @param IPv4Addr The address. 1434 */ 1435 bool optIPv4Addr(uint8_t uOption, RTNETADDRIPV4 IPv4Addr) 1436 { 1437 if (!begin(uOption, 4)) 1438 return false; 1439 putIPv4Addr(IPv4Addr); 1440 return true; 1441 } 1442 1443 /** 1444 * Adds an option taking 1 or more IPv4 address. 1445 * 1446 * If the vector contains no addresses, the option will not be added. 1447 * 1448 * @returns true/false just like begin(). 1449 * 1450 * @param uOption The option number. 1451 * @param rIPv4Addrs Reference to the address vector. 1452 */ 1453 bool optIPv4Addrs(uint8_t uOption, std::vector<RTNETADDRIPV4> const &rIPv4Addrs) 1454 { 1455 size_t const c = rIPv4Addrs.size(); 1456 if (!c) 1457 return true; 1458 1459 if (!begin(uOption, 4*c)) 1460 return false; 1461 for (size_t i = 0; i < c; i++) 1462 putIPv4Addr(rIPv4Addrs[i]); 1463 return true; 1464 } 1465 1466 /** 1467 * Puts an 8-bit integer. 1468 * 1469 * @param u8 The integer. 1470 */ 1471 void putU8(uint8_t u8) 1472 { 1473 put(&u8, 1); 1474 } 1475 1476 /** 1477 * Adds an 8-bit integer option. 1478 * 1479 * @returns true/false just like begin(). 1480 * 1481 * @param uOption The option number. 1482 * @param u8 The integer 1483 */ 1484 bool optU8(uint8_t uOption, uint8_t u8) 1485 { 1486 if (!begin(uOption, 1)) 1487 return false; 1488 putU8(u8); 1489 return true; 1490 } 1491 1492 /** 1493 * Puts an 32-bit integer (network endian). 1494 * 1495 * @param u32Network The integer. 1496 */ 1497 void putU32(uint32_t u32) 1498 { 1499 put(&u32, 4); 1500 } 1501 1502 /** 1503 * Adds an 32-bit integer (network endian) option. 1504 * 1505 * @returns true/false just like begin(). 1506 * 1507 * @param uOption The option number. 1508 * @param u32Network The integer. 1509 */ 1510 bool optU32(uint8_t uOption, uint32_t u32) 1511 { 1512 if (!begin(uOption, 4)) 1513 return false; 1514 putU32(u32); 1515 return true; 1516 } 1517 1518 /** 1519 * Puts a std::string. 1520 * 1521 * @param rStr Reference to the string. 1522 */ 1523 void putStr(std::string const &rStr) 1524 { 1525 put(rStr.c_str(), rStr.size()); 1526 } 1527 1528 /** 1529 * Adds an std::string option if the string isn't empty. 1530 * 1531 * @returns true/false just like begin(). 1532 * 1533 * @param uOption The option number. 1534 * @param rStr Reference to the string. 1535 */ 1536 bool optStr(uint8_t uOption, std::string const &rStr) 1537 { 1538 const size_t cch = rStr.size(); 1539 if (!cch) 1540 return true; 1541 1542 if (!begin(uOption, cch)) 1543 return false; 1544 put(rStr.c_str(), cch); 1545 return true; 1546 } 1547 1548 /** 1549 * Whether we've overflowed. 1550 * 1551 * @returns true on overflow, false otherwise. 1552 */ 1553 bool hasOverflowed(void) const 1554 { 1555 return m_fOverflowed; 1556 } 1557 1558 /** 1559 * Adds the terminating END option. 1560 * 1561 * The END will always be added as we're reserving room for it, however, we 1562 * might have dropped previous options due to overflows and that is what the 1563 * return status indicates. 1564 * 1565 * @returns true on success, false on a (previous) overflow. 1566 */ 1567 bool optEnd(void) 1568 { 1569 Assert((uintptr_t)(m_pbEnd - m_pbCur) < 4096); 1570 *m_pbCur++ = RTNET_DHCP_OPT_END; 1571 return !hasOverflowed(); 1572 } 1573 }; 1574 1575 1576 /** 1577 * Constructs and sends a reply to a client. 1578 * 1579 * @returns 1580 * @param uMsgType The DHCP message type. 1581 * @param pLease The lease. This can be NULL for some replies. 1582 * @param pDhcpMsg The client message. We will dig out the MAC address, 1583 * transaction ID, and requested options from this. 1584 * @param cb The size of the client message. 1585 */ 1586 void VBoxNetDhcp::makeDhcpReply(uint8_t uMsgType, VBoxNetDhcpLease *pLease, PCRTNETBOOTP pDhcpMsg, size_t cb) 1587 { 1588 size_t cbReply = RTNET_DHCP_NORMAL_SIZE; /** @todo respect the RTNET_DHCP_OPT_MAX_DHCP_MSG_SIZE option */ 1589 PRTNETBOOTP pReply = (PRTNETBOOTP)alloca(cbReply); 1590 1591 /* 1592 * The fixed bits stuff. 1593 */ 1594 pReply->bp_op = RTNETBOOTP_OP_REPLY; 1595 pReply->bp_htype = RTNET_ARP_ETHER; 1596 pReply->bp_hlen = sizeof(RTMAC); 1597 pReply->bp_hops = 0; 1598 pReply->bp_xid = pDhcpMsg->bp_xid; 1599 pReply->bp_secs = 0; 1600 pReply->bp_flags = 0; // (pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST); ?? 1601 pReply->bp_ciaddr.u = 0; 1602 pReply->bp_yiaddr.u = pLease ? pLease->m_IPv4Address.u : 0xffffffff; 1603 pReply->bp_siaddr.u = pLease && pLease->m_pCfg ? pLease->m_pCfg->m_TftpServerAddr.u : 0; /* (next server == TFTP)*/ 1604 pReply->bp_giaddr.u = 0; 1605 memset(&pReply->bp_chaddr, '\0', sizeof(pReply->bp_chaddr)); 1606 pReply->bp_chaddr.Mac = pDhcpMsg->bp_chaddr.Mac; 1607 memset(&pReply->bp_sname[0], '\0', sizeof(pReply->bp_sname)); 1608 memset(&pReply->bp_file[0], '\0', sizeof(pReply->bp_file)); 1609 pReply->bp_vend.Dhcp.dhcp_cookie = RT_H2N_U32_C(RTNET_DHCP_COOKIE); 1610 memset(&pReply->bp_vend.Dhcp.dhcp_opts[0], '\0', RTNET_DHCP_OPT_SIZE); 1611 1612 /* 1613 * The options - use a cursor class for dealing with the ugly stuff. 1614 */ 1615 VBoxNetDhcpWriteCursor Cursor(pReply, cbReply); 1616 1617 /* The basics */ 1618 Cursor.optU8(RTNET_DHCP_OPT_MSG_TYPE, uMsgType); 1619 Cursor.optIPv4Addr(RTNET_DHCP_OPT_SERVER_ID, m_Ipv4Address); 1620 1621 if (uMsgType != RTNET_DHCP_MT_NAC) 1622 { 1623 AssertReturnVoid(pLease && pLease->m_pCfg); 1624 const VBoxNetDhcpCfg *pCfg = pLease->m_pCfg; /* no need to retain it. */ 1625 1626 /* The IP config. */ 1627 Cursor.optU32(RTNET_DHCP_OPT_LEASE_TIME, RT_H2N_U32(pCfg->m_cSecLease)); 1628 Cursor.optIPv4Addr(RTNET_DHCP_OPT_SUBNET_MASK, pCfg->m_SubnetMask); 1629 Cursor.optIPv4Addrs(RTNET_DHCP_OPT_ROUTERS, pCfg->m_Routers); 1630 Cursor.optIPv4Addrs(RTNET_DHCP_OPT_ROUTERS, pCfg->m_DNSes); 1631 Cursor.optStr(RTNET_DHCP_OPT_HOST_NAME, pCfg->m_HostName); 1632 Cursor.optStr(RTNET_DHCP_OPT_DOMAIN_NAME, pCfg->m_DomainName); 1633 1634 /* The PXE config. */ 1635 if (pCfg->m_BootfileName.size()) 1636 { 1637 if (Cursor.useBpFile()) 1638 RTStrPrintf((char *)&pReply->bp_file[0], sizeof(pReply->bp_file), "%s", pCfg->m_BootfileName.c_str()); 1639 else 1640 Cursor.optStr(RTNET_DHCP_OPT_BOOTFILE_NAME, pCfg->m_BootfileName); 1641 } 1642 } 1643 1644 /* Terminate the options. */ 1645 if (!Cursor.optEnd()) 1646 debugPrint(0, true, "option overflow\n"); 1647 1648 /* 1649 * Send it. 1650 */ 1651 int rc; 1652 #if 0 1653 if (!(pDhcpMsg->bp_flags & RTNET_DHCP_FLAGS_NO_BROADCAST)) /** @todo need to see someone set this flag to check that it's correct. */ 1654 { 1655 RTNETADDRIPV4 IPv4AddrBrdCast; 1656 IPv4AddrBrdCast.u = UINT32_C(0xffffffff); /* broadcast IP */ 1657 rc = VBoxNetUDPUnicast(m_pSession, m_hIf, m_pIfBuf, 1658 m_Ipv4Address, &m_MacAddress, RTNETIPV4_PORT_BOOTPS, /* sender */ 1659 IPv4AddrBrdCast, &pDhcpMsg->bp_chaddr.Mac, RTNETIPV4_PORT_BOOTPC, /* receiver */ 1660 pReply, cbReply); 1661 } 1662 else 1663 #endif 1664 rc = VBoxNetUDPBroadcast(m_pSession, m_hIf, m_pIfBuf, 1665 m_Ipv4Address, &m_MacAddress, RTNETIPV4_PORT_BOOTPS, /* sender */ 1666 RTNETIPV4_PORT_BOOTPC, /* receiver port */ 1667 pReply, cbReply); 1668 if (RT_FAILURE(rc)) 1669 debugPrint(0, true, "error %Rrc when sending the reply", rc); 1670 } 1671 1672 1673 /** 1674 * Look up a lease by MAC address. 1675 * 1676 * @returns Pointer to the lease if found, NULL if not found. 1677 * @param pMacAddress The mac address. 1678 * @param fAnyState Any state. 1679 */ 1680 VBoxNetDhcpLease *VBoxNetDhcp::findLeaseByMacAddress(PCRTMAC pMacAddress, bool fAnyState) 1681 { 1682 size_t iLease = m_Leases.size(); 1683 while (iLease-- > 0) 1684 { 1685 VBoxNetDhcpLease *pLease = &m_Leases[iLease]; 1686 if ( pLease 1687 && pLease->m_MacAddress.au16[0] == pMacAddress->au16[0] 1688 && pLease->m_MacAddress.au16[1] == pMacAddress->au16[1] 1689 && pLease->m_MacAddress.au16[2] == pMacAddress->au16[2] 1690 && ( fAnyState 1691 || (pLease->m_enmState != VBoxNetDhcpLease::kState_Free)) ) 1692 return pLease; 1693 } 1694 1695 return NULL; 1696 } 1697 1698 1699 /** 1700 * Look up a lease by IPv4 and MAC addresses. 1701 * 1702 * @returns Pointer to the lease if found, NULL if not found. 1703 * @param IPv4Addr The IPv4 address. 1704 * @param pMacAddress The mac address. 1705 * @param fAnyState Any state. 1706 */ 1707 VBoxNetDhcpLease *VBoxNetDhcp::findLeaseByIpv4AndMacAddresses(RTNETADDRIPV4 IPv4Addr, PCRTMAC pMacAddress, bool fAnyState) 1708 { 1709 size_t iLease = m_Leases.size(); 1710 while (iLease-- > 0) 1711 { 1712 VBoxNetDhcpLease *pLease = &m_Leases[iLease]; 1713 if ( pLease 1714 && pLease->m_IPv4Address.u == IPv4Addr.u 1715 && pLease->m_MacAddress.au16[0] == pMacAddress->au16[0] 1716 && pLease->m_MacAddress.au16[1] == pMacAddress->au16[1] 1717 && pLease->m_MacAddress.au16[2] == pMacAddress->au16[2] 1718 && ( fAnyState 1719 || (pLease->m_enmState != VBoxNetDhcpLease::kState_Free)) ) 1720 return pLease; 1721 } 1722 1723 return NULL; 1724 } 1725 1726 1727 /** 1728 * Creates a new lease for the client specified in the DHCP message. 1729 * 1730 * The caller has already made sure it doesn't already have a lease. 1731 * 1732 * @returns Pointer to the lease if found, NULL+log if not found. 1733 * @param IPv4Addr The IPv4 address. 1734 * @param pMacAddress The MAC address. 1735 */ 1736 VBoxNetDhcpLease *VBoxNetDhcp::newLease(PCRTNETBOOTP pDhcpMsg, size_t cb) 1737 { 1738 RTMAC const MacAddr = pDhcpMsg->bp_chaddr.Mac; 1739 RTTIMESPEC Now; 1740 RTTimeNow(&Now); 1741 1742 /* 1743 * Search the possible leases. 1744 * 1745 * We'll try do all the searches in one pass, that is to say, perfect 1746 * match, old lease, and next free/expired lease. 1747 */ 1748 VBoxNetDhcpLease *pBest = NULL; 1749 VBoxNetDhcpLease *pOld = NULL; 1750 VBoxNetDhcpLease *pFree = NULL; 1751 1752 size_t cLeases = m_Leases.size(); 1753 for (size_t i = 0; i < cLeases; i++) 1754 { 1755 VBoxNetDhcpLease *pCur = &m_Leases[i]; 1756 1757 /* Skip it if no configuration, that means its not in the current config. */ 1758 if (!pCur->m_pCfg) 1759 continue; 1760 1761 /* best */ 1762 if ( pCur->isOneSpecificClient() 1763 && pCur->m_pCfg->matchesMacAddress(&MacAddr)) 1764 { 1765 if ( !pBest 1766 || pBest->m_pCfg->m_MacAddresses.size() < pCur->m_pCfg->m_MacAddresses.size()) 1767 pBest = pCur; 1768 } 1769 1770 /* old lease */ 1771 if ( pCur->m_MacAddress.au16[0] == MacAddr.au16[0] 1772 && pCur->m_MacAddress.au16[1] == MacAddr.au16[1] 1773 && pCur->m_MacAddress.au16[2] == MacAddr.au16[2]) 1774 { 1775 if ( !pOld 1776 || RTTimeSpecGetSeconds(&pCur->m_ExpireTime) > RTTimeSpecGetSeconds(&pFree->m_ExpireTime)) 1777 pOld = pCur; 1778 } 1779 1780 /* expired lease */ 1781 if (!pCur->isInUse(&Now)) 1782 { 1783 if ( !pFree 1784 || RTTimeSpecGetSeconds(&pCur->m_ExpireTime) < RTTimeSpecGetSeconds(&pFree->m_ExpireTime)) 1785 pFree = pCur; 1786 } 1787 } 1788 1789 VBoxNetDhcpLease *pNew = pBest; 1790 if (!pNew) 1791 pNew = pOld; 1792 if (!pNew) 1793 pNew = pFree; 1794 if (!pNew) 1795 { 1796 debugPrint(0, true, "No more leases."); 1797 return NULL; 1798 } 1799 1800 /* 1801 * Init the lease. 1802 */ 1803 pNew->m_MacAddress = MacAddr; 1804 pNew->m_xid = pDhcpMsg->bp_xid; 1805 /** @todo extract the client id. */ 1806 1807 return pNew; 1808 } 1809 1810 1811 /** 1812 * Finds an option. 1813 * 1814 * @returns On success, a pointer to the first byte in the option data (no none 1815 * then it'll be the byte following the 0 size field) and *pcbOpt set 1816 * to the option length. 1817 * On failure, NULL is returned and *pcbOpt unchanged. 1818 * 1819 * @param uOption The option to search for. 1820 * @param pDhcpMsg The DHCP message. 1821 * @param cb The size of the message. 1822 * @param pcbOpt Where to store the option size size. Optional. Note 1823 * that this is adjusted if the option length is larger 1824 * than the message buffer. 1825 */ 1826 /* static */ const uint8_t * 1827 VBoxNetDhcp::findOption(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cb, size_t *pcbOpt) 1828 { 1829 Assert(uOption != RTNET_DHCP_OPT_PAD); 1830 1831 /* 1832 * Validate the DHCP bits and figure the max size of the options in the vendor field. 1833 */ 1834 if (cb <= RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts)) 1835 return NULL; 1836 if (pDhcpMsg->bp_vend.Dhcp.dhcp_cookie != RT_H2N_U32_C(RTNET_DHCP_COOKIE)) 1837 return NULL; 1838 size_t cbLeft = cb - RT_UOFFSETOF(RTNETBOOTP, bp_vend.Dhcp.dhcp_opts); 1839 if (cbLeft > RTNET_DHCP_OPT_SIZE) 1840 cbLeft = RTNET_DHCP_OPT_SIZE; 1841 1842 /* 1843 * Search the vendor field. 1844 */ 1845 bool fExtended = false; 1846 uint8_t const *pb = &pDhcpMsg->bp_vend.Dhcp.dhcp_opts[0]; 1847 while (pb && cbLeft > 0) 1848 { 1849 uint8_t uCur = *pb; 1850 if (uCur == RTNET_DHCP_OPT_PAD) 1851 { 1852 cbLeft--; 1853 pb++; 1854 } 1855 else if (cbLeft <= 1) 1856 break; 1857 else 1858 { 1859 size_t cbCur = pb[1]; 1860 if (cbCur > cbLeft - 2) 1861 cbCur = cbLeft - 2; 1862 if (uCur == uOption) 1863 { 1864 if (pcbOpt) 1865 *pcbOpt = cbCur; 1866 return pb+2; 1867 } 1868 pb += cbCur + 2; 1869 cbLeft -= cbCur - 2; 1870 } 1871 } 1872 1873 /** @todo search extended dhcp option field(s) when present */ 1874 1875 return NULL; 1876 } 1877 1878 1879 /** 1880 * Locates an option with an IPv4 address in the DHCP message. 1881 * 1882 * @returns true and *pIpv4Addr if found, false if not. 1883 * 1884 * @param uOption The option to find. 1885 * @param pDhcpMsg The DHCP message. 1886 * @param cb The size of the message. 1887 * @param pIPv4Addr Where to put the address. 1888 */ 1889 /* static */ bool 1890 VBoxNetDhcp::findOptionIPv4Addr(uint8_t uOption, PCRTNETBOOTP pDhcpMsg, size_t cb, PRTNETADDRIPV4 pIPv4Addr) 1891 { 1892 size_t cbOpt; 1893 uint8_t const *pbOpt = findOption(uOption, pDhcpMsg, cb, &cbOpt); 1894 if (pbOpt) 1895 { 1896 if (cbOpt >= sizeof(RTNETADDRIPV4)) 1897 { 1898 *pIPv4Addr = *(PCRTNETADDRIPV4)pbOpt; 1899 return true; 1900 } 1901 } 1902 return false; 1903 } 1904 1905 1906 /** 1907 * Print debug message depending on the m_cVerbosity level. 1908 * 1909 * @param iMinLevel The minimum m_cVerbosity level for this message. 1910 * @param fMsg Whether to dump parts for the current DHCP message. 1911 * @param pszFmt The message format string. 1912 * @param ... Optional arguments. 1913 */ 1914 inline void VBoxNetDhcp::debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const 1915 { 1916 if (iMinLevel <= m_cVerbosity) 1917 { 1918 va_list va; 1919 va_start(va, pszFmt); 1920 debugPrintV(iMinLevel, fMsg, pszFmt, va); 1921 va_end(va); 1922 } 751 1923 } 752 1924 … … 773 1945 && m_pCurMsg) 774 1946 { 775 /* XXX: export this to debugPrinfDhcpMsg or variant and other method export776 * to base class777 */778 1947 const char *pszMsg = m_uCurMsgType != UINT8_MAX ? debugDhcpName(m_uCurMsgType) : ""; 779 1948 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: debug: %8s chaddr=%.6Rhxs ciaddr=%d.%d.%d.%d yiaddr=%d.%d.%d.%d siaddr=%d.%d.%d.%d xid=%#x\n", … … 834 2003 * Instantiate the DHCP server and hand it the options. 835 2004 */ 836 HRESULT hrc = com::Initialize();837 Assert(!FAILED(hrc));838 839 2005 VBoxNetDhcp *pDhcp = new VBoxNetDhcp(); 840 2006 if (!pDhcp) … … 846 2012 if (rc) 847 2013 return rc; 848 849 pDhcp->init();850 2014 851 2015 /* -
trunk/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp
r46962 r46969 1 1 /* $Id$ */ 2 2 /** @file 3 * VBoxNetBaseService - Base Service class for connecting to IntNet. 4 */ 3 * VBoxNetDHCP - DHCP Service for connecting to IntNet. 4 */ 5 /** @todo r=bird: Cut&Past rules... Please fix DHCP refs! */ 5 6 6 7 /* … … 21 22 #define LOG_GROUP LOG_GROUP_NET_SERVICE 22 23 23 #include <VBox/com/com.h>24 #include <VBox/com/listeners.h>25 #include <VBox/com/string.h>26 #include <VBox/com/Guid.h>27 #include <VBox/com/array.h>28 #include <VBox/com/ErrorInfo.h>29 #include <VBox/com/errorprint.h>30 #include <VBox/com/EventQueue.h>31 #include <VBox/com/VirtualBox.h>32 33 24 #include <iprt/alloca.h> 34 25 #include <iprt/buildconfig.h> … … 39 30 #include <iprt/param.h> 40 31 #include <iprt/path.h> 41 #include <iprt/process.h>42 32 #include <iprt/stream.h> 43 33 #include <iprt/string.h> 44 34 #include <iprt/time.h> 45 35 #include <iprt/mem.h> 46 #include <iprt/message.h>47 36 48 37 #include <VBox/sup.h> … … 55 44 #include <string> 56 45 57 #include <VBox/err.h>58 46 #include <VBox/log.h> 59 47 … … 70 58 * Structures and Typedefs * 71 59 *******************************************************************************/ 72 73 /*******************************************************************************74 * Global Variables *75 *******************************************************************************/76 /* Commonly used options for network configuration */77 60 static RTGETOPTDEF g_aGetOptDef[] = 78 61 { … … 86 69 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 87 70 }; 88 89 90 71 VBoxNetBaseService::VBoxNetBaseService() 91 72 { 92 int rc = RTCritSectInit(&m_csThis); 93 AssertRC(rc); 94 /* numbers from DrvIntNet */ 95 m_cbSendBuf = 128 * _1K; 96 m_cbRecvBuf = 256 * _1K; 97 m_hIf = INTNET_HANDLE_INVALID; 98 m_pIfBuf = NULL; 99 100 m_cVerbosity = 0; 101 m_Name = "VBoxNetNAT"; 102 m_Network = "intnet"; 103 104 for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i) 105 m_vecOptionDefs.push_back(&g_aGetOptDef[i]); 106 107 HRESULT hrc = virtualbox.createLocalObject(CLSID_VirtualBox); 108 if (FAILED(hrc)) 109 RTMsgError("Failed to create the VirtualBox object!"); 110 } 111 112 73 int rc = RTCritSectInit(&m_csThis); 74 AssertRC(rc); 75 } 113 76 VBoxNetBaseService::~VBoxNetBaseService() 114 77 { … … 136 99 } 137 100 138 139 101 int VBoxNetBaseService::init() 140 102 { 103 /* numbers from DrvIntNet */ 104 m_cbSendBuf = 128 * _1K; 105 m_cbRecvBuf = 256 * _1K; 106 m_hIf = INTNET_HANDLE_INVALID; 107 m_pIfBuf = NULL; 108 109 m_cVerbosity = 0; 110 m_Name = "VBoxNetNAT"; 111 m_Network = "intnet"; 112 for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i) 113 m_vecOptionDefs.push_back(&g_aGetOptDef[i]); 141 114 return VINF_SUCCESS; 142 115 } 143 144 145 116 /** 146 117 * Parse the arguments. … … 217 188 218 189 case 'h': 219 RTPrintf(" %sVersion %s\n"190 RTPrintf("VBoxNetDHCP Version %s\n" 220 191 "(C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n" 221 192 "All rights reserved.\n" 222 193 "\n" 223 "Usage: %s<options>\n"194 "Usage: VBoxNetDHCP <options>\n" 224 195 "\n" 225 196 "Options:\n", 226 RTProcShortName(),227 RTProcShortName(),228 RTProcShortName(),229 197 RTBldCfgVersion()); 230 198 for (unsigned int i = 0; i < m_vecOptionDefs.size(); i++) … … 247 215 return rc; 248 216 } 249 250 217 251 218 int VBoxNetBaseService::tryGoOnline(void) … … 350 317 } 351 318 352 353 319 void VBoxNetBaseService::shutdown(void) 354 320 { 355 321 } 356 357 322 358 323 int VBoxNetBaseService::waitForIntNetEvent(int cMillis) … … 412 377 } 413 378 414 415 379 /** 416 380 * Print debug message depending on the m_cVerbosity level. 417 381 * 418 382 * @param iMinLevel The minimum m_cVerbosity level for this message. 419 * @param fMsg Whether to dump parts for the current service message. 383 * @param fMsg Whether to dump parts for the current DHCP message. 384 * @param pszFmt The message format string. 385 * @param ... Optional arguments. 386 */ 387 inline void VBoxNetBaseService::debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const 388 { 389 if (iMinLevel <= m_cVerbosity) 390 { 391 va_list va; 392 va_start(va, pszFmt); 393 debugPrintV(iMinLevel, fMsg, pszFmt, va); 394 va_end(va); 395 } 396 } 397 398 399 /** 400 * Print debug message depending on the m_cVerbosity level. 401 * 402 * @param iMinLevel The minimum m_cVerbosity level for this message. 403 * @param fMsg Whether to dump parts for the current DHCP message. 420 404 * @param pszFmt The message format string. 421 405 * @param va Optional arguments. … … 427 411 va_list vaCopy; /* This dude is *very* special, thus the copy. */ 428 412 va_copy(vaCopy, va); 429 RTStrmPrintf(g_pStdErr, "%s: %s: %N\n", 430 RTProcShortName(), 431 iMinLevel >= 2 ? "debug" : "info", 432 pszFmt, 433 &vaCopy); 413 RTStrmPrintf(g_pStdErr, "VBoxNetDHCP: %s: %N\n", iMinLevel >= 2 ? "debug" : "info", pszFmt, &vaCopy); 434 414 va_end(vaCopy); 435 415 } 436 416 437 417 } 438 439 418 440 419 PRTGETOPTDEF VBoxNetBaseService::getOptionsPtr() -
trunk/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h
r46962 r46969 18 18 #ifndef ___VBoxNetBaseService_h___ 19 19 #define ___VBoxNetBaseService_h___ 20 21 20 #include <iprt/critsect.h> 22 21 class VBoxNetBaseService … … 33 32 int sendBufferOnWire(PCINTNETSEG pSg, int cSg, size_t cbBuffer); 34 33 void flushWire(); 35 36 34 virtual void usage(void) = 0; 37 virtual int run(void) = 0; 35 virtual void run(void) = 0; 36 virtual int init(void); 38 37 virtual int parseOpt(int rc, const RTGETOPTUNION& getOptVal) = 0; 39 38 40 virtual int init(void); 41 42 /* VirtualBox instance */ 43 ComPtr<IVirtualBox> virtualbox; 44 45 protected: 46 /** 47 * Print debug message depending on the m_cVerbosity level. 48 * 49 * @param iMinLevel The minimum m_cVerbosity level for this message. 50 * @param fMsg Whether to dump parts for the current DHCP message. 51 * @param pszFmt The message format string. 52 * @param ... Optional arguments. 53 */ 54 void debugPrint(int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const 55 { 56 if (iMinLevel <= m_cVerbosity) 57 { 58 va_list va; 59 va_start(va, pszFmt); 60 debugPrintV(iMinLevel, fMsg, pszFmt, va); 61 va_end(va); 62 } 63 } 64 65 virtual void debugPrintV(int32_t iMinLevel, bool fMsg, const char *pszFmt, va_list va) const; 66 39 inline void debugPrint( int32_t iMinLevel, bool fMsg, const char *pszFmt, ...) const; 40 void debugPrintV(int32_t iMinLevel, bool fMsg, const char *pszFmt, va_list va) const; 41 public: 67 42 /** @name The server configuration data members. 68 43 * @{ */ … … 74 49 RTNETADDRIPV4 m_Ipv4Address; 75 50 RTNETADDRIPV4 m_Ipv4Netmask; 51 /* cs for syncing */ 52 RTCRITSECT m_csThis; 76 53 /** @} */ 77 54 /** @name The network interface … … 89 66 private: 90 67 PRTGETOPTDEF getOptionsPtr(); 91 92 /* cs for syncing */93 RTCRITSECT m_csThis;94 95 68 /** @} */ 96 69 };
Note:
See TracChangeset
for help on using the changeset viewer.