Index: /trunk/include/VBox/settings.h
===================================================================
--- /trunk/include/VBox/settings.h	(revision 79746)
+++ /trunk/include/VBox/settings.h	(revision 79747)
@@ -349,9 +349,20 @@
 typedef DhcpOptionMap::const_iterator DhcpOptConstIterator;
 
+struct DHCPGroupCondition
+{
+    DHCPGroupCondition();
+
+    bool                    fInclusive;
+    DHCPGroupConditionType_T enmType;
+    com::Utf8Str            strValue;
+};
+typedef std::vector<DHCPGroupCondition> DHCPGroupConditionVec;
+
+
 struct DHCPConfig
 {
     DHCPConfig();
 
-    DhcpOptionMap           OptionMap;
+    DhcpOptionMap           mapOptions;
     uint32_t                secMinLeaseTime;
     uint32_t                secDefaultLeaseTime;
@@ -359,4 +370,13 @@
 };
 
+struct DHCPGroupConfig : DHCPConfig
+{
+    DHCPGroupConfig();
+
+    com::Utf8Str            strName;
+    DHCPGroupConditionVec   vecConditions;
+};
+typedef std::vector<DHCPGroupConfig> DHCPGroupConfigVec;
+
 struct DHCPIndividualConfig : DHCPConfig
 {
@@ -365,8 +385,7 @@
     com::Utf8Str            strMACAddress;
     com::Utf8Str            strVMName;
-    ULONG                   uSlot;
+    uint32_t                uSlot;
     com::Utf8Str            strFixedAddress;
 };
-
 typedef std::map<com::Utf8Str, DHCPIndividualConfig> DHCPIndividualConfigMap;
 
@@ -380,8 +399,8 @@
     com::Utf8Str            strIPUpper;
     bool                    fEnabled;
-    DHCPConfig              GlobalConfig;
-    DHCPIndividualConfigMap IndividualConfigs;
-};
-
+    DHCPConfig              globalConfig;
+    DHCPGroupConfigVec      vecGroupConfigs;
+    DHCPIndividualConfigMap mapIndividualConfigs;
+};
 typedef std::list<DHCPServer> DHCPServersList;
 
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 79746)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 79747)
@@ -1642,5 +1642,5 @@
 
   <!--
-  // IVirtualBox
+  // INATNetwork
   /////////////////////////////////////////////////////////////////////////
   -->
@@ -1754,4 +1754,10 @@
     <method name="stop"/>
   </interface>
+
+
+  <!--
+  // IDHCPServer and associates
+  /////////////////////////////////////////////////////////////////////////
+  -->
 
   <enum
@@ -1832,14 +1838,14 @@
   <enum
       name="DHCPConfigScope"
-      uuid="151df7cd-e596-42dd-235a-b164a781c099">
+      uuid="469c42e4-b9ec-43f2-bdcb-9e9d1eb434ae">
     <const name="Global"      value="0"><desc><link to="IDHCPServer::globalConfig"/></desc></const>
-    <const name="MachineNIC"  value="1"><desc><link to="IDHCPServer::individualConfigs"/></desc></const>
-    <const name="MAC"         value="2"><desc><link to="IDHCPServer::individualConfigs"/></desc></const>
-    <const name="Group"       value="3"><desc><link to="IDHCPServer::groupConfigs"/></desc></const>
+    <const name="Group"       value="1"><desc><link to="IDHCPServer::groupConfigs"/></desc></const>
+    <const name="MachineNIC"  value="2"><desc><link to="IDHCPServer::individualConfigs"/></desc></const>
+    <const name="MAC"         value="3"><desc><link to="IDHCPServer::individualConfigs"/></desc></const>
   </enum>
 
   <enum
-    name="DHCPGroupFilterType"
-    uuid="0639cd66-94b7-41ef-18ac-485636e46d97"
+    name="DHCPGroupConditionType"
+    uuid="2cb9280f-ada2-4194-dee8-bfb8ad77119d"
     >
     <const name="MAC"                     value="0"><desc>MAC address</desc></const>
@@ -2241,5 +2247,5 @@
       <desc>Whether this is an inclusive or exclusive group membership condition</desc>
     </attribute>
-    <attribute name="type" type="DHCPGroupFilterType" readonly="no">
+    <attribute name="type" type="DHCPGroupConditionType" readonly="no">
       <desc>Defines how the <link to="IDHCPGroupCondition::value"/> is interpreted.</desc>
     </attribute>
@@ -2277,6 +2283,7 @@
     <method name="addCondition">
       <param name="inclusive"  dir="in" type="boolean"/>
-      <param name="type"       dir="in" type="DHCPGroupFilterType"/>
+      <param name="type"       dir="in" type="DHCPGroupConditionType"/>
       <param name="value"      dir="in" type="wstring"/>
+      <param name="condition"  dir="return" type="IDHCPGroupCondition"/>
     </method>
 
Index: /trunk/src/VBox/Main/include/DHCPConfigImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/DHCPConfigImpl.h	(revision 79746)
+++ /trunk/src/VBox/Main/include/DHCPConfigImpl.h	(revision 79747)
@@ -23,4 +23,5 @@
 
 #include "DHCPGlobalConfigWrap.h"
+#include "DHCPGroupConditionWrap.h"
 #include "DHCPGroupConfigWrap.h"
 #include "DHCPIndividualConfigWrap.h"
@@ -29,4 +30,5 @@
 
 class DHCPServer;
+class DHCPGroupConfig;
 
 
@@ -99,8 +101,7 @@
     /** @} */
 
-protected:
+
+public:
     HRESULT             i_doWriteConfig();
-
-public:
     HRESULT             i_saveSettings(settings::DHCPConfig &a_rDst);
     DHCPConfigScope_T   i_getScope() const RT_NOEXCEPT { return m_enmScope; }
@@ -187,9 +188,149 @@
 
 /**
+ * DHCP Group inclusion/exclusion condition.
+ */
+class DHCPGroupCondition : public DHCPGroupConditionWrap
+{
+private:
+    /** Inclusive or exclusive condition. */
+    bool                        m_fInclusive;
+    /** The condition type (or how m_strValue should be interpreted). */
+    DHCPGroupConditionType_T    m_enmType;
+    /** The value.  Interpreted according to m_enmType. */
+    com::Utf8Str                m_strValue;
+    /** Pointer to the parent (weak). */
+    DHCPGroupConfig            *m_pParent;
+
+public:
+    /** @name Constructors and destructors.
+     * @{ */
+    DHCPGroupCondition()
+        : m_enmType(DHCPGroupConditionType_MAC)
+        , m_pParent(NULL)
+    {}
+    HRESULT FinalConstruct()
+    {
+        return BaseFinalConstruct();
+    }
+    void    FinalRelease()
+    {
+        uninit();
+        BaseFinalRelease();
+    }
+    HRESULT initWithDefaults(DHCPGroupConfig *a_pParent, bool a_fInclusive, DHCPGroupConditionType_T a_enmType,
+                             const com::Utf8Str a_strValue);
+    HRESULT initWithSettings(DHCPGroupConfig *a_pParent, const settings::DHCPGroupCondition &a_rSrc);
+    void    uninit();
+    /** @} */
+
+    HRESULT i_saveSettings(settings::DHCPGroupCondition &a_rDst);
+
+protected:
+    /** @name Wrapped IDHCPGroupCondition properties
+     * @{ */
+    HRESULT getInclusive(BOOL *aInclusive) RT_OVERRIDE;
+    HRESULT setInclusive(BOOL aInclusive) RT_OVERRIDE;
+    HRESULT getType(DHCPGroupConditionType_T *aType) RT_OVERRIDE;
+    HRESULT setType(DHCPGroupConditionType_T aType) RT_OVERRIDE;
+    HRESULT getValue(com::Utf8Str &aValue) RT_OVERRIDE;
+    HRESULT setValue(const com::Utf8Str &aValue) RT_OVERRIDE;
+    /** @} */
+
+    /** @name Wrapped IDHCPGroupCondition methods
+     * @{ */
+    HRESULT remove() RT_OVERRIDE;
+    /** @} */
+};
+
+
+/**
  * Group configuration.
  */
-class DHCPGroupConfig : public VirtualBoxBase, public DHCPConfig
+class DHCPGroupConfig : public DHCPGroupConfigWrap, public DHCPConfig
 {
-    /** @todo later */
+private:
+    /** Group name. */
+    com::Utf8Str                                m_strName;
+    /** Group membership conditions.   */
+    std::vector<ComObjPtr<DHCPGroupCondition> > m_Conditions;
+    /** Iterator for m_Conditions. */
+    typedef std::vector<ComObjPtr<DHCPGroupCondition> >::iterator ConditionsIterator;
+
+public:
+    /** @name Constructors and destructors.
+     * @{ */
+    DHCPGroupConfig()
+        : DHCPConfig(DHCPConfigScope_Group, this)
+    { }
+    HRESULT FinalConstruct()
+    {
+        return BaseFinalConstruct();
+    }
+    void    FinalRelease()
+    {
+        uninit();
+        BaseFinalRelease();
+    }
+    HRESULT initWithDefaults(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent, const com::Utf8Str &a_rName);
+    HRESULT initWithSettings(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent, const settings::DHCPGroupConfig &a_rSrc);
+    void    uninit();
+    /** @} */
+
+    HRESULT i_saveSettings(settings::DHCPGroupConfig &a_rDst);
+    HRESULT i_removeCondition(DHCPGroupCondition *a_pCondition);
+
+protected:
+    /** @name Wrapped IDHCPConfig properties
+     * @{ */
+    HRESULT getScope(DHCPConfigScope_T *aScope) RT_OVERRIDE             { return i_getScope(aScope); }
+    HRESULT getMinLeaseTime(ULONG *aMinLeaseTime) RT_OVERRIDE           { return i_getMinLeaseTime(aMinLeaseTime); }
+    HRESULT setMinLeaseTime(ULONG aMinLeaseTime) RT_OVERRIDE            { return i_setMinLeaseTime(aMinLeaseTime); }
+    HRESULT getDefaultLeaseTime(ULONG *aDefaultLeaseTime) RT_OVERRIDE   { return i_getDefaultLeaseTime(aDefaultLeaseTime); }
+    HRESULT setDefaultLeaseTime(ULONG aDefaultLeaseTime) RT_OVERRIDE    { return i_setDefaultLeaseTime(aDefaultLeaseTime); }
+    HRESULT getMaxLeaseTime(ULONG *aMaxLeaseTime) RT_OVERRIDE           { return i_getMaxLeaseTime(aMaxLeaseTime); }
+    HRESULT setMaxLeaseTime(ULONG aMaxLeaseTime) RT_OVERRIDE            { return i_setMaxLeaseTime(aMaxLeaseTime); }
+    /** @} */
+
+    /** @name Wrapped IDHCPGroupConfig properties
+     * @{ */
+    HRESULT getName(com::Utf8Str &aName) RT_OVERRIDE;
+    HRESULT setName(const com::Utf8Str &aName) RT_OVERRIDE;
+    HRESULT getConditions(std::vector<ComPtr<IDHCPGroupCondition> > &aConditions) RT_OVERRIDE;
+    /** @} */
+
+    /** @name Wrapped IDHCPConfig methods
+     * @{ */
+    HRESULT setOption(DhcpOpt_T aOption, DHCPOptionEncoding_T aEncoding, const com::Utf8Str &aValue) RT_OVERRIDE
+    {
+        return i_setOption(aOption, aEncoding, aValue);
+    }
+
+    HRESULT removeOption(DhcpOpt_T aOption) RT_OVERRIDE
+    {
+        return i_removeOption(aOption);
+    }
+
+    HRESULT removeAllOptions() RT_OVERRIDE
+    {
+        return i_removeAllOptions();
+    }
+
+    HRESULT getOption(DhcpOpt_T aOption, DHCPOptionEncoding_T *aEncoding, com::Utf8Str &aValue) RT_OVERRIDE
+    {
+        return i_getOption(aOption, aEncoding, aValue);
+    }
+
+    HRESULT getAllOptions(std::vector<DhcpOpt_T> &aOptions, std::vector<DHCPOptionEncoding_T> &aEncodings,
+                          std::vector<com::Utf8Str> &aValues) RT_OVERRIDE
+    {
+        return i_getAllOptions(aOptions, aEncodings, aValues);
+    }
+    /** @} */
+
+    /** @name Wrapped IDHCPGroupConfig methods
+     * @{ */
+    HRESULT addCondition(BOOL aInclusive, DHCPGroupConditionType_T aType, const com::Utf8Str &aValue,
+                         ComPtr<IDHCPGroupCondition> &aCondition) RT_OVERRIDE;
+    /** @} */
 };
 
Index: /trunk/src/VBox/Main/src-server/DHCPConfigImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/DHCPConfigImpl.cpp	(revision 79746)
+++ /trunk/src/VBox/Main/src-server/DHCPConfigImpl.cpp	(revision 79747)
@@ -59,5 +59,5 @@
     m_secMaxLeaseTime     = rConfig.secMaxLeaseTime;
 
-    for (settings::DhcpOptionMap::const_iterator it = rConfig.OptionMap.begin(); it != rConfig.OptionMap.end(); ++it)
+    for (settings::DhcpOptionMap::const_iterator it = rConfig.mapOptions.begin(); it != rConfig.mapOptions.end(); ++it)
     {
         try
@@ -85,5 +85,5 @@
     try
     {
-        a_rDst.OptionMap = m_OptionMap;
+        a_rDst.mapOptions = m_OptionMap;
     }
     catch (std::bad_alloc &)
@@ -223,5 +223,5 @@
         aValues.resize(m_OptionMap.size());
         size_t i = 0;
-        for (settings::DhcpOptionMap::iterator it = m_OptionMap.begin(); it != m_OptionMap.end(); ++it)
+        for (settings::DhcpOptionMap::iterator it = m_OptionMap.begin(); it != m_OptionMap.end(); ++it, i++)
         {
             aOptions[i]   = it->first;
@@ -244,4 +244,5 @@
  *
  * @note    Must hold no locks when this is called!
+ * @note    Public because DHCPGroupCondition needs to call it too.
  */
 HRESULT DHCPConfig::i_doWriteConfig()
@@ -327,4 +328,6 @@
 HRESULT DHCPGlobalConfig::i_saveSettings(settings::DHCPConfig &a_rDst)
 {
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
     return DHCPConfig::i_saveSettings(a_rDst);
 }
@@ -416,4 +419,308 @@
 
 /*********************************************************************************************************************************
+*   DHCPGroupCondition Implementation                                                                                            *
+*********************************************************************************************************************************/
+#undef  LOG_GROUP
+#define LOG_GROUP LOG_GROUP_MAIN_DHCPGROUPCONDITION
+
+HRESULT DHCPGroupCondition::initWithDefaults(DHCPGroupConfig *a_pParent, bool a_fInclusive, DHCPGroupConditionType_T a_enmType,
+                                             const com::Utf8Str a_strValue)
+{
+    AutoInitSpan autoInitSpan(this);
+    AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+    m_pParent    = a_pParent;
+    m_fInclusive = a_fInclusive;
+    m_enmType    = a_enmType;
+    HRESULT hrc = m_strValue.assignEx(a_strValue);
+
+    if (SUCCEEDED(hrc))
+        autoInitSpan.setSucceeded();
+    else
+        autoInitSpan.setFailed(hrc);
+    return hrc;
+}
+
+
+HRESULT DHCPGroupCondition::initWithSettings(DHCPGroupConfig *a_pParent, const settings::DHCPGroupCondition &a_rSrc)
+{
+    return initWithDefaults(a_pParent, a_rSrc.fInclusive, a_rSrc.enmType, a_rSrc.strValue);
+}
+
+
+void DHCPGroupCondition::uninit()
+{
+    AutoUninitSpan autoUninitSpan(this);
+    if (!autoUninitSpan.uninitDone())
+        autoUninitSpan.setSucceeded();
+}
+
+
+HRESULT DHCPGroupCondition::i_saveSettings(settings::DHCPGroupCondition &a_rDst)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    a_rDst.fInclusive = m_fInclusive;
+    a_rDst.enmType    = m_enmType;
+    return a_rDst.strValue.assignEx(m_strValue);
+}
+
+
+HRESULT DHCPGroupCondition::getInclusive(BOOL *aInclusive)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+    *aInclusive = m_fInclusive;
+    return S_OK;
+}
+
+
+HRESULT DHCPGroupCondition::setInclusive(BOOL aInclusive)
+{
+    {
+        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+        if ((aInclusive != FALSE) == m_fInclusive)
+            return S_OK;
+        m_fInclusive = aInclusive != FALSE;
+    }
+    return m_pParent->i_doWriteConfig();
+}
+
+
+HRESULT DHCPGroupCondition::getType(DHCPGroupConditionType_T *aType)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+    *aType = m_enmType;
+    return S_OK;
+}
+
+
+HRESULT DHCPGroupCondition::setType(DHCPGroupConditionType_T aType)
+{
+    {
+        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+        if (aType == m_enmType)
+            return S_OK;
+        m_enmType = aType;
+    }
+    return m_pParent->i_doWriteConfig();
+}
+
+
+HRESULT DHCPGroupCondition::getValue(com::Utf8Str &aValue)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+    return aValue.assignEx(m_strValue);
+}
+
+
+HRESULT DHCPGroupCondition::setValue(const com::Utf8Str &aValue)
+{
+    {
+        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+        if (aValue == m_strValue)
+            return S_OK;
+        HRESULT hrc = m_strValue.assignEx(aValue);
+        if (FAILED(hrc))
+            return hrc;
+    }
+    return m_pParent->i_doWriteConfig();
+}
+
+
+HRESULT DHCPGroupCondition::remove()
+{
+    return m_pParent->i_removeCondition(this);
+}
+
+
+
+/*********************************************************************************************************************************
+*   DHCPGroupConfig Implementation                                                                                               *
+*********************************************************************************************************************************/
+#undef  LOG_GROUP
+#define LOG_GROUP LOG_GROUP_MAIN_DHCPGROUPCONFIG
+
+
+HRESULT DHCPGroupConfig::initWithDefaults(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent, const com::Utf8Str &a_rName)
+{
+    AutoInitSpan autoInitSpan(this);
+    AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+    Assert(m_Conditions.size() == 0);
+    HRESULT hrc = DHCPConfig::i_initWithDefaults(a_pVirtualBox, a_pParent);
+    if (SUCCEEDED(hrc))
+        hrc = m_strName.assignEx(a_rName);
+
+    if (SUCCEEDED(hrc))
+        autoInitSpan.setSucceeded();
+    else
+        autoInitSpan.setFailed(hrc);
+    return hrc;
+}
+
+
+HRESULT DHCPGroupConfig::initWithSettings(VirtualBox *a_pVirtualBox, DHCPServer *a_pParent, const settings::DHCPGroupConfig &a_rSrc)
+{
+    AutoInitSpan autoInitSpan(this);
+    AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+    Assert(m_Conditions.size() == 0);
+    HRESULT hrc = DHCPConfig::i_initWithSettings(a_pVirtualBox, a_pParent, a_rSrc);
+    if (SUCCEEDED(hrc))
+        hrc = m_strName.assignEx(a_rSrc.strName);
+
+    for (settings::DHCPGroupConditionVec::const_iterator it = a_rSrc.vecConditions.begin();
+         it != a_rSrc.vecConditions.end() && SUCCEEDED(hrc); ++it)
+    {
+        ComObjPtr<DHCPGroupCondition> ptrCondition;
+        hrc = ptrCondition.createObject();
+        if (SUCCEEDED(hrc))
+        {
+            hrc = ptrCondition->initWithSettings(this, *it);
+            if (SUCCEEDED(hrc))
+            {
+                try
+                {
+                    m_Conditions.push_back(ptrCondition);
+                }
+                catch (std::bad_alloc &)
+                {
+                    hrc = E_OUTOFMEMORY;
+                }
+            }
+        }
+    }
+
+    if (SUCCEEDED(hrc))
+        autoInitSpan.setSucceeded();
+    else
+        autoInitSpan.setFailed(hrc);
+    return hrc;
+}
+
+
+void    DHCPGroupConfig::uninit()
+{
+    AutoUninitSpan autoUninitSpan(this);
+    if (!autoUninitSpan.uninitDone())
+        autoUninitSpan.setSucceeded();
+}
+
+
+HRESULT DHCPGroupConfig::i_saveSettings(settings::DHCPGroupConfig &a_rDst)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    HRESULT hrc = DHCPConfig::i_saveSettings(a_rDst);
+    if (SUCCEEDED(hrc))
+        hrc = a_rDst.strName.assignEx(m_strName);
+    if (SUCCEEDED(hrc))
+    {
+        size_t const cConditions = m_Conditions.size();
+        try
+        {
+            a_rDst.vecConditions.resize(cConditions);
+        }
+        catch (std::bad_alloc &)
+        {
+            hrc = E_OUTOFMEMORY;
+        }
+
+        for (size_t i = 0; i < cConditions && SUCCEEDED(hrc); i++)
+            hrc = m_Conditions[i]->i_saveSettings(a_rDst.vecConditions[i]);
+    }
+    return hrc;
+}
+
+
+HRESULT DHCPGroupConfig::i_removeCondition(DHCPGroupCondition *a_pCondition)
+{
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    for (ConditionsIterator it = m_Conditions.begin(); it != m_Conditions.end();)
+    {
+        DHCPGroupCondition *pCurCondition = *it;
+        if (pCurCondition == a_pCondition)
+            it = m_Conditions.erase(it);
+        else
+            ++it;
+    }
+
+    /* Never mind if already delete, right? */
+    return S_OK;
+}
+
+
+HRESULT DHCPGroupConfig::getName(com::Utf8Str &aName)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+    return aName.assignEx(m_strName);
+}
+
+
+HRESULT DHCPGroupConfig::setName(const com::Utf8Str &aName)
+{
+    {
+        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+        if (aName == m_strName)
+            return S_OK;
+        HRESULT hrc = m_strName.assignEx(aName);
+        if (FAILED(hrc))
+            return hrc;
+    }
+    return i_doWriteConfig();
+}
+
+
+HRESULT DHCPGroupConfig::getConditions(std::vector<ComPtr<IDHCPGroupCondition> > &aConditions)
+{
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+    size_t const cConditions = m_Conditions.size();
+    try
+    {
+        aConditions.resize(cConditions);
+    }
+    catch (std::bad_alloc &)
+    {
+        return E_OUTOFMEMORY;
+    }
+    HRESULT hrc = S_OK;
+    for (size_t i = 0; i < cConditions && SUCCEEDED(hrc); i++)
+        hrc = m_Conditions[i].queryInterfaceTo(aConditions[i].asOutParam());
+    return hrc;
+}
+
+
+HRESULT DHCPGroupConfig::addCondition(BOOL aInclusive, DHCPGroupConditionType_T aType, const com::Utf8Str &aValue,
+                                      ComPtr<IDHCPGroupCondition> &aCondition)
+{
+    ComObjPtr<DHCPGroupCondition> ptrCondition;
+    HRESULT hrc = ptrCondition.createObject();
+    if (SUCCEEDED(hrc))
+        hrc = ptrCondition->initWithDefaults(this, aInclusive != FALSE, aType, aValue);
+    if (SUCCEEDED(hrc))
+    {
+        hrc = ptrCondition.queryInterfaceTo(aCondition.asOutParam());
+        if (SUCCEEDED(hrc))
+        {
+            AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+            try
+            {
+                m_Conditions.push_back(ptrCondition);
+            }
+            catch (std::bad_alloc &)
+            {
+                aCondition.setNull();
+                return E_OUTOFMEMORY;
+            }
+        }
+    }
+
+    return hrc;
+}
+
+
+
+/*********************************************************************************************************************************
 *   DHCPIndividualConfig Implementation                                                                                          *
 *********************************************************************************************************************************/
@@ -510,4 +817,6 @@
 HRESULT DHCPIndividualConfig::i_saveSettings(settings::DHCPIndividualConfig &a_rDst)
 {
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
     a_rDst.uSlot = m_uSlot;
     int vrc = a_rDst.strMACAddress.printfNoThrow("%RTmac", &m_MACAddress);
@@ -536,5 +845,5 @@
 
     /* Format the return string: */
-    int vrc = aMACAddress.printfNoThrow("%RTmac", &m_MACAddress);
+    int vrc = aMACAddress.printfNoThrow("%RTmac", &MACAddress);
     return RT_SUCCESS(vrc) ? S_OK : E_OUTOFMEMORY;
 }
@@ -619,5 +928,6 @@
                     hrc = S_OK;
                 else
-                    hrc = setError(hrc, tr("INetworkAdapter returned bogus MAC address '%ls'"), bstrMACAddress.raw());
+                    hrc = setErrorBoth(E_FAIL, vrc, tr("INetworkAdapter returned bogus MAC address '%ls': %Rrc"),
+                                       bstrMACAddress.raw(), vrc);
             }
         }
Index: /trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp	(revision 79746)
+++ /trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp	(revision 79747)
@@ -66,14 +66,8 @@
     {}
 
-    static const char * const kDsrKeyGateway;
-    static const char * const kDsrKeyLowerIp;
-    static const char * const kDsrKeyUpperIp;
     static const char * const kDsrKeyConfig;
     static const char * const kDsrKeyComment;
 };
 
-/*static*/ const char * const DHCPServerRunner::kDsrKeyGateway = "--gateway";
-/*static*/ const char * const DHCPServerRunner::kDsrKeyLowerIp = "--lower-ip";
-/*static*/ const char * const DHCPServerRunner::kDsrKeyUpperIp = "--upper-ip";
 /*static*/ const char * const DHCPServerRunner::kDsrKeyConfig  = "--config";
 /*static*/ const char * const DHCPServerRunner::kDsrKeyComment = "--comment";
@@ -89,5 +83,4 @@
         , strName()
         , enabled(FALSE)
