VirtualBox

Changeset 46969 in vbox


Ignore:
Timestamp:
Jul 4, 2013 6:35:01 AM (11 years ago)
Author:
vboxsync
Message:

backed out r86967,r86968,r86969,r86970,r86971,r86972,r86973,r86975,r86976.
will fix build locally.

Location:
trunk
Files:
4 deleted
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/settings.h

    r46959 r46969  
    286286typedef std::list<MachineRegistryEntry> MachinesRegistry;
    287287
    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 VmNameSlotKey
    294 {
    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) const
    300     {
    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 
    311288struct DHCPServer
    312289{
     
    317294    com::Utf8Str    strNetworkName,
    318295                    strIPAddress,
     296                    strIPNetworkMask,
    319297                    strIPLower,
    320298                    strIPUpper;
    321299    bool            fEnabled;
    322     std::map<DhcpOpt_T, com::Utf8Str>  GlobalDhcpOptions;
    323     VmSlot2OptionsMap VmSlot2OptionsM;
    324300};
    325301typedef std::list<DHCPServer> DHCPServersList;
     
    361337    void readMachineRegistry(const xml::ElementNode &elmMachineRegistry);
    362338    void readDHCPServers(const xml::ElementNode &elmDHCPServers);
    363     void readDhcpOptions(DhcpOptionMap& map, const xml::ElementNode& options);
    364339    void readNATNetworks(const xml::ElementNode &elmNATNetworks);
    365340
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp

    r46967 r46969  
    4040#include "VBoxManage.h"
    4141
    42 #include <string>
    43 #include <vector>
    44 #include <map>
    45 
    4642#ifndef VBOX_ONLY_DOCS
    4743using namespace com;
     
    5349    OP_MODIFY
    5450} 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 VmNameSlotKey
    64 {
    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) const
    73     {
    74         if (VmName == that.VmName)
    75             return u8Slot < that.u8Slot;
    76         else
    77             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;
    8651
    8752static const RTGETOPTDEF g_aDHCPIPOptions[]
     
    10772        { "-enable",            'e', RTGETOPT_REQ_NOTHING },    // deprecated
    10873        { "--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
    11675      };
    11776
     
    12382    int index = iStart;
    12483    HRESULT rc;
    125     bool fOptionsRead = false;
    126     bool fVmOptionRead = false;
    127 
    128     const char *pszVmName = NULL;
     84
    12985    const char *pNetName = NULL;
    13086    const char *pIfName = NULL;
     
    13389    const char * pLowerIp = NULL;
    13490    const char * pUpperIp = NULL;
    135 
    136     uint8_t u8OptId = -1;
    137     uint8_t u8Slot = -1;
    138 
    13991    int enable = -1;
    140 
    141     DhcpOptMap GlobalDhcpOptions;
    142     VmSlot2OptionsM VmSlot2Options;
    143     VmConfigs       VmConfigs2Delete;
    14492
    14593    int c;
     
    228176                return errorSyntax(USAGE_DHCPSERVER, "unhandled parameter: %s", ValueUnion.psz);
    229177            break;
    230 
    231             case 'o': // --options
    232                 {
    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-name
    249                 {
    250                     if (fVmOptionRead)
    251                         return errorSyntax(USAGE_DHCPSERVER,
    252                                            "previous vm option edition wasn't finished");
    253                     else
    254                         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': // --slot
    261                 {
    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': // --id
    271                 {
    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': // --value
    281                 {
    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 (   fVmOptionRead
    290                         && 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 value
    304 
    305178            default:
    306179                if (c > 0)
     
    323196        return errorSyntax(USAGE_DHCPSERVER, "You need to specify either --netname or --ifname to identify the DHCP server");
    324197
    325     if(   enmCode != OP_REMOVE
    326        && GlobalDhcpOptions.size() == 0
    327        && VmSlot2Options.size() == 0)
     198    if(enmCode != OP_REMOVE)
    328199    {
    329200        if(enable < 0 || pIp || pNetmask || pLowerIp || pUpperIp)
     
    383254        if (pIp || pNetmask || pLowerIp || pUpperIp)
    384255        {
    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()));
    390257            if(FAILED(rc))
    391258                return errorArgument("Failed to set configuration");
     
    395262        {
    396263            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             }
    430264        }
    431265    }
  • trunk/src/VBox/Main/Makefile.kmk

    r46959 r46969  
    335335        src-server/BIOSSettingsImpl.cpp \
    336336        src-server/DHCPServerImpl.cpp \
    337         src-server/NetworkServiceRunner.cpp \
     337        src-server/DHCPServerRunner.cpp \
    338338        src-server/NATNetworkImpl.cpp \
     339        $(if $(VBOX_WITH_NAT_SERVICE),src-server/NATNetworkServiceRunner.cpp,) \
    339340        src-server/GuestOSTypeImpl.cpp \
    340341        src-server/HostImpl.cpp \
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r46959 r46969  
    14661466  </interface>
    14671467
    1468   <enum
    1469       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  
    15361468  <interface
    15371469    name="IDHCPServer" extends="$unknown"
    1538     uuid="ff0774c5-1f62-4bc3-919c-7fc942bf1d25"
     1470    uuid="6cfe387c-74fb-4ca7-bff6-973bec8af7a3"
    15391471    wsmap="managed"
    15401472    >
     
    15451477      <link to="IVirtualBox::DHCPServers"/> attribute.
    15461478    </desc>
    1547     <!-- We want to keep our "real" servers updated about configuration changes -->
    1548     <attribute name="eventSource" type="IEventSource" readonly="yes"/>
     1479
    15491480    <attribute name="enabled" type="boolean">
    15501481      <desc>
     
    15821513      </desc>
    15831514    </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 settings
    1597          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 address
    1602          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 because
    1606          of import/export
    1607          
    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 in
    1613               VM configuration files. And we haven't got the attachment type for
    1614               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>
    16401515
    16411516    <method name="setConfiguration">
     
    81638038  <interface
    81648039    name="IHost" extends="$unknown"
    8165     uuid="a6107246-f939-42c4-82b6-8aca40327b6d"
     8040    uuid="30678943-32df-4830-b413-931b25ac86a0"
    81668041    wsmap="managed"
    81678042    >
     
    82248099    <attribute name="networkInterfaces" type="IHostNetworkInterface" safearray="yes" readonly="yes">
    82258100      <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>
    82388101    </attribute>
    82398102
  • trunk/src/VBox/Main/include/DHCPServerImpl.h

    r46959 r46969  
    3030{
    3131    struct DHCPServer;
    32     struct VmNameSlotKey;
    3332}
    34 #ifdef RT_OS_WINDOWS
    35 # define DHCP_EXECUTABLE_NAME "VBoxNetDHCP.exe"
    36 #else
    37 # define DHCP_EXECUTABLE_NAME "VBoxNetDHCP"
    38 #endif
    39 
    40 class DHCPServerRunner: public NetworkServiceRunner
    41 {
    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) pair
    49  *  (vm-name, slot) <----> (MAC)
    50  * 
    51  *  but for client configuration, when server will have MACs at hand, it'd be
    52  *  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 in
    57  *  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 
    6933
    7034class ATL_NO_VTABLE DHCPServer :
     
    10670    STDMETHOD(COMGETTER(UpperIP))(BSTR *aIPAddress);
    10771
    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 
    11872    STDMETHOD(SetConfiguration)(IN_BSTR aIPAddress, IN_BSTR aNetworkMask, IN_BSTR aFromIPAddress, IN_BSTR aToIPAddress);
    11973
     
    13286
    13387        Bstr IPAddress;
     88        Bstr networkMask;
    13489        Bstr lowerIP;
    13590        Bstr upperIP;
     91        BOOL enabled;
    13692
    137         BOOL enabled;
    13893        DHCPServerRunner dhcp;
    139        
    140         DhcpOptionMap GlobalDhcpOptions;
    141         VmSlot2OptionsMap VmSlot2Options;
    14294    } m;
    143    
    144     DhcpOptionMap& findOptMapByVmNameSlot(const com::Utf8Str& aVmName,
    145                                    LONG Slot);
     95
    14696};
    14797
  • trunk/src/VBox/Main/include/HostImpl.h

    r46959 r46969  
    6262    STDMETHOD(COMGETTER(USBDeviceFilters))(ComSafeArrayOut(IHostUSBDeviceFilter *, aUSBDeviceFilters));
    6363    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 
    6864    STDMETHOD(COMGETTER(ProcessorCount))(ULONG *count);
    6965    STDMETHOD(COMGETTER(ProcessorOnlineCount))(ULONG *count);
     
    151147    HRESULT updateNetIfList();
    152148
    153 #ifndef RT_OS_WINDOWS
    154     HRESULT parseResolvConf();
    155 #else
    156     HRESULT fetchNameResolvingInformation();
    157 #endif
    158 
    159149#ifdef VBOX_WITH_RESOURCE_USAGE_API
    160150    void registerMetrics(PerformanceCollector *aCollector);
  • trunk/src/VBox/Main/include/NATNetworkImpl.h

    r46959 r46969  
    3737}
    3838
    39 #ifdef RT_OS_WINDOWS
    40 # define NATSR_EXECUTABLE_NAME "VBoxNetLwipNAT.exe"
    41 #else
    42 # define NATSR_EXECUTABLE_NAME "VBoxNetLwipNAT"
    43 #endif
    44 
    45 class NATNetworkServiceRunner: public NetworkServiceRunner
    46 {
    47 public:
    48     NATNetworkServiceRunner(): NetworkServiceRunner(NATSR_EXECUTABLE_NAME){}
    49     virtual ~NATNetworkServiceRunner(){}
    50 };
    5139
    5240class ATL_NO_VTABLE NATNetwork :
  • trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp

    r46959 r46969  
    115115#endif /* VBOX_WITH_NETFLT */
    116116
    117 #include "NetworkServiceRunner.h"
     117#include "DHCPServerRunner.h"
    118118#include "BusAssignmentManager.h"
    119119#ifdef VBOX_WITH_EXTPACK
  • trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp

    r46961 r46969  
    1818 */
    1919
    20 #include "NetworkServiceRunner.h"
     20#include "DHCPServerRunner.h"
    2121#include "DHCPServerImpl.h"
    2222#include "AutoCaller.h"
     
    2525#include <iprt/cpp/utils.h>
    2626
    27 #include <VBox/com/array.h>
    2827#include <VBox/settings.h>
    2928
     
    3837}
    3938
    40 
    4139DHCPServer::~DHCPServer()
    4240{
    4341}
    4442
    45 
    4643HRESULT DHCPServer::FinalConstruct()
    4744{
     
    4946}
    5047
    51 
    5248void DHCPServer::FinalRelease()
    5349{
     
    5652    BaseFinalRelease();
    5753}
    58 
    5954
    6055void DHCPServer::uninit()
     
    6863}
    6964
    70 
    7165HRESULT DHCPServer::init(VirtualBox *aVirtualBox, IN_BSTR aName)
    7266{
     
    8175    unconst(mName) = aName;
    8276    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";
    8478    m.enabled = FALSE;
    85    
    8679    m.lowerIP = "0.0.0.0";
    8780    m.upperIP = "0.0.0.0";
     
    9285    return S_OK;
    9386}
    94 
    9587
    9688HRESULT DHCPServer::init(VirtualBox *aVirtualBox,
     
    10698    unconst(mName) = data.strNetworkName;
    10799    m.IPAddress = data.strIPAddress;
     100    m.networkMask = data.strIPNetworkMask;
    108101    m.enabled = data.fEnabled;
    109102    m.lowerIP = data.strIPLower;
    110103    m.upperIP = data.strIPUpper;
    111104
    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 
    121105    autoInitSpan.setSucceeded();
    122106
    123107    return S_OK;
    124108}
    125 
    126109
    127110HRESULT DHCPServer::saveSettings(settings::DHCPServer &data)
     
    134117    data.strNetworkName = mName;
    135118    data.strIPAddress = m.IPAddress;
    136 
     119    data.strIPNetworkMask = m.networkMask;
    137120    data.fEnabled = !!m.enabled;
    138121    data.strIPLower = m.lowerIP;
    139122    data.strIPUpper = m.upperIP;
    140123
    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}
    152126
    153127STDMETHODIMP DHCPServer::COMGETTER(NetworkName) (BSTR *aName)
     
    163137}
    164138
    165 
    166139STDMETHODIMP DHCPServer::COMGETTER(Enabled) (BOOL *aEnabled)
    167140{
     
    175148    return S_OK;
    176149}
    177 
    178150
    179151STDMETHODIMP DHCPServer::COMSETTER(Enabled) (BOOL aEnabled)
     
    193165}
    194166
    195 
    196167STDMETHODIMP DHCPServer::COMGETTER(IPAddress) (BSTR *aIPAddress)
    197168{
     
    206177}
    207178
    208 
    209179STDMETHODIMP DHCPServer::COMGETTER(NetworkMask) (BSTR *aNetworkMask)
    210180{
     
    214184    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    215185
    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}
    221190
    222191STDMETHODIMP DHCPServer::COMGETTER(LowerIP) (BSTR *aIPAddress)
     
    226195    AutoCaller autoCaller(this);
    227196    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    228    
     197
    229198    m.lowerIP.cloneTo(aIPAddress);
    230199
     
    232201}
    233202
    234 
    235203STDMETHODIMP DHCPServer::COMGETTER(UpperIP) (BSTR *aIPAddress)
    236204{
     
    244212    return S_OK;
    245213}
    246 
    247214
    248215STDMETHODIMP DHCPServer::SetConfiguration (IN_BSTR aIPAddress, IN_BSTR aNetworkMask, IN_BSTR aLowerIP, IN_BSTR aUpperIP)
     
    258225    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    259226    m.IPAddress = aIPAddress;
    260     m.GlobalDhcpOptions[DhcpOpt_SubnetMask] = aNetworkMask;
    261 
     227    m.networkMask = aNetworkMask;
    262228    m.lowerIP = aLowerIP;
    263229    m.upperIP = aUpperIP;
     
    269235}
    270236
    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 
    464237STDMETHODIMP DHCPServer::Start(IN_BSTR aNetworkName, IN_BSTR aTrunkName, IN_BSTR aTrunkType)
    465238{
     
    467240    if (!m.enabled)
    468241        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);
    473244    Bstr tmp(aTrunkName);
    474 
    475245    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
    480250    char strMAC[32];
    481251    Guid guid;
    482252    guid.create();
    483253    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
    492269    return RT_FAILURE(m.dhcp.start()) ? E_FAIL : S_OK;
    493270    //m.dhcp.detachFromServer(); /* need to do this to avoid server shutdown on runner destruction */
    494271}
    495272
    496 
    497273STDMETHODIMP DHCPServer::Stop (void)
    498274{
    499275    return RT_FAILURE(m.dhcp.stop()) ? E_FAIL : S_OK;
    500276}
    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  
    134134#include <iprt/mem.h>
    135135#include <iprt/system.h>
    136 #ifndef RT_OS_WINDOWS
     136#ifdef RT_OS_SOLARIS
    137137# include <iprt/path.h>
    138 #endif
    139 #ifdef RT_OS_SOLARIS
    140138# include <iprt/ctype.h>
    141139#endif
     
    217215
    218216    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 some
    225      *  (~1h?, 5 min?) period, this values should be refetched from host syetem.
    226      */
    227217};
    228218
    229 #ifndef RT_OS_WINDOWS
    230 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_OS2
    237     /*
    238      * This was in an old Slirp code:
    239      * IBM's "Technical Document # - 16070238", clearly says \MPTN\ETC\RESOLV2
    240      * 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 # else
    253     strcmp(g_aszResolvConf, "/etc/resolv.conf");
    254 # endif   
    255     return g_aszResolvConf;
    256 }
    257 #endif
    258219
    259220////////////////////////////////////////////////////////////////////////////////
     
    836797#endif
    837798}
    838 
    839 
    840 /**
    841  * This method return the list of registered name servers
    842  */
    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 host
    851  */
    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 
    866799
    867800STDMETHODIMP Host::COMGETTER(USBDeviceFilters)(ComSafeArrayOut(IHostUSBDeviceFilter*, aUSBDeviceFilters))
  • trunk/src/VBox/Main/src-server/NATNetworkImpl.cpp

    r46959 r46969  
    1818 */
    1919
    20 #include "NetworkServiceRunner.h"
     20#include "DHCPServerRunner.h"
    2121#include "DHCPServerImpl.h"
    2222#include "NATNetworkImpl.h"
     
    3535#include "VBoxEvents.h"
    3636
     37#include "NATNetworkServiceRunner.h"
    3738#include "VirtualBoxImpl.h"
    3839
     
    631632
    632633    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    }
    640656
    641657    if (m->fNeedDhcpServer)
     
    666682                  return E_FAIL;
    667683                /* breakthrough */
    668 
     684            case S_OK:
    669685            {
    670686                LogFunc(("gateway: %s, dhcpserver:%s, dhcplowerip:%s, dhcpupperip:%s\n",
     
    673689                         Utf8Str(m->IPv4DhcpServerLowerIp.raw()).c_str(),
    674690                         Utf8Str(m->IPv4DhcpServerUpperIp.raw()).c_str()));
    675 
    676                 m->dhcpServer->AddGlobalOption(DhcpOpt_Router, m->IPv4Gateway.raw());
     691                         
    677692
    678693                rc = m->dhcpServer->SetEnabled(true);
    679 
    680694                BSTR dhcpip = NULL;
    681695                BSTR netmask = NULL;
    682696                BSTR lowerip = NULL;
    683697                BSTR upperip = NULL;
    684 
    685698                m->IPv4DhcpServer.cloneTo(&dhcpip);
    686699                m->IPv4NetworkMask.cloneTo(&netmask);
     700               
    687701                m->IPv4DhcpServerLowerIp.cloneTo(&lowerip);
    688702                m->IPv4DhcpServerUpperIp.cloneTo(&upperip);
     
    691705                                                     lowerip,
    692706                                                     upperip);
     707            break;
    693708            }
    694             case S_OK:
    695                 break;
    696                
    697             default:
    698                 return E_FAIL;
     709           
     710        default:
     711            return E_FAIL;
    699712        }
    700713
     
    715728#else
    716729    NOREF(aTrunkType);
    717     ReturnComNotImplemented();
     730    return E_NOTIMPL;
    718731#endif
    719732}
     
    728741    }
    729742    else return E_FAIL;
     743       
    730744#else
    731     ReturnComNotImplemented();
     745    return E_NOTIMPL;
    732746#endif
    733747}
     
    804818        m->IPv4DhcpServerLowerIp = aszDhcpLowerIp;
    805819        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));
    812821    }
    813822    /* we need IPv4NetworkMask for NAT's gw service start */
  • trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp

    r46959 r46969  
    6161#include "SystemPropertiesImpl.h"
    6262#include "GuestOSTypeImpl.h"
    63 #include "NetworkServiceRunner.h"
     63#include "DHCPServerRunner.h"
    6464#include "DHCPServerImpl.h"
    6565#include "NATNetworkImpl.h"
  • trunk/src/VBox/Main/src-server/xpcom/server.cpp

    r46959 r46969  
    6767#include "BandwidthControlImpl.h"
    6868#include "BandwidthGroupImpl.h"
    69 #include "NetworkServiceRunner.h"
     69#include "DHCPServerRunner.h"
    7070#include "DHCPServerImpl.h"
    7171#include "GuestOSTypeImpl.h"
  • trunk/src/VBox/Main/xml/Settings.cpp

    r46959 r46969  
    13021302            if (    (pelmServer->getAttributeValue("networkName", srv.strNetworkName))
    13031303                 && (pelmServer->getAttributeValue("IPAddress", srv.strIPAddress))
    1304                     && (pelmServer->getAttributeValue("networkMask", srv.GlobalDhcpOptions[DhcpOpt_SubnetMask]))
     1304                 && (pelmServer->getAttributeValue("networkMask", srv.strIPNetworkMask))
    13051305                 && (pelmServer->getAttributeValue("lowerIP", srv.strIPLower))
    13061306                 && (pelmServer->getAttributeValue("upperIP", srv.strIPUpper))
    13071307                 && (pelmServer->getAttributeValue("enabled", srv.fEnabled))
    13081308               )
    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                 }
    13291309                llDhcpServers.push_back(srv);
    1330             }
    13311310            else
    13321311                throw ConfigFileError(this, pelmServer, N_("Required DHCPServer/@networkName, @IPAddress, @networkMask, @lowerIP, @upperIP or @enabled attribute is missing"));
    13331312        }
    13341313    }
    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 
    13571314}
    13581315
     
    14891446#endif
    14901447        srv.strIPAddress = "192.168.56.100";
    1491         srv.GlobalDhcpOptions[DhcpOpt_SubnetMask] = "255.255.255.0";
     1448        srv.strIPNetworkMask = "255.255.255.0";
    14921449        srv.strIPLower = "192.168.56.101";
    14931450        srv.strIPUpper = "192.168.56.254";
     
    15321489        const DHCPServer &d = *it;
    15331490        xml::ElementNode *pelmThis = pelmDHCPServers->createChild("DHCPServer");
    1534         DhcpOptConstIterator itOpt;
    1535         itOpt = d.GlobalDhcpOptions.find(DhcpOpt_SubnetMask);
    1536 
    15371491        pelmThis->setAttribute("networkName", d.strNetworkName);
    15381492        pelmThis->setAttribute("IPAddress", d.strIPAddress);
    1539         if (itOpt != d.GlobalDhcpOptions.end())
    1540             pelmThis->setAttribute("networkMask", itOpt->second);
     1493        pelmThis->setAttribute("networkMask", d.strIPNetworkMask);
    15411494        pelmThis->setAttribute("lowerIP", d.strIPLower);
    15421495        pelmThis->setAttribute("upperIP", d.strIPUpper);
    15431496        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    }
    15931498
    15941499    /* TODO: bump main version ? */
  • trunk/src/VBox/NetworkServices/DHCP/Makefile.kmk

    r46968 r46969  
    3333# Hardened VBoxNetDHCP.
    3434#
    35 VBoxNetDHCPHardened_TEMPLATE = VBOXMAINCLIENTEXE
     35VBoxNetDHCPHardened_TEMPLATE = VBOXR3HARDENEDEXE
    3636VBoxNetDHCPHardened_SOURCES = VBoxNetDHCPHardened.cpp
    3737VBoxNetDHCPHardened_NAME = VBoxNetDHCP
     
    4141# VBoxNetDHCP
    4242#
    43 VBoxNetDHCP_TEMPLATE = VBOXMAINCLIENTEXE
    44 #VBoxNetDHCP_TEMPLATE := VBOXR3$(if-expr defined(VBOX_WITH_HARDENING),,EXE)
     43VBoxNetDHCP_TEMPLATE =
     44VBoxNetDHCP_TEMPLATE := VBOXR3$(if-expr defined(VBOX_WITH_HARDENING),,EXE)
    4545VBoxNetDHCP_SOURCES = \
    4646        VBoxNetDHCP.cpp \
    47         Config.cpp \
    4847        ../NetLib/VBoxNetIntIf.cpp \
    4948        ../NetLib/VBoxNetUDP.cpp \
    50         ../NetLib/VBoxNetARP.cpp \
    51         ../NetLib/VBoxNetBaseService.cpp
     49        ../NetLib/VBoxNetARP.cpp
    5250VBoxNetDHCP_LIBS = \
    5351        $(LIB_RUNTIME)
    5452VBoxNetDHCP_LDFLAGS.win = /SUBSYSTEM:windows
    5553
    56 ifeq ($(USERNAME),vvl)
    57 PROGRAMS += tstDhcpConfig
    58 
    59 #
    60 # VBOXMAINCLIENT here only to use DhcpOpt_T type.
    61 tstDhcpConfig_TEMPLATE = VBOXMAINCLIENTEXE
    62 #XXX: enable condtionally if user is vvl
    63 #tstDhcpConfig_INSTTYPE = none
    64 tstDhcpConfig_SOURCES = test/tstDhcpConfig.cpp
    65 endif
    66 
    6754
    6855include $(FILE_KBUILD_SUB_FOOTER)
  • trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp

    r46962 r46969  
    2525*   Header Files                                                               *
    2626*******************************************************************************/
    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 
    3727#include <iprt/alloca.h>
    3828#include <iprt/buildconfig.h>
     
    5444#include <VBox/version.h>
    5545
    56 
    5746#include "../NetLib/VBoxNetLib.h"
    5847
    5948#include <vector>
    60 #include <list>
    6149#include <string>
    62 #include <map>
    63 
    64 #include "../NetLib/VBoxNetBaseService.h"
    6550
    6651#ifdef RT_OS_WINDOWS /* WinMain */
     
    6954#endif
    7055
    71 #ifndef INET4_ADDRLEN
    72 # define INET4_ADDRLEN 17
    73 #endif
    74 
    75 #include "Config.h"
     56
    7657/*******************************************************************************
    7758*   Structures and Typedefs                                                    *
    7859*******************************************************************************/
     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 */
     66class VBoxNetDhcpCfg
     67{
     68public:
     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 */
     245class VBoxNetDhcpLease
     246{
     247public:
     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
     276public:
     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
    79362/**
    80363 * DHCP server instance.
    81364 */
    82 class VBoxNetDhcp: public VBoxNetBaseService
     365class VBoxNetDhcp
    83366{
    84367public:
     
    86369    virtual ~VBoxNetDhcp();
    87370
    88     int                 init();
     371    int                 parseArgs(int argc, char **argv);
     372    int                 tryGoOnline(void);
    89373    int                 run(void);
    90     void                usage(void) { /* XXX: document options */ };
    91     int                 parseOpt(int rc, const RTGETOPTUNION& getOptVal);
    92374
    93375protected:
     376    int                 addConfig(VBoxNetDhcpCfg *pCfg);
     377    void                explodeConfig(void);
     378
    94379    bool                handleDhcpMsg(uint8_t uMsgType, PCRTNETBOOTP pDhcpMsg, size_t cb);
    95380    bool                handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb);
     
    97382    bool                handleDhcpReqDecline(PCRTNETBOOTP pDhcpMsg, size_t cb);
    98383    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;
    100394    void                debugPrintV(int32_t iMinLevel, bool fMsg,  const char *pszFmt, va_list va) const;
    101395    static const char  *debugDhcpName(uint8_t uMsgType);
    102396
    103397protected:
    104     /** @name The DHCP server specific configuration data members.
     398    /** @name The server configuration data members.
    105399     * @{ */
    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;
    111406    std::string         m_LeaseDBName;
    112 
    113407    /** @} */
    114408
    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    /** @} */
    136423
    137424    /** @name Debug stuff
     
    144431    /** @} */
    145432};
    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
    153434
    154435/*******************************************************************************
     
    158439static VBoxNetDhcp *g_pDhcp;
    159440
    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
    172442/**
    173443 * Offer this lease to a client.
     
    235505    return RTTimeSpecGetSeconds(&m_ExpireTime) > RTTimeSpecGetSeconds(RTTimeNow(&Now));
    236506}
    237 #endif
     507
     508
     509
    238510
    239511/**
     
    266538    memset(&m_CurHdrs, '\0', sizeof(m_CurHdrs));
    267539
    268     m_fIgnoreCmdLineParameters = true;
    269 
    270540#if 0 /* enable to hack the code without a mile long argument list. */
    271541    VBoxNetDhcpCfg *pDefCfg = new VBoxNetDhcpCfg();
     
    279549    pDefCfg->m_DNSes.push_back(Addr);
    280550    pDefCfg->m_DomainName     = "vboxnetdhcp.org";
    281 # if 0
     551#if 0
    282552    pDefCfg->m_cSecLease      = 60*60; /* 1 hour */
    283 # else
     553#else
    284554    pDefCfg->m_cSecLease      = 30; /* sec */
    285 # endif
     555#endif
    286556    pDefCfg->m_TftpServer     = "10.0.2.3"; //??
    287557    this->addConfig(pDefCfg);
     
    295565VBoxNetDhcp::~VBoxNetDhcp()
    296566{
    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 */
     597int 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 */
     622void 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 */
     693int 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
    321766            /* 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();
    342843
    343844    return rc;
    344845}
    345846
    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 */
     853int 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.
    401910         */
    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    }
    438945    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
    484951
    485952/**
     
    491958int VBoxNetDhcp::run(void)
    492959{
    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 
    500960    /*
    501961     * The loop.
     
    6141074bool VBoxNetDhcp::handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb)
    6151075{
    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;
    6561094}
    6571095
     
    6671105bool VBoxNetDhcp::handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb)
    6681106{
    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    }
    6831193    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    }
    6871198
    6881199    return true;
     
    7491260    debugPrint(1, true, "RELEASE is not implemented");
    7501261    return true;
     1262}
     1263
     1264
     1265/**
     1266 * Helper class for stuffing DHCP options into a reply packet.
     1267 */
     1268class VBoxNetDhcpWriteCursor
     1269{
     1270private:
     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
     1279public:
     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 */
     1586void 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 */
     1680VBoxNetDhcpLease *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 */
     1707VBoxNetDhcpLease *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 */
     1736VBoxNetDhcpLease *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 *
     1827VBoxNetDhcp::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
     1890VBoxNetDhcp::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 */
     1914inline 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    }
    7511923}
    7521924
     
    7731945            &&  m_pCurMsg)
    7741946        {
    775             /* XXX: export this to debugPrinfDhcpMsg or variant and other method export
    776              *  to base class
    777              */
    7781947            const char *pszMsg = m_uCurMsgType != UINT8_MAX ? debugDhcpName(m_uCurMsgType) : "";
    7791948            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",
     
    8342003     * Instantiate the DHCP server and hand it the options.
    8352004     */
    836     HRESULT hrc = com::Initialize();
    837     Assert(!FAILED(hrc));
    838 
    8392005    VBoxNetDhcp *pDhcp = new VBoxNetDhcp();
    8402006    if (!pDhcp)
     
    8462012    if (rc)
    8472013        return rc;
    848 
    849     pDhcp->init();
    8502014
    8512015    /*
  • trunk/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp

    r46962 r46969  
    11/* $Id$ */
    22/** @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! */
    56
    67/*
     
    2122#define LOG_GROUP LOG_GROUP_NET_SERVICE
    2223
    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 
    3324#include <iprt/alloca.h>
    3425#include <iprt/buildconfig.h>
     
    3930#include <iprt/param.h>
    4031#include <iprt/path.h>
    41 #include <iprt/process.h>
    4232#include <iprt/stream.h>
    4333#include <iprt/string.h>
    4434#include <iprt/time.h>
    4535#include <iprt/mem.h>
    46 #include <iprt/message.h>
    4736
    4837#include <VBox/sup.h>
     
    5544#include <string>
    5645
    57 #include <VBox/err.h>
    5846#include <VBox/log.h>
    5947
     
    7058*   Structures and Typedefs                                                    *
    7159*******************************************************************************/
    72 
    73 /*******************************************************************************
    74 *   Global Variables                                                           *
    75 *******************************************************************************/
    76 /* Commonly used options for network configuration */
    7760static RTGETOPTDEF g_aGetOptDef[] =
    7861{
     
    8669    { "--verbose",        'v',   RTGETOPT_REQ_NOTHING },
    8770};
    88 
    89 
    9071VBoxNetBaseService::VBoxNetBaseService()
    9172{
    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}
    11376VBoxNetBaseService::~VBoxNetBaseService()
    11477{
     
    13699}
    137100
    138 
    139101int VBoxNetBaseService::init()
    140102{
     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]);
    141114    return VINF_SUCCESS;
    142115}
    143 
    144 
    145116/**
    146117 * Parse the arguments.
     
    217188
    218189            case 'h':
    219                 RTPrintf("%s Version %s\n"
     190                RTPrintf("VBoxNetDHCP Version %s\n"
    220191                         "(C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
    221192                         "All rights reserved.\n"
    222193                         "\n"
    223                          "Usage: %s <options>\n"
     194                         "Usage: VBoxNetDHCP <options>\n"
    224195                         "\n"
    225196                         "Options:\n",
    226                          RTProcShortName(),
    227                          RTProcShortName(),
    228                          RTProcShortName(),
    229197                         RTBldCfgVersion());
    230198                for (unsigned int i = 0; i < m_vecOptionDefs.size(); i++)
     
    247215    return rc;
    248216}
    249 
    250217
    251218int VBoxNetBaseService::tryGoOnline(void)
     
    350317}
    351318
    352 
    353319void VBoxNetBaseService::shutdown(void)
    354320{
    355321}
    356 
    357322
    358323int VBoxNetBaseService::waitForIntNetEvent(int cMillis)
     
    412377}
    413378
    414 
    415379/**
    416380 * Print debug message depending on the m_cVerbosity level.
    417381 *
    418382 * @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 */
     387inline 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.
    420404 * @param   pszFmt          The message format string.
    421405 * @param   va              Optional arguments.
     
    427411        va_list vaCopy;                 /* This dude is *very* special, thus the copy. */
    428412        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);
    434414        va_end(vaCopy);
    435415    }
    436416
    437417}
    438 
    439418
    440419PRTGETOPTDEF VBoxNetBaseService::getOptionsPtr()
  • trunk/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.h

    r46962 r46969  
    1818#ifndef ___VBoxNetBaseService_h___
    1919#define ___VBoxNetBaseService_h___
    20 
    2120#include <iprt/critsect.h>
    2221class VBoxNetBaseService
     
    3332    int                 sendBufferOnWire(PCINTNETSEG pSg, int cSg, size_t cbBuffer);
    3433    void                flushWire();
    35 
    3634    virtual void        usage(void) = 0;
    37     virtual int         run(void) = 0;
     35    virtual void        run(void) = 0;
     36    virtual int         init(void);
    3837    virtual int         parseOpt(int rc, const RTGETOPTUNION& getOptVal) = 0;
    3938
    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;
     41public:
    6742    /** @name The server configuration data members.
    6843     * @{ */
     
    7449    RTNETADDRIPV4       m_Ipv4Address;
    7550    RTNETADDRIPV4       m_Ipv4Netmask;
     51    /* cs for syncing */
     52    RTCRITSECT          m_csThis;
    7653    /** @} */
    7754    /** @name The network interface
     
    8966private:
    9067    PRTGETOPTDEF getOptionsPtr();
    91 
    92     /* cs for syncing */
    93     RTCRITSECT          m_csThis;
    94 
    9568    /** @} */
    9669};
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette