Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp	(revision 79770)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp	(revision 79771)
@@ -202,34 +202,196 @@
 
 /**
+ * Helper class for dhcpdHandleAddAndModify
+ */
+class DHCPCmdScope
+{
+    DHCPConfigScope_T               m_enmScope;
+    const char                     *m_pszName;
+    uint8_t                         m_uSlot;
+    ComPtr<IDHCPConfig>             m_ptrConfig;
+    ComPtr<IDHCPGlobalConfig>       m_ptrGlobalConfig;
+    ComPtr<IDHCPGroupConfig>        m_ptrGroupConfig;
+    ComPtr<IDHCPIndividualConfig>   m_ptrIndividualConfig;
+
+public:
+    DHCPCmdScope()
+        : m_enmScope(DHCPConfigScope_Global)
+        , m_pszName(NULL)
+        , m_uSlot(0)
+    {
+    }
+
+    void setGlobal()
+    {
+        m_enmScope = DHCPConfigScope_Global;
+        m_pszName  = NULL;
+        m_uSlot    = 0;
+        resetPointers();
+    }
+
+    void setGroup(const char *pszGroup)
+    {
+        m_enmScope = DHCPConfigScope_Group;
+        m_pszName  = pszGroup;
+        m_uSlot    = 0;
+        resetPointers();
+    }
+
+    void setMachineNIC(const char *pszMachine)
+    {
+        m_enmScope = DHCPConfigScope_MachineNIC;
+        m_pszName  = pszMachine;
+        m_uSlot    = 0;
+        resetPointers();
+    }
+
+    void setMachineSlot(uint8_t uSlot)
+    {
+        Assert(m_enmScope == DHCPConfigScope_MachineNIC);
+        m_uSlot    = uSlot;
+        resetPointers();
+    }
+
+    void setMACAddress(const char *pszMACAddress)
+    {
+        m_enmScope = DHCPConfigScope_MAC;
+        m_pszName  = pszMACAddress;
+        m_uSlot    = 0;
+        resetPointers();
+    }
+
+    ComPtr<IDHCPConfig> &getConfig(ComPtr<IDHCPServer> const &ptrDHCPServer)
+    {
+        if (m_ptrConfig.isNull())
+            CHECK_ERROR2I_STMT(ptrDHCPServer, GetConfig(m_enmScope, Bstr(m_pszName).raw(), m_uSlot, TRUE /*mayAdd*/,
+                                                        m_ptrConfig.asOutParam()), m_ptrConfig.setNull());
+        return m_ptrConfig;
+    }
+
+    ComPtr<IDHCPIndividualConfig> &getIndividual(ComPtr<IDHCPServer> const &ptrDHCPServer)
+    {
+        getConfig(ptrDHCPServer);
+        if (m_ptrIndividualConfig.isNull() && m_ptrConfig.isNotNull())
+        {
+            HRESULT hrc = m_ptrConfig.queryInterfaceTo(m_ptrIndividualConfig.asOutParam());
+            if (FAILED(hrc))
+            {
+                com::GlueHandleComError(m_ptrConfig, "queryInterface", hrc, __FILE__, __LINE__);
+                m_ptrIndividualConfig.setNull();
+            }
+        }
+        return m_ptrIndividualConfig;
+    }
+
+    ComPtr<IDHCPGroupConfig> &getGroup(ComPtr<IDHCPServer> const &ptrDHCPServer)
+    {
+        getConfig(ptrDHCPServer);
+        if (m_ptrGroupConfig.isNull() && m_ptrConfig.isNotNull())
+        {
+            HRESULT hrc = m_ptrConfig.queryInterfaceTo(m_ptrGroupConfig.asOutParam());
+            if (FAILED(hrc))
+            {
+                com::GlueHandleComError(m_ptrConfig, "queryInterface", hrc, __FILE__, __LINE__);
+                m_ptrGroupConfig.setNull();
+            }
+        }
+        return m_ptrGroupConfig;
+    }
+
+    DHCPConfigScope_T getScope() const { return m_enmScope; }
+
+private:
+    void resetPointers()
+    {
+        m_ptrConfig.setNull();
+        m_ptrGlobalConfig.setNull();
+        m_ptrIndividualConfig.setNull();
+        m_ptrGroupConfig.setNull();
+    }
+};
+
+enum
+{
+    DHCP_ADDMOD = 1000,
+    DHCP_ADDMOD_ZAP_OPTIONS,
+    DHCP_ADDMOD_INCL_MAC,
+    DHCP_ADDMOD_EXCL_MAC,
+    DHCP_ADDMOD_DEL_MAC,
+    DHCP_ADDMOD_INCL_MAC_WILD,
+    DHCP_ADDMOD_EXCL_MAC_WILD,
+    DHCP_ADDMOD_DEL_MAC_WILD,
+    DHCP_ADDMOD_INCL_VENDOR,
+    DHCP_ADDMOD_EXCL_VENDOR,
+    DHCP_ADDMOD_DEL_VENDOR,
+    DHCP_ADDMOD_INCL_VENDOR_WILD,
+    DHCP_ADDMOD_EXCL_VENDOR_WILD,
+    DHCP_ADDMOD_DEL_VENDOR_WILD,
+    DHCP_ADDMOD_INCL_USER,
+    DHCP_ADDMOD_EXCL_USER,
+    DHCP_ADDMOD_DEL_USER,
+    DHCP_ADDMOD_INCL_USER_WILD,
+    DHCP_ADDMOD_EXCL_USER_WILD,
+    DHCP_ADDMOD_DEL_USER_WILD,
+    DHCP_ADDMOD_ZAP_CONDITIONS
+};
+
+/**
  * Handles the 'add' and 'modify' subcommands.
  */
 static DECLCALLBACK(RTEXITCODE) dhcpdHandleAddAndModify(PDHCPDCMDCTX pCtx, int argc, char **argv)
 {
-    /*
-     * Parse options.
-     */
     static const RTGETOPTDEF s_aOptions[] =
     {
         DHCPD_CMD_COMMON_OPTION_DEFS(),
-        { "--server-ip",        'a', RTGETOPT_REQ_STRING  },
-        { "--ip",               'a', RTGETOPT_REQ_STRING  },    // deprecated
-        { "-ip",                'a', RTGETOPT_REQ_STRING  },    // deprecated
-        { "--netmask",          'm', RTGETOPT_REQ_STRING  },
-        { "-netmask",           'm', RTGETOPT_REQ_STRING  },    // deprecated
-        { "--lower-ip",         'l', RTGETOPT_REQ_STRING  },
-        { "--lowerip",          'l', RTGETOPT_REQ_STRING  },
-        { "-lowerip",           'l', RTGETOPT_REQ_STRING  },    // deprecated
-        { "--upper-ip",         'u', RTGETOPT_REQ_STRING  },
-        { "--upperip",          'u', RTGETOPT_REQ_STRING  },
-        { "-upperip",           'u', RTGETOPT_REQ_STRING  },    // deprecated
-        { "--enable",           'e', RTGETOPT_REQ_NOTHING },
-        { "-enable",            'e', RTGETOPT_REQ_NOTHING },    // deprecated
-        { "--disable",          'd', RTGETOPT_REQ_NOTHING },
-        { "-disable",           'd', RTGETOPT_REQ_NOTHING },    // deprecated
-        { "--global",           'g', RTGETOPT_REQ_NOTHING },
-        { "--vm",               'M', RTGETOPT_REQ_STRING  },
-        { "--nic",              'n', RTGETOPT_REQ_UINT8   },
-        { "--add-opt",          'A', RTGETOPT_REQ_UINT8   },
-        { "--del-opt",          'D', RTGETOPT_REQ_UINT8   },
+        { "--server-ip",        'a',                            RTGETOPT_REQ_STRING  },
+        { "--ip",               'a',                            RTGETOPT_REQ_STRING  },    // deprecated
+        { "-ip",                'a',                            RTGETOPT_REQ_STRING  },    // deprecated
+        { "--netmask",          'm',                            RTGETOPT_REQ_STRING  },
+        { "-netmask",           'm',                            RTGETOPT_REQ_STRING  },    // deprecated
+        { "--lower-ip",         'l',                            RTGETOPT_REQ_STRING  },
+        { "--lowerip",          'l',                            RTGETOPT_REQ_STRING  },
+        { "-lowerip",           'l',                            RTGETOPT_REQ_STRING  },    // deprecated
+        { "--upper-ip",         'u',                            RTGETOPT_REQ_STRING  },
+        { "--upperip",          'u',                            RTGETOPT_REQ_STRING  },
+        { "-upperip",           'u',                            RTGETOPT_REQ_STRING  },    // deprecated
+        { "--enable",           'e',                            RTGETOPT_REQ_NOTHING },
+        { "-enable",            'e',                            RTGETOPT_REQ_NOTHING },    // deprecated
+        { "--disable",          'd',                            RTGETOPT_REQ_NOTHING },
+        { "-disable",           'd',                            RTGETOPT_REQ_NOTHING },    // deprecated
+        { "--global",           'g',                            RTGETOPT_REQ_NOTHING },
+        { "--group",            'G',                            RTGETOPT_REQ_STRING  },
+        { "--mac-address",      'E',                            RTGETOPT_REQ_MACADDR },
+        { "--vm",               'M',                            RTGETOPT_REQ_STRING  },
+        { "--nic",              'n',                            RTGETOPT_REQ_UINT8   },
+        { "--set-opt",          's',                            RTGETOPT_REQ_UINT8   },
+        { "--set-opt-hex",      'x',                            RTGETOPT_REQ_UINT8   },
+        { "--del-opt",          'D',                            RTGETOPT_REQ_UINT8   },
+        { "--zap-options",      DHCP_ADDMOD_ZAP_OPTIONS,        RTGETOPT_REQ_NOTHING },
+        { "--min-lease-time",   'q' ,                           RTGETOPT_REQ_UINT32  },
+        { "--default-lease-time", 'L' ,                         RTGETOPT_REQ_UINT32  },
+        { "--max-lease-time",   'Q' ,                           RTGETOPT_REQ_UINT32  },
+        { "--remove-config",    'R',                            RTGETOPT_REQ_NOTHING },
+        { "--fixed-address",    'f',                            RTGETOPT_REQ_STRING  },
+        /* group conditions: */
+        { "--incl-mac",         DHCP_ADDMOD_INCL_MAC,           RTGETOPT_REQ_STRING  },
+        { "--excl-mac",         DHCP_ADDMOD_EXCL_MAC,           RTGETOPT_REQ_STRING  },
+        { "--del-mac",          DHCP_ADDMOD_DEL_MAC,            RTGETOPT_REQ_STRING  },
+        { "--incl-mac-wild",    DHCP_ADDMOD_INCL_MAC_WILD,      RTGETOPT_REQ_STRING  },
+        { "--excl-mac-wild",    DHCP_ADDMOD_EXCL_MAC_WILD,      RTGETOPT_REQ_STRING  },
+        { "--del-mac-wild",     DHCP_ADDMOD_DEL_MAC_WILD,       RTGETOPT_REQ_STRING  },
+        { "--incl-vendor",      DHCP_ADDMOD_INCL_VENDOR,        RTGETOPT_REQ_STRING  },
+        { "--excl-vendor",      DHCP_ADDMOD_EXCL_VENDOR,        RTGETOPT_REQ_STRING  },
+        { "--del-vendor",       DHCP_ADDMOD_DEL_VENDOR,         RTGETOPT_REQ_STRING  },
+        { "--incl-vendor-wild", DHCP_ADDMOD_INCL_VENDOR_WILD,   RTGETOPT_REQ_STRING  },
+        { "--excl-vendor-wild", DHCP_ADDMOD_EXCL_VENDOR_WILD,   RTGETOPT_REQ_STRING  },
+        { "--del-vendor-wild",  DHCP_ADDMOD_DEL_VENDOR_WILD,    RTGETOPT_REQ_STRING  },
+        { "--incl-user",        DHCP_ADDMOD_INCL_USER,          RTGETOPT_REQ_STRING  },
+        { "--excl-user",        DHCP_ADDMOD_EXCL_USER,          RTGETOPT_REQ_STRING  },
+        { "--del-user",         DHCP_ADDMOD_DEL_USER,           RTGETOPT_REQ_STRING  },
+        { "--incl-user-wild",   DHCP_ADDMOD_INCL_USER_WILD,     RTGETOPT_REQ_STRING  },
+        { "--excl-user-wild",   DHCP_ADDMOD_EXCL_USER_WILD,     RTGETOPT_REQ_STRING  },
+        { "--del-user-wild",    DHCP_ADDMOD_DEL_USER_WILD,      RTGETOPT_REQ_STRING  },
+        { "--zap-conditions",   DHCP_ADDMOD_ZAP_CONDITIONS,     RTGETOPT_REQ_NOTHING },
+        /* obsolete, to be removed: */
         { "--id",               'i', RTGETOPT_REQ_UINT8   },    // obsolete, backwards compatibility only.
         { "--value",            'p', RTGETOPT_REQ_STRING  },    // obsolete, backwards compatibility only.
@@ -239,264 +401,508 @@
     };
 
-    const char       *pszServerIp           = NULL;
-    const char       *pszNetmask            = NULL;
-    const char       *pszLowerIp            = NULL;
-    const char       *pszUpperIp            = NULL;
-    int               fEnabled              = -1;
-
-    DhcpOpts          GlobalDhcpOptions;
-    DhcpOptIds        GlobalDhcpOptions2Delete;
-    VmSlot2OptionsM   VmSlot2Options;
-    VmSlot2OptionIdsM VmSlot2Options2Delete;
-
-    const char       *pszVmName             = NULL;
-    uint8_t           u8Slot                = 0;
-    DhcpOpts         *pScopeOptions         = &GlobalDhcpOptions;
-    DhcpOptIds       *pScopeOptions2Delete  = &GlobalDhcpOptions2Delete;
-
-    bool              fNeedValueOrRemove    = false; /* Only used with --id; remove in 6.1+ */
-    uint8_t           u8OptId               = 0;     /* Only used too keep --id for following --value/--remove. remove in 6.1+ */
-
-    RTGETOPTSTATE GetState;
-    int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
-    AssertRCReturn(vrc, RTEXITCODE_FAILURE);
-
-    RTGETOPTUNION ValueUnion;
-    while ((vrc = RTGetOpt(&GetState, &ValueUnion)))
-    {
-        switch (vrc)
-        {
-            DHCPD_CMD_COMMON_OPTION_CASES(pCtx, vrc, &ValueUnion);
-            case 'a':   // --server-ip
-                pszServerIp = ValueUnion.psz;
-                break;
-            case 'm':   // --netmask
-                pszNetmask = ValueUnion.psz;
-                break;
-            case 'l':   // --lower-ip
-                pszLowerIp = ValueUnion.psz;
-                break;
-            case 'u':   // --upper-ip
-                pszUpperIp = ValueUnion.psz;
-                break;
-            case 'e':   // --enable
-                fEnabled = 1;
-                break;
-            case 'd':   // --disable
-                fEnabled = 0;
-                break;
-
-            case 'g':   // --global     Sets the option scope to 'global'.
-                if (fNeedValueOrRemove)
-                    return errorSyntax("Incomplete option sequence preseeding '--global'");
-                pScopeOptions         = &GlobalDhcpOptions;
-                pScopeOptions2Delete  = &GlobalDhcpOptions2Delete;
-                break;
-
-            case 'M':   // --vm         Sets the option scope to ValueUnion.psz + 0.
-                if (fNeedValueOrRemove)
-                    return errorSyntax("Incomplete option sequence preseeding '--vm'");
-                pszVmName = ValueUnion.psz;
-                u8Slot    = 0;
-                pScopeOptions        = &VmSlot2Options[VmNameSlotKey(pszVmName, u8Slot)];
-                pScopeOptions2Delete = &VmSlot2Options2Delete[VmNameSlotKey(pszVmName, u8Slot)];
-                break;
-
-            case 'n':   // --nic        Sets the option scope to pszVmName + (ValueUnion.u8 - 1).
-                if (!pszVmName)
-                    return errorSyntax("--nic option requires a --vm preceeding selecting the VM it should apply to");
-                if (fNeedValueOrRemove)
-                    return errorSyntax("Incomplete option sequence preseeding '--nic=%u", ValueUnion.u8);
-                u8Slot = ValueUnion.u8;
-                if (u8Slot < 1)
-                    return errorSyntax("invalid NIC number: %u", u8Slot);
-                --u8Slot;
-                pScopeOptions        = &VmSlot2Options[VmNameSlotKey(pszVmName, u8Slot)];
-                pScopeOptions2Delete = &VmSlot2Options2Delete[VmNameSlotKey(pszVmName, u8Slot)];
-                break;
-
-            case 'A':   // --add-opt num hexvalue
+    /*
+     * Parse the arguments in two passes:
+     *
+     *  1. Validate the command line and establish the IDHCPServer settings.
+     *  2. Execute the various IDHCPConfig settings changes.
+     *
+     * This is considered simpler than duplicating the command line instructions
+     * into elaborate structures and executing these.
+     */
+    RTEXITCODE          rcExit = RTEXITCODE_SUCCESS;
+    ComPtr<IDHCPServer> ptrDHCPServer;
+    for (size_t iPass = 0; iPass < 2; iPass++)
+    {
+        const char         *pszServerIp         = NULL;
+        const char         *pszNetmask          = NULL;
+        const char         *pszLowerIp          = NULL;
+        const char         *pszUpperIp          = NULL;
+        int                 fEnabled            = -1;
+
+        DHCPCmdScope        Scope;
+        char                szMACAddress[32];
+
+        bool                fNeedValueOrRemove  = false; /* Only used with --id; remove in 6.1+ */
+        uint8_t             u8OptId             = 0;     /* Only used too keep --id for following --value/--remove. remove in 6.1+ */
+
+        RTGETOPTSTATE GetState;
+        int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
+        AssertRCReturn(vrc, RTEXITCODE_FAILURE);
+
+        RTGETOPTUNION ValueUnion;
+        while ((vrc = RTGetOpt(&GetState, &ValueUnion)))
+        {
+            switch (vrc)
             {
-                uint8_t const idAddOpt = ValueUnion.u8;
-                vrc = RTGetOptFetchValue(&GetState, &ValueUnion, RTGETOPT_REQ_STRING);
-                if (RT_FAILURE(vrc))
-                    return errorFetchValue(1, "--add-opt", vrc, &ValueUnion);
-                pScopeOptions->push_back(DhcpOptSpec((DhcpOpt_T)idAddOpt, Utf8Str(ValueUnion.psz)));
-                break;
+                DHCPD_CMD_COMMON_OPTION_CASES(pCtx, vrc, &ValueUnion);
+                case 'a':   // --server-ip
+                    pszServerIp = ValueUnion.psz;
+                    break;
+                case 'm':   // --netmask
+                    pszNetmask = ValueUnion.psz;
+                    break;
+                case 'l':   // --lower-ip
+                    pszLowerIp = ValueUnion.psz;
+                    break;
+                case 'u':   // --upper-ip
+                    pszUpperIp = ValueUnion.psz;
+                    break;
+                case 'e':   // --enable
+                    fEnabled = 1;
+                    break;
+                case 'd':   // --disable
+                    fEnabled = 0;
+                    break;
+
+                /*
+                 * Configuration selection:
+                 */
+                case 'g':   // --global     Sets the option scope to 'global'.
+                    if (fNeedValueOrRemove)
+                        return errorSyntax("Incomplete option sequence preseeding '--global'");
+                    Scope.setGlobal();
+                    break;
+
+                case 'G':   // --group
+                    if (fNeedValueOrRemove)
+                        return errorSyntax("Incomplete option sequence preseeding '--group'");
+                    if (!*ValueUnion.psz)
+                        return errorSyntax("Group name cannot be empty");
+                    Scope.setGroup(ValueUnion.psz);
+                    break;
+
+                case 'E':   // --mac-address
+                    if (fNeedValueOrRemove)
+                        return errorSyntax("Incomplete option sequence preseeding '--mac-address'");
+                    RTStrPrintf(szMACAddress, sizeof(szMACAddress), "%RTmac", &ValueUnion.MacAddr);
+                    Scope.setMACAddress(szMACAddress);
+                    break;
+
+                case 'M':   // --vm         Sets the option scope to ValueUnion.psz + 0.
+                    if (fNeedValueOrRemove)
+                        return errorSyntax("Incomplete option sequence preseeding '--vm'");
+                    Scope.setMachineNIC(ValueUnion.psz);
+                    break;
+
+                case 'n':   // --nic        Sets the option scope to pszVmName + (ValueUnion.u8 - 1).
+                    if (Scope.getScope() != DHCPConfigScope_MachineNIC)
+                        return errorSyntax("--nic option requires a --vm preceeding selecting the VM it should apply to");
+                    if (fNeedValueOrRemove)
+                        return errorSyntax("Incomplete option sequence preseeding '--nic=%u", ValueUnion.u8);
+                    if (ValueUnion.u8 < 1)
+                        return errorSyntax("invalid NIC number: %u", ValueUnion.u8);
+                    Scope.setMachineSlot(ValueUnion.u8 - 1);
+                    break;
+
+                /*
+                 * Modify configuration:
+                 */
+                case 's':   // --set-opt num stringvalue
+                {
+                    uint8_t const idAddOpt = ValueUnion.u8;
+                    vrc = RTGetOptFetchValue(&GetState, &ValueUnion, RTGETOPT_REQ_STRING);
+                    if (RT_FAILURE(vrc))
+                        return errorFetchValue(1, "--set-opt", vrc, &ValueUnion);
+                    if (iPass == 1)
+                    {
+                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
+                        if (ptrConfig.isNull())
+                            return RTEXITCODE_FAILURE;
+                        CHECK_ERROR2I_STMT(ptrConfig, SetOption((DhcpOpt_T)idAddOpt, DHCPOptionEncoding_Legacy,
+                                                                Bstr(ValueUnion.psz).raw()), rcExit = RTEXITCODE_FAILURE);
+                    }
+                    break;
+                }
+
+                case 'x':   // --set-opt-hex num hex-string
+                {
+                    uint8_t const idAddOpt = ValueUnion.u8;
+                    vrc = RTGetOptFetchValue(&GetState, &ValueUnion, RTGETOPT_REQ_STRING);
+                    if (RT_FAILURE(vrc))
+                        return errorFetchValue(1, "--set-opt-hex", vrc, &ValueUnion);
+                    uint8_t abBuf[256];
+                    size_t cbRet;
+                    vrc = RTStrConvertHexBytesEx(ValueUnion.psz, abBuf, sizeof(abBuf), RTSTRCONVERTHEXBYTES_F_SEP_COLON,
+                                                 NULL, &cbRet);
+                    if (RT_FAILURE(vrc))
+                        return errorArgument("Malformed hex string given to --set-opt-hex %u: %s\n", idAddOpt, ValueUnion.psz);
+                    if (iPass == 1)
+                    {
+                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
+                        if (ptrConfig.isNull())
+                            return RTEXITCODE_FAILURE;
+                        CHECK_ERROR2I_STMT(ptrConfig, SetOption((DhcpOpt_T)idAddOpt, DHCPOptionEncoding_Hex,
+                                                                Bstr(ValueUnion.psz).raw()), rcExit = RTEXITCODE_FAILURE);
+                    }
+                    break;
+                }
+
+                case 'D':   // --del-opt num
+                    if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
+                        return errorSyntax("--del-opt does not apply to the 'add' subcommand");
+                    if (iPass == 1)
+                    {
+                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
+                        if (ptrConfig.isNull())
+                            return RTEXITCODE_FAILURE;
+                        CHECK_ERROR2I_STMT(ptrConfig, RemoveOption((DhcpOpt_T)ValueUnion.u8), rcExit = RTEXITCODE_FAILURE);
+                    }
+                    break;
+
+                case DHCP_ADDMOD_ZAP_OPTIONS:
+                    if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
+                        return errorSyntax("--zap-options does not apply to the 'add' subcommand");
+                    if (iPass == 1)
+                    {
+                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
+                        if (ptrConfig.isNull())
+                            return RTEXITCODE_FAILURE;
+                        CHECK_ERROR2I_STMT(ptrConfig, RemoveAllOptions(), rcExit = RTEXITCODE_FAILURE);
+                    }
+                    break;
+
+                case 'q':   // --min-lease-time
+                    if (iPass == 1)
+                    {
+                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
+                        if (ptrConfig.isNull())
+                            return RTEXITCODE_FAILURE;
+                        CHECK_ERROR2I_STMT(ptrConfig, COMSETTER(MinLeaseTime)(ValueUnion.u32), rcExit = RTEXITCODE_FAILURE);
+                    }
+                    break;
+
+                case 'L':   // --default-lease-time
+                    if (iPass == 1)
+                    {
+                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
+                        if (ptrConfig.isNull())
+                            return RTEXITCODE_FAILURE;
+                        CHECK_ERROR2I_STMT(ptrConfig, COMSETTER(DefaultLeaseTime)(ValueUnion.u32), rcExit = RTEXITCODE_FAILURE);
+                    }
+                    break;
+
+                case 'Q':   // --max-lease-time
+                    if (iPass == 1)
+                    {
+                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
+                        if (ptrConfig.isNull())
+                            return RTEXITCODE_FAILURE;
+                        CHECK_ERROR2I_STMT(ptrConfig, COMSETTER(MaxLeaseTime)(ValueUnion.u32), rcExit = RTEXITCODE_FAILURE);
+                    }
+                    break;
+
+                case 'R':   // --remove-config
+                    if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
+                        return errorSyntax("--remove-config does not apply to the 'add' subcommand");
+                    if (Scope.getScope() == DHCPConfigScope_Global)
+                        return errorSyntax("--remove-config cannot be applied to the global config");
+                    if (iPass == 1)
+                    {
+                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
+                        if (ptrConfig.isNull())
+                            return RTEXITCODE_FAILURE;
+                        CHECK_ERROR2I_STMT(ptrConfig, Remove(), rcExit = RTEXITCODE_FAILURE);
+                    }
+                    Scope.setGlobal();
+                    break;
+
+                case 'f':   // --fixed-address
+                    if (Scope.getScope() != DHCPConfigScope_MachineNIC && Scope.getScope() != DHCPConfigScope_MAC)
+                        return errorSyntax("--fixed-address can only be applied to a VM NIC or an MAC address");
+                    if (iPass == 1)
+                    {
+                        ComPtr<IDHCPIndividualConfig> &ptrIndividualConfig = Scope.getIndividual(ptrDHCPServer);
+                        if (ptrIndividualConfig.isNull())
+                            return RTEXITCODE_FAILURE;
+                        CHECK_ERROR2I_STMT(ptrIndividualConfig, COMSETTER(FixedAddress)(Bstr(ValueUnion.psz).raw()),
+                                           rcExit = RTEXITCODE_FAILURE);
+                    }
+                    break;
+
+                /*
+                 * Group conditions:
+                 */
+                case DHCP_ADDMOD_INCL_MAC:
+                case DHCP_ADDMOD_EXCL_MAC:
+                case DHCP_ADDMOD_DEL_MAC:
+                case DHCP_ADDMOD_INCL_MAC_WILD:
+                case DHCP_ADDMOD_EXCL_MAC_WILD:
+                case DHCP_ADDMOD_DEL_MAC_WILD:
+                case DHCP_ADDMOD_INCL_VENDOR:
+                case DHCP_ADDMOD_EXCL_VENDOR:
+                case DHCP_ADDMOD_DEL_VENDOR:
+                case DHCP_ADDMOD_INCL_VENDOR_WILD:
+                case DHCP_ADDMOD_EXCL_VENDOR_WILD:
+                case DHCP_ADDMOD_DEL_VENDOR_WILD:
+                case DHCP_ADDMOD_INCL_USER:
+                case DHCP_ADDMOD_EXCL_USER:
+                case DHCP_ADDMOD_DEL_USER:
+                case DHCP_ADDMOD_INCL_USER_WILD:
+                case DHCP_ADDMOD_EXCL_USER_WILD:
+                case DHCP_ADDMOD_DEL_USER_WILD:
+                {
+                    if (Scope.getScope() != DHCPConfigScope_Group)
+                        return errorSyntax("A group must be selected to perform condition alterations.");
+                    if (!*ValueUnion.psz)
+                        return errorSyntax("Condition value cannot be empty"); /* or can it? */
+                    if (iPass != 1)
+                        break;
+
+                    DHCPGroupConditionType enmType;
+                    switch (vrc)
+                    {
+                        case DHCP_ADDMOD_INCL_MAC: case DHCP_ADDMOD_EXCL_MAC: case DHCP_ADDMOD_DEL_MAC:
+                            enmType = DHCPGroupConditionType_MAC;
+                            break;
+                        case DHCP_ADDMOD_INCL_MAC_WILD: case DHCP_ADDMOD_EXCL_MAC_WILD: case DHCP_ADDMOD_DEL_MAC_WILD:
+                            enmType = DHCPGroupConditionType_MACWildcard;
+                            break;
+                        case DHCP_ADDMOD_INCL_VENDOR: case DHCP_ADDMOD_EXCL_VENDOR: case DHCP_ADDMOD_DEL_VENDOR:
+                            enmType = DHCPGroupConditionType_vendorClassID;
+                            break;
+                        case DHCP_ADDMOD_INCL_VENDOR_WILD: case DHCP_ADDMOD_EXCL_VENDOR_WILD: case DHCP_ADDMOD_DEL_VENDOR_WILD:
+                            enmType = DHCPGroupConditionType_vendorClassIDWildcard;
+                            break;
+                        case DHCP_ADDMOD_INCL_USER: case DHCP_ADDMOD_EXCL_USER: case DHCP_ADDMOD_DEL_USER:
+                            enmType = DHCPGroupConditionType_userClassID;
+                            break;
+                        case DHCP_ADDMOD_INCL_USER_WILD: case DHCP_ADDMOD_EXCL_USER_WILD: case DHCP_ADDMOD_DEL_USER_WILD:
+                            enmType = DHCPGroupConditionType_userClassIDWildcard;
+                            break;
+                        default:
+                            AssertFailedReturn(RTEXITCODE_FAILURE);
+                    }
+
+                    int fInclusive;
+                    switch (vrc)
+                    {
+                        case DHCP_ADDMOD_DEL_MAC:
+                        case DHCP_ADDMOD_DEL_MAC_WILD:
+                        case DHCP_ADDMOD_DEL_USER:
+                        case DHCP_ADDMOD_DEL_USER_WILD:
+                        case DHCP_ADDMOD_DEL_VENDOR:
+                        case DHCP_ADDMOD_DEL_VENDOR_WILD:
+                            fInclusive = -1;
+                            break;
+                        case DHCP_ADDMOD_EXCL_MAC:
+                        case DHCP_ADDMOD_EXCL_MAC_WILD:
+                        case DHCP_ADDMOD_EXCL_USER:
+                        case DHCP_ADDMOD_EXCL_USER_WILD:
+                        case DHCP_ADDMOD_EXCL_VENDOR:
+                        case DHCP_ADDMOD_EXCL_VENDOR_WILD:
+                            fInclusive = 0;
+                            break;
+                        case DHCP_ADDMOD_INCL_MAC:
+                        case DHCP_ADDMOD_INCL_MAC_WILD:
+                        case DHCP_ADDMOD_INCL_USER:
+                        case DHCP_ADDMOD_INCL_USER_WILD:
+                        case DHCP_ADDMOD_INCL_VENDOR:
+                        case DHCP_ADDMOD_INCL_VENDOR_WILD:
+                            fInclusive = 1;
+                            break;
+                        default:
+                            AssertFailedReturn(RTEXITCODE_FAILURE);
+                    }
+
+                    ComPtr<IDHCPGroupConfig> &ptrGroupConfig = Scope.getGroup(ptrDHCPServer);
+                    if (ptrGroupConfig.isNull())
+                        return RTEXITCODE_FAILURE;
+                    if (fInclusive >= 0)
+                    {
+                        ComPtr<IDHCPGroupCondition> ptrCondition;
+                        CHECK_ERROR2I_STMT(ptrGroupConfig, AddCondition((BOOL)fInclusive, enmType, Bstr(ValueUnion.psz).raw(),
+                                                                        ptrCondition.asOutParam()), rcExit = RTEXITCODE_FAILURE);
+                    }
+                    else
+                    {
+                        com::SafeIfaceArray<IDHCPGroupCondition> Conditions;
+                        CHECK_ERROR2I_STMT(ptrGroupConfig, COMGETTER(Conditions)(ComSafeArrayAsOutParam(Conditions)),
+                                           rcExit = RTEXITCODE_FAILURE; break);
+                        bool fFound = false;
+                        for (size_t iCond = 0; iCond < Conditions.size(); iCond++)
+                            {
+                                DHCPGroupConditionType_T enmCurType = DHCPGroupConditionType_MAC;
+                                CHECK_ERROR2I_STMT(Conditions[iCond], COMGETTER(Type)(&enmCurType),
+                                                   rcExit = RTEXITCODE_FAILURE; continue);
+                                if (enmCurType == enmType)
+                                {
+                                    Bstr bstrValue;
+                                    CHECK_ERROR2I_STMT(Conditions[iCond], COMGETTER(Value)(bstrValue.asOutParam()),
+                                                      rcExit = RTEXITCODE_FAILURE; continue);
+                                    if (RTUtf16CmpUtf8(bstrValue.raw(), ValueUnion.psz) == 0)
+                                    {
+                                        CHECK_ERROR2I_STMT(Conditions[iCond], Remove(), rcExit = RTEXITCODE_FAILURE);
+                                        fFound = true;
+                                    }
+                                }
+                            }
+                        if (!fFound)
+                            rcExit = RTMsgErrorExitFailure("Could not find any condition of type %d with value '%s' to delete",
+                                                           enmType, ValueUnion.psz);
+                    }
+                    break;
+                }
+
+                case DHCP_ADDMOD_ZAP_CONDITIONS:
+                    if (Scope.getScope() != DHCPConfigScope_Group)
+                        return errorSyntax("--zap-conditions can only be with a group selected");
+                    if (iPass == 1)
+                    {
+                        ComPtr<IDHCPGroupConfig> &ptrGroupConfig = Scope.getGroup(ptrDHCPServer);
+                        if (ptrGroupConfig.isNull())
+                            return RTEXITCODE_FAILURE;
+                        CHECK_ERROR2I_STMT(ptrGroupConfig, RemoveAllConditions(), rcExit = RTEXITCODE_FAILURE);
+                    }
+                    break;
+
+                /*
+                 * For backwards compatibility. Remove in 6.1 or later.
+                 */
+
+                case 'o':   // --options - obsolete, ignored.
+                    break;
+
+                case 'i':   // --id
+                    if (fNeedValueOrRemove)
+                        return errorSyntax("Incomplete option sequence preseeding '--id=%u", ValueUnion.u8);
+                    u8OptId = ValueUnion.u8;
+                    fNeedValueOrRemove = true;
+                    break;
+
+                case 'p':   // --value
+                    if (!fNeedValueOrRemove)
+                        return errorSyntax("--value without --id=dhcp-opt-no");
+                    if (iPass == 1)
+                    {
+                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
+                        if (ptrConfig.isNull())
+                            return RTEXITCODE_FAILURE;
+                        CHECK_ERROR2I_STMT(ptrConfig, SetOption((DhcpOpt_T)u8OptId, DHCPOptionEncoding_Legacy,
+                                                                Bstr(ValueUnion.psz).raw()), rcExit = RTEXITCODE_FAILURE);
+                    }
+                    fNeedValueOrRemove = false;
+                    break;
+
+                case 'r':   // --remove
+                    if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
+                        return errorSyntax("--remove does not apply to the 'add' subcommand");
+                    if (!fNeedValueOrRemove)
+                        return errorSyntax("--remove without --id=dhcp-opt-no");
+
+                    if (iPass == 1)
+                    {
+                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
+                        if (ptrConfig.isNull())
+                            return RTEXITCODE_FAILURE;
+                        CHECK_ERROR2I_STMT(ptrConfig, RemoveOption((DhcpOpt_T)u8OptId), rcExit = RTEXITCODE_FAILURE);
+                    }
+                    fNeedValueOrRemove = false;
+                    break;
+
+                default:
+                    return errorGetOpt(vrc, &ValueUnion);
             }
-
-            case 'D':   // --del-opt num
-                if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
-                    return errorSyntax("--del-opt does not apply to the 'add' subcommand");
-                pScopeOptions2Delete->push_back((DhcpOpt_T)ValueUnion.u8);
-                break;
-
-            /*
-             * For backwards compatibility. Remove in 6.1 or later.
-             */
-
-            case 'o':   // --options - obsolete, ignored.
-                break;
-
-            case 'i':   // --id
-                if (fNeedValueOrRemove)
-                    return errorSyntax("Incomplete option sequence preseeding '--id=%u", ValueUnion.u8);
-                u8OptId = ValueUnion.u8;
-                fNeedValueOrRemove = true;
-                break;
-
-            case 'p':   // --value
-                if (!fNeedValueOrRemove)
-                    return errorSyntax("--value without --id=dhcp-opt-no");
-                pScopeOptions->push_back(DhcpOptSpec((DhcpOpt_T)u8OptId, Utf8Str(ValueUnion.psz)));
-                fNeedValueOrRemove = false;
-                break;
-
-            case 'r':   // --remove
-                if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
-                    return errorSyntax("--remove does not apply to the 'add' subcommand");
-                if (!fNeedValueOrRemove)
-                    return errorSyntax("--remove without --id=dhcp-opt-no");
-                pScopeOptions2Delete->push_back((DhcpOpt_T)u8OptId);
-                /** @todo remove from pScopeOptions */
-                fNeedValueOrRemove = false;
-                break;
-
-            default:
-                return errorGetOpt(vrc, &ValueUnion);
-        }
-    }
-
-    /*
-     * Ensure we've got mandatory options and supply defaults
-     * where needed (modify case)
-     */
-    if (!pCtx->pszNetwork && !pCtx->pszInterface)
-        return errorSyntax("You need to specify either --network or --interface to identify the DHCP server");
-
-    if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
-    {
+        }
+
+        if (iPass != 0)
+            break;
+
+        /*
+         * Ensure we've got mandatory options and supply defaults
+         * where needed (modify case)
+         */
+        if (!pCtx->pszNetwork && !pCtx->pszInterface)
+            return errorSyntax("You need to specify either --network or --interface to identify the DHCP server");
+
+        if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
+        {
+            RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
+            if (!pszServerIp)
+                rcExit = errorSyntax("Missing required option: --ip");
+            if (!pszNetmask)
+                rcExit = errorSyntax("Missing required option: --netmask");
+            if (!pszLowerIp)
+                rcExit = errorSyntax("Missing required option: --lowerip");
+            if (!pszUpperIp)
+                rcExit = errorSyntax("Missing required option: --upperip");
+            if (rcExit != RTEXITCODE_SUCCESS)
+                return rcExit;
+        }
+
+        /*
+         * Find or create the server.
+         */
+        HRESULT rc;
+        Bstr NetName;
+        if (!pCtx->pszNetwork)
+        {
+            ComPtr<IHost> host;
+            CHECK_ERROR(pCtx->pArg->virtualBox, COMGETTER(Host)(host.asOutParam()));
+
+            ComPtr<IHostNetworkInterface> hif;
+            CHECK_ERROR(host, FindHostNetworkInterfaceByName(Bstr(pCtx->pszInterface).mutableRaw(), hif.asOutParam()));
+            if (FAILED(rc))
+                return errorArgument("Could not find interface '%s'", pCtx->pszInterface);
+
+            CHECK_ERROR(hif, COMGETTER(NetworkName) (NetName.asOutParam()));
+            if (FAILED(rc))
+                return errorArgument("Could not get network name for the interface '%s'", pCtx->pszInterface);
+        }
+        else
+        {
+            NetName = Bstr(pCtx->pszNetwork);
+        }
+
+        rc = pCtx->pArg->virtualBox->FindDHCPServerByNetworkName(NetName.mutableRaw(), ptrDHCPServer.asOutParam());
+        if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
+        {
+            if (SUCCEEDED(rc))
+                return errorArgument("DHCP server already exists");
+
+            CHECK_ERROR(pCtx->pArg->virtualBox, CreateDHCPServer(NetName.mutableRaw(), ptrDHCPServer.asOutParam()));
+            if (FAILED(rc))
+                return errorArgument("Failed to create the DHCP server");
+        }
+        else if (FAILED(rc))
+            return errorArgument("DHCP server does not exist");
+
+        /*
+         * Apply IDHCPServer settings:
+         */
+        HRESULT hrc;
         RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
-        if (!pszServerIp)
-            rcExit = errorSyntax("Missing required option: --ip");
-        if (!pszNetmask)
-            rcExit = errorSyntax("Missing required option: --netmask");
-        if (!pszLowerIp)
-            rcExit = errorSyntax("Missing required option: --lowerip");
-        if (!pszUpperIp)
-            rcExit = errorSyntax("Missing required option: --upperip");
-        if (rcExit != RTEXITCODE_SUCCESS)
-            return rcExit;
-    }
-
-    /*
-     * Find or create the server.
-     */
-    HRESULT rc;
-    Bstr NetName;
-    if (!pCtx->pszNetwork)
-    {
-        ComPtr<IHost> host;
-        CHECK_ERROR(pCtx->pArg->virtualBox, COMGETTER(Host)(host.asOutParam()));
-
-        ComPtr<IHostNetworkInterface> hif;
-        CHECK_ERROR(host, FindHostNetworkInterfaceByName(Bstr(pCtx->pszInterface).mutableRaw(), hif.asOutParam()));
-        if (FAILED(rc))
-            return errorArgument("Could not find interface '%s'", pCtx->pszInterface);
-
-        CHECK_ERROR(hif, COMGETTER(NetworkName) (NetName.asOutParam()));
-        if (FAILED(rc))
-            return errorArgument("Could not get network name for the interface '%s'", pCtx->pszInterface);
-    }
-    else
-    {
-        NetName = Bstr(pCtx->pszNetwork);
-    }
-
-    ComPtr<IDHCPServer> svr;
-    rc = pCtx->pArg->virtualBox->FindDHCPServerByNetworkName(NetName.mutableRaw(), svr.asOutParam());
-    if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
-    {
-        if (SUCCEEDED(rc))
-            return errorArgument("DHCP server already exists");
-
-        CHECK_ERROR(pCtx->pArg->virtualBox, CreateDHCPServer(NetName.mutableRaw(), svr.asOutParam()));
-        if (FAILED(rc))
-            return errorArgument("Failed to create the DHCP server");
-    }
-    else if (FAILED(rc))
-        return errorArgument("DHCP server does not exist");
-
-    /*
-     * Apply settings.
-     */
-    HRESULT hrc;
-    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
-    if (pszServerIp || pszNetmask || pszLowerIp || pszUpperIp)
-    {
-        Bstr bstrServerIp(pszServerIp);
-        Bstr bstrNetmask(pszNetmask);
-        Bstr bstrLowerIp(pszLowerIp);
-        Bstr bstrUpperIp(pszUpperIp);
-
-        if (!pszServerIp)
-        {
-            CHECK_ERROR2_RET(hrc, svr, COMGETTER(IPAddress)(bstrServerIp.asOutParam()), RTEXITCODE_FAILURE);
-        }
-        if (!pszNetmask)
-        {
-            CHECK_ERROR2_RET(hrc, svr, COMGETTER(NetworkMask)(bstrNetmask.asOutParam()), RTEXITCODE_FAILURE);
-        }
-        if (!pszLowerIp)
-        {
-            CHECK_ERROR2_RET(hrc, svr, COMGETTER(LowerIP)(bstrLowerIp.asOutParam()), RTEXITCODE_FAILURE);
-        }
-        if (!pszUpperIp)
-        {
-            CHECK_ERROR2_RET(hrc, svr, COMGETTER(UpperIP)(bstrUpperIp.asOutParam()), RTEXITCODE_FAILURE);
-        }
-
-        CHECK_ERROR2_STMT(hrc, svr, SetConfiguration(bstrServerIp.raw(), bstrNetmask.raw(), bstrLowerIp.raw(), bstrUpperIp.raw()),
-                          rcExit = errorArgument("Failed to set configuration (%ls, %ls, %ls, %ls)", bstrServerIp.raw(),
-                                                 bstrNetmask.raw(), bstrLowerIp.raw(), bstrUpperIp.raw()));
-    }
-
-    if (fEnabled >= 0)
-    {
-        CHECK_ERROR2_STMT(hrc, svr, COMSETTER(Enabled)((BOOL)fEnabled), rcExit = RTEXITCODE_FAILURE);
-    }
-
-    /* Remove options: */
-    for (DhcpOptIdIterator itOptId = GlobalDhcpOptions2Delete.begin(); itOptId != GlobalDhcpOptions2Delete.end(); ++itOptId)
-    {
-        CHECK_ERROR2_STMT(hrc, svr, RemoveGlobalOption(*itOptId), rcExit = RTEXITCODE_FAILURE);
-    }
-
-    for (VmSlot2OptionIdsIterator itIdVector = VmSlot2Options2Delete.begin();
-         itIdVector != VmSlot2Options2Delete.end(); ++itIdVector)
-    {
-        for (DhcpOptIdIterator itOptId = itIdVector->second.begin(); itOptId != itIdVector->second.end(); ++itOptId)
-        {
-            CHECK_ERROR2_STMT(hrc, svr, RemoveVmSlotOption(Bstr(itIdVector->first.VmName.c_str()).raw(),
-                                                           itIdVector->first.u8Slot, *itOptId),
-                              rcExit = RTEXITCODE_FAILURE);
-        }
-    }
-
-    /* Global Options */
-    for (DhcpOptIterator itOpt = GlobalDhcpOptions.begin(); itOpt != GlobalDhcpOptions.end(); ++itOpt)
-    {
-        CHECK_ERROR2_STMT(hrc, svr, AddGlobalOption(itOpt->first, com::Bstr(itOpt->second.c_str()).raw()),
-                          rcExit = RTEXITCODE_FAILURE);
-    }
-
-    /* VM slot options. */
-    for (VmSlot2OptionsIterator it = VmSlot2Options.begin(); it != VmSlot2Options.end(); ++it)
-    {
-        for (DhcpOptIterator itOpt = it->second.begin(); itOpt != it->second.end(); ++itOpt)
-        {
-            CHECK_ERROR2_STMT(hrc, svr, AddVmSlotOption(Bstr(it->first.VmName.c_str()).raw(), it->first.u8Slot, itOpt->first,
-                                                        com::Bstr(itOpt->second).raw()),
-                              rcExit = RTEXITCODE_FAILURE);
+        if (pszServerIp || pszNetmask || pszLowerIp || pszUpperIp)
+        {
+            Bstr bstrServerIp(pszServerIp);
+            Bstr bstrNetmask(pszNetmask);
+            Bstr bstrLowerIp(pszLowerIp);
+            Bstr bstrUpperIp(pszUpperIp);
+
+            if (!pszServerIp)
+            {
+                CHECK_ERROR2_RET(hrc, ptrDHCPServer, COMGETTER(IPAddress)(bstrServerIp.asOutParam()), RTEXITCODE_FAILURE);
+            }
+            if (!pszNetmask)
+            {
+                CHECK_ERROR2_RET(hrc, ptrDHCPServer, COMGETTER(NetworkMask)(bstrNetmask.asOutParam()), RTEXITCODE_FAILURE);
+            }
+            if (!pszLowerIp)
+            {
+                CHECK_ERROR2_RET(hrc, ptrDHCPServer, COMGETTER(LowerIP)(bstrLowerIp.asOutParam()), RTEXITCODE_FAILURE);
+            }
+            if (!pszUpperIp)
+            {
+                CHECK_ERROR2_RET(hrc, ptrDHCPServer, COMGETTER(UpperIP)(bstrUpperIp.asOutParam()), RTEXITCODE_FAILURE);
+            }
+
+            CHECK_ERROR2_STMT(hrc, ptrDHCPServer, SetConfiguration(bstrServerIp.raw(), bstrNetmask.raw(),
+                                                                   bstrLowerIp.raw(), bstrUpperIp.raw()),
+                              rcExit = errorArgument("Failed to set configuration (%ls, %ls, %ls, %ls)", bstrServerIp.raw(),
+                                                     bstrNetmask.raw(), bstrLowerIp.raw(), bstrUpperIp.raw()));
+        }
+
+        if (fEnabled >= 0)
+        {
+            CHECK_ERROR2_STMT(hrc, ptrDHCPServer, COMSETTER(Enabled)((BOOL)fEnabled), rcExit = RTEXITCODE_FAILURE);
         }
     }
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp	(revision 79770)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp	(revision 79771)
@@ -859,30 +859,30 @@
 {
     HRESULT hrcRet = S_OK;
-    com::SafeIfaceArray<IDHCPServer> svrs;
-    CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(DHCPServers)(ComSafeArrayAsOutParam(svrs)), hrcCheck);
-    for (size_t i = 0; i < svrs.size(); ++i)
+    com::SafeIfaceArray<IDHCPServer> DHCPServers;
+    CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(DHCPServers)(ComSafeArrayAsOutParam(DHCPServers)), hrcCheck);
+    for (size_t i = 0; i < DHCPServers.size(); ++i)
     {
         if (i > 0)
             RTPrintf("\n");
 
-        ComPtr<IDHCPServer> svr = svrs[i];
+        ComPtr<IDHCPServer> ptrDHCPServer = DHCPServers[i];
         Bstr bstr;
-        CHECK_ERROR2I_STMT(svr, COMGETTER(NetworkName)(bstr.asOutParam()), hrcRet = hrcCheck);
+        CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(NetworkName)(bstr.asOutParam()), hrcRet = hrcCheck);
         RTPrintf("NetworkName:    %ls\n", bstr.raw());
 
-        CHECK_ERROR2I_STMT(svr, COMGETTER(IPAddress)(bstr.asOutParam()), hrcRet = hrcCheck);
+        CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(IPAddress)(bstr.asOutParam()), hrcRet = hrcCheck);
         RTPrintf("Dhcpd IP:       %ls\n", bstr.raw());
 
-        CHECK_ERROR2I_STMT(svr, COMGETTER(LowerIP)(bstr.asOutParam()), hrcRet = hrcCheck);
+        CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(LowerIP)(bstr.asOutParam()), hrcRet = hrcCheck);
         RTPrintf("LowerIPAddress: %ls\n", bstr.raw());
 
-        CHECK_ERROR2I_STMT(svr, COMGETTER(UpperIP)(bstr.asOutParam()), hrcRet = hrcCheck);
+        CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(UpperIP)(bstr.asOutParam()), hrcRet = hrcCheck);
         RTPrintf("UpperIPAddress: %ls\n", bstr.raw());
 
-        CHECK_ERROR2I_STMT(svr, COMGETTER(NetworkMask)(bstr.asOutParam()), hrcRet = hrcCheck);
+        CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(NetworkMask)(bstr.asOutParam()), hrcRet = hrcCheck);
         RTPrintf("NetworkMask:    %ls\n", bstr.raw());
 
         BOOL fEnabled = FALSE;
-        CHECK_ERROR2I_STMT(svr, COMGETTER(Enabled)(&fEnabled), hrcRet = hrcCheck);
+        CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(Enabled)(&fEnabled), hrcRet = hrcCheck);
         RTPrintf("Enabled:        %s\n", fEnabled ? "Yes" : "No");
 
@@ -891,5 +891,5 @@
         HRESULT hrc;
         ComPtr<IDHCPGlobalConfig> ptrGlobal;
-        CHECK_ERROR2_STMT(hrc, svr, COMGETTER(GlobalConfig)(ptrGlobal.asOutParam()), hrcRet = hrc);
+        CHECK_ERROR2_STMT(hrc, ptrDHCPServer, COMGETTER(GlobalConfig)(ptrGlobal.asOutParam()), hrcRet = hrc);
         if (SUCCEEDED(hrc))
         {
@@ -901,5 +901,5 @@
         /* Group configurations: */
         com::SafeIfaceArray<IDHCPGroupConfig> Groups;
-        CHECK_ERROR2_STMT(hrc, svr, COMGETTER(GroupConfigs)(ComSafeArrayAsOutParam(Groups)), hrcRet = hrc);
+        CHECK_ERROR2_STMT(hrc, ptrDHCPServer, COMGETTER(GroupConfigs)(ComSafeArrayAsOutParam(Groups)), hrcRet = hrc);
         if (FAILED(hrc))
             RTPrintf("Groups:               %Rrc\n", hrc);
@@ -913,4 +913,31 @@
                 RTPrintf("Group:                %ls\n", bstr.raw());
 
+                com::SafeIfaceArray<IDHCPGroupCondition> Conditions;
+                CHECK_ERROR2_STMT(hrc, Groups[iGrp], COMGETTER(Conditions)(ComSafeArrayAsOutParam(Conditions)), hrcRet = hrc);
+                if (FAILED(hrc))
+                    RTPrintf("    Conditions:       %Rhrc\n", hrc);
+                else if (Conditions.size() == 0)
+                    RTPrintf("    Conditions:       None\n");
+                else
+                    for (size_t iCond = 0; iCond < Conditions.size(); iCond++)
+                    {
+                        BOOL fInclusive = TRUE;
+                        CHECK_ERROR2_STMT(hrc, Conditions[iCond], COMGETTER(Inclusive)(&fInclusive), hrcRet = hrc);
+                        DHCPGroupConditionType_T enmType = DHCPGroupConditionType_MAC;
+                        CHECK_ERROR2_STMT(hrc, Conditions[iCond], COMGETTER(Type)(&enmType), hrcRet = hrc);
+                        CHECK_ERROR2_STMT(hrc, Conditions[iCond], COMGETTER(Value)(bstr.asOutParam()), hrcRet = hrc);
+
+                        RTPrintf("    Conditions:       %s %s %ls\n",
+                                 fInclusive ? "include" : "exclude",
+                                   enmType == DHCPGroupConditionType_MAC                    ? "MAC       "
+                                 : enmType == DHCPGroupConditionType_MACWildcard            ? "MAC*      "
+                                 : enmType == DHCPGroupConditionType_vendorClassID          ? "VendorCID "
+                                 : enmType == DHCPGroupConditionType_vendorClassIDWildcard  ? "VendorCID*"
+                                 : enmType == DHCPGroupConditionType_userClassID            ? "UserCID   "
+                                 : enmType == DHCPGroupConditionType_userClassIDWildcard    ? "UserCID*  "
+                                 :                                                            "!UNKNOWN! ",
+                                 bstr.raw());
+                    }
+
                 hrc = showDhcpConfig(Groups[iGrp]);
                 if (FAILED(hrc))
@@ -922,5 +949,5 @@
         /* Individual host / NIC configurations: */
         com::SafeIfaceArray<IDHCPIndividualConfig> Hosts;
-        CHECK_ERROR2_STMT(hrc, svr, COMGETTER(IndividualConfigs)(ComSafeArrayAsOutParam(Hosts)), hrcRet = hrc);
+        CHECK_ERROR2_STMT(hrc, ptrDHCPServer, COMGETTER(IndividualConfigs)(ComSafeArrayAsOutParam(Hosts)), hrcRet = hrc);
         if (FAILED(hrc))
             RTPrintf("Individual Configs:   %Rrc\n", hrc);
@@ -936,5 +963,5 @@
                 if (enmScope == DHCPConfigScope_MAC)
                 {
-                    CHECK_ERROR2I_STMT(Hosts[i], COMGETTER(MACAddress)(bstr.asOutParam()), hrcRet = hrcCheck);
+                    CHECK_ERROR2I_STMT(Hosts[iHost], COMGETTER(MACAddress)(bstr.asOutParam()), hrcRet = hrcCheck);
                     RTPrintf("Individual Config:    MAC %ls\n", bstr.raw());
                 }
@@ -942,8 +969,8 @@
                 {
                     ULONG uSlot = 0;
-                    CHECK_ERROR2I_STMT(Hosts[i], COMGETTER(Slot)(&uSlot), hrcRet = hrcCheck);
-                    CHECK_ERROR2I_STMT(Hosts[i], COMGETTER(MachineId)(bstr.asOutParam()), hrcRet = hrcCheck);
+                    CHECK_ERROR2I_STMT(Hosts[iHost], COMGETTER(Slot)(&uSlot), hrcRet = hrcCheck);
+                    CHECK_ERROR2I_STMT(Hosts[iHost], COMGETTER(MachineId)(bstr.asOutParam()), hrcRet = hrcCheck);
                     Bstr bstrMACAddress;
-                    hrc = Hosts[i]->COMGETTER(MACAddress)(bstrMACAddress.asOutParam()); /* No CHECK_ERROR2 stuff! */
+                    hrc = Hosts[iHost]->COMGETTER(MACAddress)(bstrMACAddress.asOutParam()); /* No CHECK_ERROR2 stuff! */
                     if (SUCCEEDED(hrc))
                         RTPrintf("Individual Config:    VM NIC: %ls slot %u, MAC %ls\n", bstr.raw(), uSlot, bstrMACAddress.raw());
@@ -952,5 +979,5 @@
                 }
 
-                CHECK_ERROR2I_STMT(Hosts[i], COMGETTER(FixedAddress)(bstr.asOutParam()), hrcRet = hrcCheck);
+                CHECK_ERROR2I_STMT(Hosts[iHost], COMGETTER(FixedAddress)(bstr.asOutParam()), hrcRet = hrcCheck);
                 if (bstr.isNotEmpty())
                     RTPrintf("    Fixed Address:    %ls\n", bstr.raw());
@@ -958,5 +985,5 @@
                     RTPrintf("    Fixed Address:    dynamic\n");
 
-                hrc = showDhcpConfig(Hosts[i]);
+                hrc = showDhcpConfig(Hosts[iHost]);
                 if (FAILED(hrc))
                     hrcRet = hrc;
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 79770)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 79771)
@@ -2140,5 +2140,5 @@
   <interface
     name="IDHCPConfig" extends="$unknown"
-    uuid="38fdb664-f65e-4905-ee56-a8a912871bbf"
+    uuid="39cdde66-cfc3-4eec-7427-faf5b16469ae"
     wsmap="managed"
     reservedMethods="8" reservedAttributes="16"
@@ -2223,4 +2223,12 @@
       </param>
     </method>
+
+    <method name="remove">
+      <desc>
+        Remove this group or individual configuration.
+        Will of course not work on global configurations.
+      </desc>
+    </method>
+
   </interface>
 
@@ -2260,5 +2268,5 @@
   <interface
     name="IDHCPGroupConfig" extends="IDHCPConfig"
-    uuid="406a5eca-d032-4f65-a882-6bb626a424a5"
+    uuid="537707f7-ebf9-4d5c-7aea-877bfc4256ba"
     wsmap="managed"
     reservedMethods="8" reservedAttributes="8"
@@ -2282,8 +2290,13 @@
 
     <method name="addCondition">
+      <desc>Adds a new condition.</desc>
       <param name="inclusive"  dir="in" type="boolean"/>
       <param name="type"       dir="in" type="DHCPGroupConditionType"/>
       <param name="value"      dir="in" type="wstring"/>
       <param name="condition"  dir="return" type="IDHCPGroupCondition"/>
+    </method>
+
+    <method name="removeAllConditions">
+      <desc>Removes all conditions.</desc>
     </method>
 
Index: /trunk/src/VBox/Main/include/DHCPConfigImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/DHCPConfigImpl.h	(revision 79770)
+++ /trunk/src/VBox/Main/include/DHCPConfigImpl.h	(revision 79771)
@@ -99,4 +99,5 @@
     HRESULT         i_getAllOptions(std::vector<DhcpOpt_T> &aOptions, std::vector<DHCPOptionEncoding_T> &aEncodings,
                                     std::vector<com::Utf8Str> &aValues);
+    virtual HRESULT i_remove();
     /** @} */
 
@@ -178,4 +179,9 @@
         return i_getAllOptions(aOptions, aEncodings, aValues);
     }
+
+    HRESULT remove() RT_OVERRIDE
+    {
+        return i_remove();
+    }
     /** @} */
 
@@ -184,4 +190,5 @@
     HRESULT i_removeOption(DhcpOpt_T aOption) RT_OVERRIDE;
     HRESULT i_removeAllOptions() RT_OVERRIDE;
+    HRESULT i_remove() RT_OVERRIDE;
 };
 
@@ -225,4 +232,6 @@
 
     HRESULT i_saveSettings(settings::DHCPGroupCondition &a_rDst);
+    static HRESULT i_validateTypeAndValue(DHCPGroupConditionType_T enmType, com::Utf8Str const &strValue,
+                                          VirtualBoxBase *pErrorDst);
 
 protected:
@@ -326,4 +335,9 @@
         return i_getAllOptions(aOptions, aEncodings, aValues);
     }
+
+    HRESULT remove() RT_OVERRIDE
+    {
+        return i_remove();
+    }
     /** @} */
 
@@ -332,4 +346,5 @@
     HRESULT addCondition(BOOL aInclusive, DHCPGroupConditionType_T aType, const com::Utf8Str &aValue,
                          ComPtr<IDHCPGroupCondition> &aCondition) RT_OVERRIDE;
+    HRESULT removeAllConditions() RT_OVERRIDE;
     /** @} */
 };
@@ -444,4 +459,9 @@
         return i_getAllOptions(aOptions, aEncodings, aValues);
     }
+
+    HRESULT remove() RT_OVERRIDE
+    {
+        return i_remove();
+    }
     /** @} */
 
Index: /trunk/src/VBox/Main/include/DHCPServerImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/DHCPServerImpl.h	(revision 79770)
+++ /trunk/src/VBox/Main/include/DHCPServerImpl.h	(revision 79771)
@@ -69,4 +69,5 @@
      * @{ */
     HRESULT i_saveSettings(settings::DHCPServer &data);
+    HRESULT i_removeConfig(DHCPConfig *pConfig, DHCPConfigScope_T enmScope);
     /** @} */
 
Index: /trunk/src/VBox/Main/src-server/DHCPConfigImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/DHCPConfigImpl.cpp	(revision 79770)
+++ /trunk/src/VBox/Main/src-server/DHCPConfigImpl.cpp	(revision 79771)
@@ -24,4 +24,5 @@
 #include "LoggingNew.h"
 
+#include <iprt/ctype.h>
 #include <iprt/errcore.h>
 #include <iprt/net.h>
@@ -33,4 +34,5 @@
 
 #include "AutoCaller.h"
+#include "DHCPServerImpl.h"
 #include "MachineImpl.h"
 #include "VirtualBoxImpl.h"
@@ -271,4 +273,11 @@
 
 
+HRESULT DHCPConfig::i_remove()
+{
+    return m_pParent->i_removeConfig(this, m_enmScope);
+}
+
+
+
 /**
  * Causes the global VirtualBox configuration file to be written
@@ -450,4 +459,13 @@
 
 
+/**
+ * Overriden to prevent removal.
+ */
+HRESULT DHCPGlobalConfig::i_remove()
+{
+    return setError(E_ACCESSDENIED, tr("Cannot delete the global config"));
+}
+
+
 
 /*********************************************************************************************************************************
@@ -500,4 +518,160 @@
 
 
+/**
+ * Worker for validating the condition value according to the given type.
+ *
+ * @returns COM status code.
+ * @param   enmType             The condition type.
+ * @param   strValue            The condition value.
+ * @param   pErrorDst           The object to use for reporting errors.
+ */
+/*static*/ HRESULT DHCPGroupCondition::i_validateTypeAndValue(DHCPGroupConditionType_T enmType, com::Utf8Str const &strValue,
+                                                              VirtualBoxBase *pErrorDst)
+{
+    switch (enmType)
+    {
+        case DHCPGroupConditionType_MAC:
+        {
+            RTMAC MACAddress;
+            int vrc = RTNetStrToMacAddr(strValue.c_str(), &MACAddress);
+            if (RT_SUCCESS(vrc))
+                return S_OK;
+            return pErrorDst->setError(E_INVALIDARG, pErrorDst->tr("Not a valid MAC address: %s"), strValue.c_str());
+        }
+
+        case DHCPGroupConditionType_MACWildcard:
+        {
+            /* This must be colon separated double xdigit bytes.  Single bytes
+               shorthand or raw hexstrings won't match anything.  For reasons of
+               simplicity, '?' can only be used to match xdigits, '*' must match 1+
+               chars. */
+            /** @todo test this properly...   */
+            const char *psz           = strValue.c_str();
+            size_t      off           = 0;
+            unsigned    cPairsLeft    = 6;
+            bool        fSeenAsterisk = false;
+            for (;;)
+            {
+                char ch = psz[off++];
+                if (RT_C_IS_XDIGIT(ch) || ch == '?')
+                {
+                    ch = psz[off++];
+                    if (RT_C_IS_XDIGIT(ch) || ch == '?')
+                    {
+                        ch = psz[off++];
+                        cPairsLeft -= 1;
+                        if (cPairsLeft == 0)
+                        {
+                            if (!ch)
+                                return S_OK;
+                            return pErrorDst->setError(E_INVALIDARG,
+                                                       pErrorDst->tr("Trailing chars in MAC wildcard address: %s (offset %zu)"),
+                                                       psz, off - 1);
+                        }
+                        if (ch == ':' || ch == '*')
+                            continue;
+                        if (ch == '\0' && fSeenAsterisk)
+                            return S_OK;
+                        return pErrorDst->setError(E_INVALIDARG,
+                                                   pErrorDst->tr("Malformed MAC wildcard address: %s (offset %zu)"),
+                                                   psz, off - 1);
+                    }
+
+                    if (ch == '*')
+                    {
+                        fSeenAsterisk = true;
+                        do
+                            ch = psz[off++];
+                        while (ch == '*');
+                        if (ch == '\0')
+                            return S_OK;
+                        cPairsLeft -= 1;
+                        if (cPairsLeft == 0)
+                            return pErrorDst->setError(E_INVALIDARG,
+                                                       pErrorDst->tr("Trailing chars in MAC wildcard address: %s (offset %zu)"),
+                                                       psz, off - 1);
+                        if (ch == ':')
+                            continue;
+                    }
+                    else
+                        return pErrorDst->setError(E_INVALIDARG, pErrorDst->tr("Malformed MAC wildcard address: %s (offset %zu)"),
+                                                   psz, off - 1);
+                }
+                else if (ch == '*')
+                {
+                    fSeenAsterisk = true;
+                    do
+                        ch = psz[off++];
+                    while (ch == '*');
+                    if (ch == '\0')
+                        return S_OK;
+                    if (ch == ':')
+                    {
+                        cPairsLeft -= 1;
+                        if (cPairsLeft == 0)
+                            return pErrorDst->setError(E_INVALIDARG,
+                                                       pErrorDst->tr("Trailing chars in MAC wildcard address: %s (offset %zu)"),
+                                                       psz, off - 1);
+                        continue;
+                    }
+
+                }
+                else
+                    return pErrorDst->setError(E_INVALIDARG, pErrorDst->tr("Malformed MAC wildcard address: %s (offset %zu)"),
+                                               psz, off - 1);
+
+                /* Pick up after '*' in the two cases above: ch is not ':' or '\0'. */
+                Assert(ch != ':' && ch != '\0');
+                if (RT_C_IS_XDIGIT(ch) || ch == '?')
+                {
+                    ch = psz[off++];
+                    if (RT_C_IS_XDIGIT(ch) || ch == '?' || ch == '*')
+                    {
+                        off -= 2;
+                        continue;
+                    }
+                    if (ch == ':')
+                    {
+                        ch = psz[off++];
+                        if (ch == '\0')
+                            return S_OK;
+                        cPairsLeft -= 1;
+                        if (cPairsLeft == 0)
+                            return pErrorDst->setError(E_INVALIDARG,
+                                                       pErrorDst->tr("Trailing chars in MAC wildcard address: %s (offset %zu)"),
+                                                       psz, off - 1);
+                        continue;
+                    }
+                    if (ch == '\0')
+                        return S_OK;
+                    return pErrorDst->setError(E_INVALIDARG,
+                                               pErrorDst->tr("Trailing chars in MAC wildcard address: %s (offset %zu)"),
+                                               psz, off - 1);
+                }
+                return pErrorDst->setError(E_INVALIDARG,
+                                           pErrorDst->tr("Malformed MAC wildcard address: %s (offset %zu)"),
+                                           psz, off - 1);
+            }
+            break;
+        }
+
+        case DHCPGroupConditionType_vendorClassID:
+        case DHCPGroupConditionType_vendorClassIDWildcard:
+        case DHCPGroupConditionType_userClassID:
+        case DHCPGroupConditionType_userClassIDWildcard:
+            if (strValue.length() == 0)
+                return pErrorDst->setError(E_INVALIDARG, pErrorDst->tr("Value cannot be empty"));
+            if (strValue.length() < 255)
+                return pErrorDst->setError(E_INVALIDARG, pErrorDst->tr("Value is too long: %zu bytes"), strValue.length());
+            break;
+
+        default:
+            return pErrorDst->setError(E_INVALIDARG, pErrorDst->tr("Invalid condition type: %d"), enmType);
+    }
+
+    return S_OK;
+}
+
+
 HRESULT DHCPGroupCondition::getInclusive(BOOL *aInclusive)
 {
@@ -534,4 +708,7 @@
         if (aType == m_enmType)
             return S_OK;
+        HRESULT hrc = i_validateTypeAndValue(aType, m_strValue, this);
+        if (FAILED(hrc))
+            return hrc;
         m_enmType = aType;
     }
@@ -553,5 +730,8 @@
         if (aValue == m_strValue)
             return S_OK;
-        HRESULT hrc = m_strValue.assignEx(aValue);
+        HRESULT hrc = i_validateTypeAndValue(m_enmType, aValue, this);
+        if (FAILED(hrc))
+            return hrc;
+        hrc = m_strValue.assignEx(aValue);
         if (FAILED(hrc))
             return hrc;
@@ -728,22 +908,38 @@
                                       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());
+    /*
+     * Valdiate it.
+     */
+    HRESULT hrc = DHCPGroupCondition::i_validateTypeAndValue(aType, aValue, this);
+    if (SUCCEEDED(hrc))
+    {
+        /*
+         * Add it.
+         */
+        ComObjPtr<DHCPGroupCondition> ptrCondition;
+        hrc = ptrCondition.createObject();
+        if (SUCCEEDED(hrc))
+            hrc = ptrCondition->initWithDefaults(this, aInclusive != FALSE, aType, aValue);
         if (SUCCEEDED(hrc))
         {
-            AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-            try
+            hrc = ptrCondition.queryInterfaceTo(aCondition.asOutParam());
+            if (SUCCEEDED(hrc))
             {
-                m_Conditions.push_back(ptrCondition);
-            }
-            catch (std::bad_alloc &)
-            {
-                aCondition.setNull();
-                return E_OUTOFMEMORY;
+                {
+                    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+                    try
+                    {
+                        m_Conditions.push_back(ptrCondition);
+                    }
+                    catch (std::bad_alloc &)
+                    {
+                        aCondition.setNull();
+                        return E_OUTOFMEMORY;
+                    }
+                }
+
+                hrc = i_doWriteConfig();
+                if (FAILED(hrc))
+                    aCondition.setNull();
             }
         }
@@ -751,4 +947,19 @@
 
     return hrc;
+}
+
+
+HRESULT DHCPGroupConfig::removeAllConditions()
+{
+    {
+        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+        if (m_Conditions.size() == 0)
+            return S_OK;
+
+        /** @todo sever the weak parent link for each entry...  */
+        m_Conditions.erase(m_Conditions.begin(), m_Conditions.end());
+    }
+
+    return i_doWriteConfig();
 }
 
Index: /trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp	(revision 79770)
+++ /trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp	(revision 79771)
@@ -311,4 +311,7 @@
 
 
+/**
+ * Called by VirtualBox to save our settings.
+ */
 HRESULT DHCPServer::i_saveSettings(settings::DHCPServer &rData)
 {
@@ -367,4 +370,54 @@
 
     return hrc;
+}
+
+
+HRESULT DHCPServer::i_removeConfig(DHCPConfig *pConfig, DHCPConfigScope_T enmScope)
+{
+    {
+        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+        bool fFound = false;
+        switch (enmScope)
+        {
+            case DHCPConfigScope_Group:
+                for (Data::GroupConfigIterator it = m->groupConfigs.begin(); it != m->groupConfigs.end();)
+                {
+                    DHCPConfig *pCurConfig = it->second;
+                    if (pCurConfig == pConfig)
+                    {
+                        fFound = true;
+                        it = m->groupConfigs.erase(it);
+                    }
+                    else
+                        ++it;
+                }
+                break;
+
+            case DHCPConfigScope_MAC:
+            case DHCPConfigScope_MachineNIC:
+                for (Data::IndividualConfigIterator it = m->individualConfigs.begin(); it != m->individualConfigs.end();)
+                {
+                    DHCPConfig *pCurConfig = it->second;
+                    if (pCurConfig == pConfig)
+                    {
+                        fFound = true;
+                        it = m->individualConfigs.erase(it);
+                    }
+                    else
+                        ++it;
+                }
+                break;
+
+            default:
+                AssertFailedReturn(E_FAIL);
+        }
+
+        /* Don't complain if already removed, right? */
+        if (!fFound)
+            return S_OK;
+    }
+
+    return i_doSaveSettings();
 }
 