-//        , router(false)
         , uIndividualMACAddressVersion(1)
     {
@@ -106,13 +99,4 @@
 
     BOOL enabled;
-#if 0
-    /** Don't quit get WTF this is about, but the old addOption method contained the
-     * following hint: "Indirect way to understand that we're on NAT network."
-     *
-     * Apparently this is a busted with the new dhcpd implementation, so we don't
-     * maintain it with the API overhaul in 6.0.12.
-     */
-    bool router;
-#endif
     DHCPServerRunner dhcp;
 
@@ -126,8 +110,8 @@
     ComObjPtr<DHCPGlobalConfig> globalConfig;
 
-//    /** Group configuration indexed by name. */
-//    std::map<com::Utf8Str, ComObjPtr<DHCPGroupConfig>> groupConfigs;
-//    /** Iterator for groupConfigs. */
-//    typedef std::map<com::Utf8Str, ComObjPtr<DHCPGroupConfig>>::iterator GroupConfigIterator;
+    /** Group configuration indexed by name. */
+    std::map<com::Utf8Str, ComObjPtr<DHCPGroupConfig>> groupConfigs;
+    /** Iterator for groupConfigs. */
+    typedef std::map<com::Utf8Str, ComObjPtr<DHCPGroupConfig>>::iterator GroupConfigIterator;
 
     /** Individual (host) configuration indexed by MAC address or VM UUID. */
@@ -210,4 +194,7 @@
     if (SUCCEEDED(hrc))
         hrc = m->globalConfig->initWithDefaults(aVirtualBox, this);
+
+    Assert(m->groupConfigs.size() == 0);
+    Assert(m->individualConfigs.size() == 0);
 
     /* Confirm a successful initialization or not: */
@@ -240,9 +227,29 @@
     HRESULT hrc = m->globalConfig.createObject();
     if (SUCCEEDED(hrc))
-        hrc = m->globalConfig->initWithSettings(aVirtualBox, this, rData.GlobalConfig);
+        hrc = m->globalConfig->initWithSettings(aVirtualBox, this, rData.globalConfig);
 
     /*
      * Group configurations:
      */
+    Assert(m->groupConfigs.size() == 0);
+    for (settings::DHCPGroupConfigVec::const_iterator it = rData.vecGroupConfigs.begin();
+         it != rData.vecGroupConfigs.end() && SUCCEEDED(hrc); ++it)
+    {
+        ComObjPtr<DHCPGroupConfig> ptrGroupConfig;
+        hrc = ptrGroupConfig.createObject();
+        if (SUCCEEDED(hrc))
+            hrc = ptrGroupConfig->initWithSettings(aVirtualBox, this, *it);
+        if (SUCCEEDED(hrc))
+        {
+            try
+            {
+                m->groupConfigs[it->strName] = ptrGroupConfig;
+            }
+            catch (std::bad_alloc &)
+            {
+                return E_OUTOFMEMORY;
+            }
+        }
+    }
 
     /*
@@ -250,53 +257,50 @@
      */
     Assert(m->individualConfigs.size() == 0);
-    if (SUCCEEDED(hrc))
-    {
-        for (settings::DHCPIndividualConfigMap::const_iterator it = rData.IndividualConfigs.begin();
-             it != rData.IndividualConfigs.end() && SUCCEEDED(hrc); ++it)
-        {
-            ComObjPtr<DHCPIndividualConfig> ptrIndiCfg;
-            com::Utf8Str                    strKey;
-            if (!it->second.strVMName.isNotEmpty())
+    for (settings::DHCPIndividualConfigMap::const_iterator it = rData.mapIndividualConfigs.begin();
+         it != rData.mapIndividualConfigs.end() && SUCCEEDED(hrc); ++it)
+    {
+        ComObjPtr<DHCPIndividualConfig> ptrIndiCfg;
+        com::Utf8Str                    strKey;
+        if (!it->second.strVMName.isNotEmpty())
+        {
+            RTMAC MACAddress;
+            int vrc = RTNetStrToMacAddr(it->second.strMACAddress.c_str(), &MACAddress);
+            if (RT_FAILURE(vrc))
             {
-                RTMAC MACAddress;
-                int vrc = RTNetStrToMacAddr(it->second.strMACAddress.c_str(), &MACAddress);
-                if (RT_FAILURE(vrc))
-                {
-                    LogRel(("Ignoring invalid MAC address for individual DHCP config: '%s' - %Rrc\n", it->second.strMACAddress.c_str(), vrc));
-                    continue;
-                }
-
-                vrc = strKey.printfNoThrow("%RTmac", &MACAddress);
-                AssertRCReturn(vrc, E_OUTOFMEMORY);
-
+                LogRel(("Ignoring invalid MAC address for individual DHCP config: '%s' - %Rrc\n", it->second.strMACAddress.c_str(), vrc));
+                continue;
+            }
+
+            vrc = strKey.printfNoThrow("%RTmac", &MACAddress);
+            AssertRCReturn(vrc, E_OUTOFMEMORY);
+
+            hrc = ptrIndiCfg.createObject();
+            if (SUCCEEDED(hrc))
+                hrc = ptrIndiCfg->initWithSettingsAndMACAddress(aVirtualBox, this, it->second, &MACAddress);
+        }
+        else
+        {
+            /* This ASSUMES that we're being called after the machines have been
+               loaded so we can resolve VM names into UUID for old settings. */
+            com::Guid idMachine;
+            hrc = i_vmNameToIdAndValidateSlot(it->second.strVMName, it->second.uSlot, idMachine);
+            if (SUCCEEDED(hrc))
+            {
                 hrc = ptrIndiCfg.createObject();
                 if (SUCCEEDED(hrc))
-                    hrc = ptrIndiCfg->initWithSettingsAndMACAddress(aVirtualBox, this, it->second, &MACAddress);
+                    hrc = ptrIndiCfg->initWithSettingsAndMachineIdAndSlot(aVirtualBox, this, it->second,
+                                                                          idMachine, it->second.uSlot,
+                                                                          m->uIndividualMACAddressVersion - UINT32_MAX / 4);
             }
-            else
+        }
+        if (SUCCEEDED(hrc))
+        {
+            try
             {
-                /* This ASSUMES that we're being called after the machines have been
-                   loaded so we can resolve VM names into UUID for old settings. */
-                com::Guid idMachine;
-                hrc = i_vmNameToIdAndValidateSlot(it->second.strVMName, it->second.uSlot, idMachine);
-                if (SUCCEEDED(hrc))
-                {
-                    hrc = ptrIndiCfg.createObject();
-                    if (SUCCEEDED(hrc))
-                        hrc = ptrIndiCfg->initWithSettingsAndMachineIdAndSlot(aVirtualBox, this, it->second,
-                                                                              idMachine, it->second.uSlot,
-                                                                              m->uIndividualMACAddressVersion - UINT32_MAX / 4);
-                }
+                m->individualConfigs[strKey] = ptrIndiCfg;
             }
-            if (SUCCEEDED(hrc))
+            catch (std::bad_alloc &)
             {
-                try
-                {
-                    m->individualConfigs[strKey] = ptrIndiCfg;
-                }
-                catch (std::bad_alloc &)
-                {
-                    return E_OUTOFMEMORY;
-                }
+                return E_OUTOFMEMORY;
             }
         }
@@ -326,7 +330,29 @@
 
     /* Global configuration: */
-    HRESULT hrc = m->globalConfig->i_saveSettings(rData.GlobalConfig);
+    HRESULT hrc = m->globalConfig->i_saveSettings(rData.globalConfig);
 
     /* Group configuration: */
+    size_t const cGroupConfigs = m->groupConfigs.size();
+    try
+    {
+        rData.vecGroupConfigs.resize(cGroupConfigs);
+    }
+    catch (std::bad_alloc &)
+    {
+        return E_OUTOFMEMORY;
+    }
+    size_t i = 0;
+    for (Data::GroupConfigIterator it = m->groupConfigs.begin(); it != m->groupConfigs.end() && SUCCEEDED(hrc); ++it, i++)
+    {
+        try
+        {
+            rData.vecGroupConfigs[i] = settings::DHCPGroupConfig();
+        }
+        catch (std::bad_alloc &)
+        {
+            return E_OUTOFMEMORY;
+        }
+        hrc = it->second->i_saveSettings(rData.vecGroupConfigs[i]);
+    }
 
     /* Individual configuration: */
@@ -336,5 +362,5 @@
         try
         {
-            rData.IndividualConfigs[it->first] = settings::DHCPIndividualConfig();
+            rData.mapIndividualConfigs[it->first] = settings::DHCPIndividualConfig();
         }
         catch (std::bad_alloc &)
@@ -342,5 +368,5 @@
             return E_OUTOFMEMORY;
         }
-        hrc = it->second->i_saveSettings(rData.IndividualConfigs[it->first]);
+        hrc = it->second->i_saveSettings(rData.mapIndividualConfigs[it->first]);
     }
 
@@ -681,4 +707,15 @@
 
 
+/**
+ * Validates the VM name and slot, returning the machine ID.
+ *
+ * If a machine ID is given instead of a name, we won't check whether it
+ * actually exists...
+ *
+ * @returns COM status code.
+ * @param   aVmName             The VM name or UUID.
+ * @param   aSlot               The slot.
+ * @param   idMachine           Where to return the VM UUID.
+ */
 HRESULT DHCPServer::i_vmNameToIdAndValidateSlot(const com::Utf8Str &aVmName, LONG aSlot, com::Guid &idMachine)
 {
@@ -692,5 +729,5 @@
         /* No, find the VM and get it's UUID. */
         ComObjPtr<Machine> ptrMachine;
-        HRESULT hrc = m->pVirtualBox->i_findMachine(aVmName, false /*fPermitInaccessible*/, true /*aSetError*/, &ptrMachine);
+        HRESULT hrc = m->pVirtualBox->i_findMachineByName(aVmName, true /*aSetError*/, &ptrMachine);
         if (SUCCEEDED(hrc))
             idMachine = ptrMachine->i_getId();
@@ -856,9 +893,9 @@
 {
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-#if 0 /** @todo implement group configs   */
-
+
+    size_t const cGroupConfigs = m->groupConfigs.size();
     try
     {
-        aGroupConfigs.resize(m->groupConfigs.size());
+        aGroupConfigs.resize(cGroupConfigs);
     }
     catch (std::bad_alloc &)
@@ -868,6 +905,7 @@
 
     size_t i = 0;
-    for (Data::GroupConfigIterator it = m->groupConfigs.begin(); it != m->groupConfigs.end(); ++it)
-    {
+    for (Data::GroupConfigIterator it = m->groupConfigs.begin(); it != m->groupConfigs.end(); ++it, i++)
+    {
+        Assert(i < cGroupConfigs);
         HRESULT hrc = it->second.queryInterfaceTo(aGroupConfigs[i].asOutParam());
         if (FAILED(hrc))
@@ -875,7 +913,4 @@
     }
 
-#else
-    aGroupConfigs.resize(0);
-#endif
     return S_OK;
 }
@@ -886,7 +921,8 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
+    size_t const cIndividualConfigs = m->individualConfigs.size();
     try
     {
-        aIndividualConfigs.resize(m->individualConfigs.size());
+        aIndividualConfigs.resize(cIndividualConfigs);
     }
     catch (std::bad_alloc &)
@@ -896,6 +932,7 @@
 
     size_t i = 0;
-    for (Data::IndividualConfigIterator it = m->individualConfigs.begin(); it != m->individualConfigs.end(); ++it)
-    {
+    for (Data::IndividualConfigIterator it = m->individualConfigs.begin(); it != m->individualConfigs.end(); ++it, i++)
+    {
+        Assert(i < cIndividualConfigs);
         HRESULT hrc = it->second.queryInterfaceTo(aIndividualConfigs[i].asOutParam());
         if (FAILED(hrc))
@@ -957,6 +994,6 @@
          * Groups.
          */
-        //for (Data::GroupConfigIterator it = m->groupConfigs.begin(); it != m->groupConfigs.end(); ++it)
-        //    it->second->i_writeDhcpdConfig(pElmRoot->createChild("Config"));
+        for (Data::GroupConfigIterator it = m->groupConfigs.begin(); it != m->groupConfigs.end(); ++it)
+            it->second->i_writeDhcpdConfig(pElmRoot->createChild("Group"));
 
         /*
@@ -1267,9 +1304,51 @@
             if (aName.isNotEmpty())
                 return setError(E_INVALIDARG, tr("The name must be empty or NULL for the Global scope!"));
+
             /* No locking required here. */
             return m->globalConfig.queryInterfaceTo(aConfig.asOutParam());
 
         case DHCPConfigScope_Group:
-            return setError(E_NOTIMPL, tr("Groups are not yet implemented, sorry."));
+        {
+            if (aName.isEmpty())
+                return setError(E_INVALIDARG, tr("A group must have a name!"));
+            if (aName.length() > _1K)
+                return setError(E_INVALIDARG, tr("Name too long! %zu bytes"), aName.length());
+
+            /* Look up the group: */
+            {
+                AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+                Data::GroupConfigIterator it = m->groupConfigs.find(aName);
+                if (it != m->groupConfigs.end())
+                    return it->second.queryInterfaceTo(aConfig.asOutParam());
+            }
+            /* Create a new group if we can. */
+            if (!aMayAdd)
+                return setError(VBOX_E_OBJECT_NOT_FOUND, tr("Found no configuration for group %s"), aName.c_str());
+            ComObjPtr<DHCPGroupConfig> ptrGroupConfig;
+            HRESULT hrc = ptrGroupConfig.createObject();
+            if (SUCCEEDED(hrc))
+                hrc = ptrGroupConfig->initWithDefaults(m->pVirtualBox, this, aName);
+            if (SUCCEEDED(hrc))
+            {
+                AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+                /* Check for insertion race: */
+                Data::GroupConfigIterator it = m->groupConfigs.find(aName);
+                if (it != m->groupConfigs.end())
+                    return it->second.queryInterfaceTo(aConfig.asOutParam()); /* creation race*/
+
+                /* Try insert it: */
+                try
+                {
+                    m->groupConfigs[aName] = ptrGroupConfig;
+                }
+                catch (std::bad_alloc &)
+                {
+                    return E_OUTOFMEMORY;
+                }
+                return ptrGroupConfig.queryInterfaceTo(aConfig.asOutParam());
+            }
+            return hrc;
+        }
 
         case DHCPConfigScope_MachineNIC:
Index: /trunk/src/VBox/Main/xml/Settings.cpp
===================================================================
--- /trunk/src/VBox/Main/xml/Settings.cpp	(revision 79746)
+++ /trunk/src/VBox/Main/xml/Settings.cpp	(revision 79747)
@@ -1629,13 +1629,32 @@
 }
 
-
 /**
  * Default constructor.
  */
+DHCPGroupCondition::DHCPGroupCondition()
+    : fInclusive(true)
+    , enmType(DHCPGroupConditionType_MAC)
+    , strValue()
+{
+}
+
+/**
+ * Default constructor.
+ */
 DHCPConfig::DHCPConfig()
-    : OptionMap()
+    : mapOptions()
     , secMinLeaseTime(0)
     , secDefaultLeaseTime(0)
     , secMaxLeaseTime(0)
+{
+}
+
+/**
+ * Default constructor.
+ */
+DHCPGroupConfig::DHCPGroupConfig()
+    : DHCPConfig()
+    , strName()
+    , vecConditions()
 {
 }
@@ -1719,6 +1738,6 @@
         pElmThis->setAttribute("networkName", srv.strNetworkName);
         pElmThis->setAttribute("IPAddress", srv.strIPAddress);
-        DhcpOptConstIterator itOpt = srv.GlobalConfig.OptionMap.find(DhcpOpt_SubnetMask);
-        if (itOpt != srv.GlobalConfig.OptionMap.end())
+        DhcpOptConstIterator itOpt = srv.globalConfig.mapOptions.find(DhcpOpt_SubnetMask);
+        if (itOpt != srv.globalConfig.mapOptions.end())
             pElmThis->setAttribute("networkMask", itOpt->second.strValue);
         pElmThis->setAttribute("lowerIP", srv.strIPLower);
@@ -1727,28 +1746,44 @@
 
         /* We don't want duplicate validation check of networkMask here*/
-        if (srv.GlobalConfig.OptionMap.size() > (itOpt != srv.GlobalConfig.OptionMap.end() ? 1U : 0U))
+        if (srv.globalConfig.mapOptions.size() > (itOpt != srv.globalConfig.mapOptions.end() ? 1U : 0U))
         {
             xml::ElementNode *pElmOptions = pElmThis->createChild("Options");
-            buildDHCPOptions(*pElmOptions, srv.GlobalConfig, true);
-        }
-
-        if (srv.IndividualConfigs.size() > 0)
-        {
-            for (DHCPIndividualConfigMap::const_iterator itHost = srv.IndividualConfigs.begin();
-                 itHost != srv.IndividualConfigs.end(); ++itHost)
-            {
-                DHCPIndividualConfig const &rIndividualConfig = itHost->second;
-
-                xml::ElementNode *pElmConfig = pElmThis->createChild("Config");
-                if (rIndividualConfig.strMACAddress.isNotEmpty())
-                    pElmConfig->setAttribute("MACAddress", rIndividualConfig.strMACAddress);
-                if (rIndividualConfig.strVMName.isNotEmpty())
-                    pElmConfig->setAttribute("vm-name", rIndividualConfig.strVMName);
-                if (rIndividualConfig.uSlot != 0 || rIndividualConfig.strVMName.isNotEmpty())
-                    pElmConfig->setAttribute("slot", rIndividualConfig.strVMName);
-                if (rIndividualConfig.strFixedAddress.isNotEmpty())
-                    pElmConfig->setAttribute("fixedAddress", rIndividualConfig.strFixedAddress);
-                buildDHCPOptions(*pElmConfig, rIndividualConfig, false);
-            }
+            buildDHCPOptions(*pElmOptions, srv.globalConfig, true);
+        }
+
+        for (DHCPGroupConfigVec::const_iterator itGroup = srv.vecGroupConfigs.begin();
+             itGroup != srv.vecGroupConfigs.end(); ++itGroup)
+        {
+            DHCPGroupConfig const &rGroupConfig = *itGroup;
+
+            xml::ElementNode *pElmGroup = pElmThis->createChild("Group");
+            pElmGroup->setAttribute("name", rGroupConfig.strName);
+            buildDHCPOptions(*pElmGroup, rGroupConfig, false);
+
+            for (DHCPGroupConditionVec::const_iterator itCond = rGroupConfig.vecConditions.begin();
+                 itCond != rGroupConfig.vecConditions.end(); ++itCond)
+            {
+                xml::ElementNode *pElmCondition = pElmGroup->createChild("Condition");
+                pElmCondition->setAttribute("inclusive", itCond->fInclusive);
+                pElmCondition->setAttribute("type", (int32_t)itCond->enmType);
+                pElmCondition->setAttribute("value", itCond->strValue);
+            }
+        }
+
+        for (DHCPIndividualConfigMap::const_iterator itHost = srv.mapIndividualConfigs.begin();
+             itHost != srv.mapIndividualConfigs.end(); ++itHost)
+        {
+            DHCPIndividualConfig const &rIndividualConfig = itHost->second;
+
+            xml::ElementNode *pElmConfig = pElmThis->createChild("Config");
+            if (rIndividualConfig.strMACAddress.isNotEmpty())
+                pElmConfig->setAttribute("MACAddress", rIndividualConfig.strMACAddress);
+            if (rIndividualConfig.strVMName.isNotEmpty())
+                pElmConfig->setAttribute("vm-name", rIndividualConfig.strVMName);
+            if (rIndividualConfig.uSlot != 0 || rIndividualConfig.strVMName.isNotEmpty())
+                pElmConfig->setAttribute("slot", rIndividualConfig.uSlot);
+            if (rIndividualConfig.strFixedAddress.isNotEmpty())
+                pElmConfig->setAttribute("fixedAddress", rIndividualConfig.strFixedAddress);
+            buildDHCPOptions(*pElmConfig, rIndividualConfig, false);
         }
      }
@@ -1769,5 +1804,5 @@
 
     /* The DHCP options are <Option> child elements: */
-    for (DhcpOptConstIterator it = rConfig.OptionMap.begin(); it != rConfig.OptionMap.end(); ++it)
+    for (DhcpOptConstIterator it = rConfig.mapOptions.begin(); it != rConfig.mapOptions.end(); ++it)
         if (it->first != DhcpOpt_SubnetMask || !fSkipSubnetMask)
         {
@@ -1795,5 +1830,5 @@
             if (   pelmServer->getAttributeValue("networkName", srv.strNetworkName)
                 && pelmServer->getAttributeValue("IPAddress", srv.strIPAddress)
-                && pelmServer->getAttributeValue("networkMask", srv.GlobalConfig.OptionMap[DhcpOpt_SubnetMask].strValue)
+                && pelmServer->getAttributeValue("networkMask", srv.globalConfig.mapOptions[DhcpOpt_SubnetMask].strValue)
                 && pelmServer->getAttributeValue("lowerIP", srv.strIPLower)
                 && pelmServer->getAttributeValue("upperIP", srv.strIPUpper)
@@ -1804,5 +1839,38 @@
                 xml::NodesLoop          nlOptions(*pelmServer, "Options");
                 while ((pElmOptions = nlOptions.forAllNodes()) != NULL) /** @todo this loop makes no sense, there can only be one \<Options\> child. */
-                    readDHCPOptions(srv.GlobalConfig, *pElmOptions, true /*fIgnoreSubnetMask*/);
+                    readDHCPOptions(srv.globalConfig, *pElmOptions, true /*fIgnoreSubnetMask*/);
+
+                /* Group configurations: */
+                xml::NodesLoop nlGroup(*pelmServer, "Group");
+                const xml::ElementNode *pElmGroup;
+                size_t i = 0;
+                while ((pElmGroup = nlGroup.forAllNodes()) != NULL)
+                {
+                    srv.vecGroupConfigs.push_back(DHCPGroupConfig());
+                    DHCPGroupConfig &rGroupConfig = srv.vecGroupConfigs.back();
+
+                    if (!pElmGroup->getAttributeValue("name", rGroupConfig.strName))
+                        rGroupConfig.strName.printf("Unamed Group #%u", ++i);
+
+                    readDHCPOptions(rGroupConfig, *pElmGroup, false /*fIgnoreSubnetMask*/);
+
+                    xml::NodesLoop nlCondition(*pElmGroup, "Condition");
+                    const xml::ElementNode *pElmCondition;
+                    while ((pElmCondition = nlCondition.forAllNodes()) != NULL)
+                    {
+                        rGroupConfig.vecConditions.push_back(DHCPGroupCondition());
+                        DHCPGroupCondition &rGroupCondition = rGroupConfig.vecConditions.back();
+
+                        if (!pElmCondition->getAttributeValue("inclusive", rGroupCondition.fInclusive))
+                            rGroupCondition.fInclusive = true;
+
+                        int32_t iType;
+                        if (!pElmCondition->getAttributeValue("type", iType))
+                            iType = DHCPGroupConditionType_MAC;
+                        rGroupCondition.enmType = (DHCPGroupConditionType_T)iType;
+
+                        pElmCondition->getAttributeValue("value", rGroupCondition.strValue);
+                    }
+                }
 
                 /* host specific configuration: */
@@ -1829,5 +1897,5 @@
                         strKey.printf("%s/%u", strMACAddress.c_str(), uSlot);
 
-                    DHCPIndividualConfig &rIndividualConfig = srv.IndividualConfigs[strKey];
+                    DHCPIndividualConfig &rIndividualConfig = srv.mapIndividualConfigs[strKey];
                     rIndividualConfig.strMACAddress = strMACAddress;
                     rIndividualConfig.strVMName     = strVMName;
@@ -1837,4 +1905,5 @@
                     readDHCPOptions(rIndividualConfig, *pElmConfig, false /*fIgnoreSubnetMask*/);
                 }
+
                 llDhcpServers.push_back(srv);
             }
@@ -1864,6 +1933,8 @@
     while ((pElmOption = nl2.forAllNodes()) != NULL)
     {
-        DhcpOpt_T OptName;
-        pElmOption->getAttributeValue("name", (uint32_t&)OptName);
+        int32_t iOptName;
+        if (!pElmOption->getAttributeValue("name", iOptName))
+            continue;
+        DhcpOpt_T OptName = (DhcpOpt_T)iOptName;
         if (OptName == DhcpOpt_SubnetMask && fIgnoreSubnetMask)
             continue;
@@ -1876,5 +1947,5 @@
             iOptEnc = DHCPOptionEncoding_Legacy;
 
-        rConfig.OptionMap[OptName] = DhcpOptValue(strValue, (DHCPOptionEncoding_T)iOptEnc);
+        rConfig.mapOptions[OptName] = DhcpOptValue(strValue, (DHCPOptionEncoding_T)iOptEnc);
     } /* end of forall("Option") */
 
@@ -2187,5 +2258,5 @@
 #endif
         srv.strIPAddress = "192.168.56.100";
-        srv.GlobalConfig.OptionMap[DhcpOpt_SubnetMask] = DhcpOptValue("255.255.255.0");
+        srv.globalConfig.mapOptions[DhcpOpt_SubnetMask] = DhcpOptValue("255.255.255.0");
         srv.strIPLower = "192.168.56.101";
         srv.strIPUpper = "192.168.56.254";
Index: /trunk/src/VBox/Runtime/common/net/macstr.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/net/macstr.cpp	(revision 79746)
+++ /trunk/src/VBox/Runtime/common/net/macstr.cpp	(revision 79747)
@@ -51,4 +51,25 @@
 {
     /*
+     * First check if it might be a 12 xdigit string without any separators.
+     */
+    size_t cchValue = strlen(pszValue);
+    if (cchValue >= 12 && memchr(pszValue, ':', 12) == NULL)
+    {
+        bool fOkay = true;
+        for (size_t off = 0; off < 12 && fOkay; off++)
+            fOkay = RT_C_IS_XDIGIT(pszValue[off]);
+        if (fOkay && cchValue > 12)
+            for (size_t off = 12; off < cchValue && fOkay; off++)
+                fOkay = RT_C_IS_SPACE(pszValue[off]);
+        if (fOkay)
+        {
+            int rc = RTStrConvertHexBytes(pszValue, pAddr, sizeof(*pAddr), 0);
+            if (RT_SUCCESS(rc))
+                rc = VINF_SUCCESS;
+            return rc;
+        }
+    }
+
+    /*
      * Not quite sure if I should accept stuff like "08::27:::1" here...
      * The code is accepting "::" patterns now, except for for the first
