VirtualBox

Changeset 79771 in vbox


Ignore:
Timestamp:
Jul 14, 2019 9:10:58 PM (6 years ago)
Author:
vboxsync
Message:

Main/DHCP*,VBoxManage: Some adjustments to the DHCP*Config interfaces and reworked the VBoxMAnage dhcpserver add/modify commands to support groups, fixed address assignments, setting lease times, removing group and individaul configurations, ++. todo: update man page. bugref:9288

Location:
trunk/src/VBox
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp

    r79761 r79771  
    202202
    203203/**
     204 * Helper class for dhcpdHandleAddAndModify
     205 */
     206class DHCPCmdScope
     207{
     208    DHCPConfigScope_T               m_enmScope;
     209    const char                     *m_pszName;
     210    uint8_t                         m_uSlot;
     211    ComPtr<IDHCPConfig>             m_ptrConfig;
     212    ComPtr<IDHCPGlobalConfig>       m_ptrGlobalConfig;
     213    ComPtr<IDHCPGroupConfig>        m_ptrGroupConfig;
     214    ComPtr<IDHCPIndividualConfig>   m_ptrIndividualConfig;
     215
     216public:
     217    DHCPCmdScope()
     218        : m_enmScope(DHCPConfigScope_Global)
     219        , m_pszName(NULL)
     220        , m_uSlot(0)
     221    {
     222    }
     223
     224    void setGlobal()
     225    {
     226        m_enmScope = DHCPConfigScope_Global;
     227        m_pszName  = NULL;
     228        m_uSlot    = 0;
     229        resetPointers();
     230    }
     231
     232    void setGroup(const char *pszGroup)
     233    {
     234        m_enmScope = DHCPConfigScope_Group;
     235        m_pszName  = pszGroup;
     236        m_uSlot    = 0;
     237        resetPointers();
     238    }
     239
     240    void setMachineNIC(const char *pszMachine)
     241    {
     242        m_enmScope = DHCPConfigScope_MachineNIC;
     243        m_pszName  = pszMachine;
     244        m_uSlot    = 0;
     245        resetPointers();
     246    }
     247
     248    void setMachineSlot(uint8_t uSlot)
     249    {
     250        Assert(m_enmScope == DHCPConfigScope_MachineNIC);
     251        m_uSlot    = uSlot;
     252        resetPointers();
     253    }
     254
     255    void setMACAddress(const char *pszMACAddress)
     256    {
     257        m_enmScope = DHCPConfigScope_MAC;
     258        m_pszName  = pszMACAddress;
     259        m_uSlot    = 0;
     260        resetPointers();
     261    }
     262
     263    ComPtr<IDHCPConfig> &getConfig(ComPtr<IDHCPServer> const &ptrDHCPServer)
     264    {
     265        if (m_ptrConfig.isNull())
     266            CHECK_ERROR2I_STMT(ptrDHCPServer, GetConfig(m_enmScope, Bstr(m_pszName).raw(), m_uSlot, TRUE /*mayAdd*/,
     267                                                        m_ptrConfig.asOutParam()), m_ptrConfig.setNull());
     268        return m_ptrConfig;
     269    }
     270
     271    ComPtr<IDHCPIndividualConfig> &getIndividual(ComPtr<IDHCPServer> const &ptrDHCPServer)
     272    {
     273        getConfig(ptrDHCPServer);
     274        if (m_ptrIndividualConfig.isNull() && m_ptrConfig.isNotNull())
     275        {
     276            HRESULT hrc = m_ptrConfig.queryInterfaceTo(m_ptrIndividualConfig.asOutParam());
     277            if (FAILED(hrc))
     278            {
     279                com::GlueHandleComError(m_ptrConfig, "queryInterface", hrc, __FILE__, __LINE__);
     280                m_ptrIndividualConfig.setNull();
     281            }
     282        }
     283        return m_ptrIndividualConfig;
     284    }
     285
     286    ComPtr<IDHCPGroupConfig> &getGroup(ComPtr<IDHCPServer> const &ptrDHCPServer)
     287    {
     288        getConfig(ptrDHCPServer);
     289        if (m_ptrGroupConfig.isNull() && m_ptrConfig.isNotNull())
     290        {
     291            HRESULT hrc = m_ptrConfig.queryInterfaceTo(m_ptrGroupConfig.asOutParam());
     292            if (FAILED(hrc))
     293            {
     294                com::GlueHandleComError(m_ptrConfig, "queryInterface", hrc, __FILE__, __LINE__);
     295                m_ptrGroupConfig.setNull();
     296            }
     297        }
     298        return m_ptrGroupConfig;
     299    }
     300
     301    DHCPConfigScope_T getScope() const { return m_enmScope; }
     302
     303private:
     304    void resetPointers()
     305    {
     306        m_ptrConfig.setNull();
     307        m_ptrGlobalConfig.setNull();
     308        m_ptrIndividualConfig.setNull();
     309        m_ptrGroupConfig.setNull();
     310    }
     311};
     312
     313enum
     314{
     315    DHCP_ADDMOD = 1000,
     316    DHCP_ADDMOD_ZAP_OPTIONS,
     317    DHCP_ADDMOD_INCL_MAC,
     318    DHCP_ADDMOD_EXCL_MAC,
     319    DHCP_ADDMOD_DEL_MAC,
     320    DHCP_ADDMOD_INCL_MAC_WILD,
     321    DHCP_ADDMOD_EXCL_MAC_WILD,
     322    DHCP_ADDMOD_DEL_MAC_WILD,
     323    DHCP_ADDMOD_INCL_VENDOR,
     324    DHCP_ADDMOD_EXCL_VENDOR,
     325    DHCP_ADDMOD_DEL_VENDOR,
     326    DHCP_ADDMOD_INCL_VENDOR_WILD,
     327    DHCP_ADDMOD_EXCL_VENDOR_WILD,
     328    DHCP_ADDMOD_DEL_VENDOR_WILD,
     329    DHCP_ADDMOD_INCL_USER,
     330    DHCP_ADDMOD_EXCL_USER,
     331    DHCP_ADDMOD_DEL_USER,
     332    DHCP_ADDMOD_INCL_USER_WILD,
     333    DHCP_ADDMOD_EXCL_USER_WILD,
     334    DHCP_ADDMOD_DEL_USER_WILD,
     335    DHCP_ADDMOD_ZAP_CONDITIONS
     336};
     337
     338/**
    204339 * Handles the 'add' and 'modify' subcommands.
    205340 */
    206341static DECLCALLBACK(RTEXITCODE) dhcpdHandleAddAndModify(PDHCPDCMDCTX pCtx, int argc, char **argv)
    207342{
    208     /*
    209      * Parse options.
    210      */
    211343    static const RTGETOPTDEF s_aOptions[] =
    212344    {
    213345        DHCPD_CMD_COMMON_OPTION_DEFS(),
    214         { "--server-ip",        'a', RTGETOPT_REQ_STRING  },
    215         { "--ip",               'a', RTGETOPT_REQ_STRING  },    // deprecated
    216         { "-ip",                'a', RTGETOPT_REQ_STRING  },    // deprecated
    217         { "--netmask",          'm', RTGETOPT_REQ_STRING  },
    218         { "-netmask",           'm', RTGETOPT_REQ_STRING  },    // deprecated
    219         { "--lower-ip",         'l', RTGETOPT_REQ_STRING  },
    220         { "--lowerip",          'l', RTGETOPT_REQ_STRING  },
    221         { "-lowerip",           'l', RTGETOPT_REQ_STRING  },    // deprecated
    222         { "--upper-ip",         'u', RTGETOPT_REQ_STRING  },
    223         { "--upperip",          'u', RTGETOPT_REQ_STRING  },
    224         { "-upperip",           'u', RTGETOPT_REQ_STRING  },    // deprecated
    225         { "--enable",           'e', RTGETOPT_REQ_NOTHING },
    226         { "-enable",            'e', RTGETOPT_REQ_NOTHING },    // deprecated
    227         { "--disable",          'd', RTGETOPT_REQ_NOTHING },
    228         { "-disable",           'd', RTGETOPT_REQ_NOTHING },    // deprecated
    229         { "--global",           'g', RTGETOPT_REQ_NOTHING },
    230         { "--vm",               'M', RTGETOPT_REQ_STRING  },
    231         { "--nic",              'n', RTGETOPT_REQ_UINT8   },
    232         { "--add-opt",          'A', RTGETOPT_REQ_UINT8   },
    233         { "--del-opt",          'D', RTGETOPT_REQ_UINT8   },
     346        { "--server-ip",        'a',                            RTGETOPT_REQ_STRING  },
     347        { "--ip",               'a',                            RTGETOPT_REQ_STRING  },    // deprecated
     348        { "-ip",                'a',                            RTGETOPT_REQ_STRING  },    // deprecated
     349        { "--netmask",          'm',                            RTGETOPT_REQ_STRING  },
     350        { "-netmask",           'm',                            RTGETOPT_REQ_STRING  },    // deprecated
     351        { "--lower-ip",         'l',                            RTGETOPT_REQ_STRING  },
     352        { "--lowerip",          'l',                            RTGETOPT_REQ_STRING  },
     353        { "-lowerip",           'l',                            RTGETOPT_REQ_STRING  },    // deprecated
     354        { "--upper-ip",         'u',                            RTGETOPT_REQ_STRING  },
     355        { "--upperip",          'u',                            RTGETOPT_REQ_STRING  },
     356        { "-upperip",           'u',                            RTGETOPT_REQ_STRING  },    // deprecated
     357        { "--enable",           'e',                            RTGETOPT_REQ_NOTHING },
     358        { "-enable",            'e',                            RTGETOPT_REQ_NOTHING },    // deprecated
     359        { "--disable",          'd',                            RTGETOPT_REQ_NOTHING },
     360        { "-disable",           'd',                            RTGETOPT_REQ_NOTHING },    // deprecated
     361        { "--global",           'g',                            RTGETOPT_REQ_NOTHING },
     362        { "--group",            'G',                            RTGETOPT_REQ_STRING  },
     363        { "--mac-address",      'E',                            RTGETOPT_REQ_MACADDR },
     364        { "--vm",               'M',                            RTGETOPT_REQ_STRING  },
     365        { "--nic",              'n',                            RTGETOPT_REQ_UINT8   },
     366        { "--set-opt",          's',                            RTGETOPT_REQ_UINT8   },
     367        { "--set-opt-hex",      'x',                            RTGETOPT_REQ_UINT8   },
     368        { "--del-opt",          'D',                            RTGETOPT_REQ_UINT8   },
     369        { "--zap-options",      DHCP_ADDMOD_ZAP_OPTIONS,        RTGETOPT_REQ_NOTHING },
     370        { "--min-lease-time",   'q' ,                           RTGETOPT_REQ_UINT32  },
     371        { "--default-lease-time", 'L' ,                         RTGETOPT_REQ_UINT32  },
     372        { "--max-lease-time",   'Q' ,                           RTGETOPT_REQ_UINT32  },
     373        { "--remove-config",    'R',                            RTGETOPT_REQ_NOTHING },
     374        { "--fixed-address",    'f',                            RTGETOPT_REQ_STRING  },
     375        /* group conditions: */
     376        { "--incl-mac",         DHCP_ADDMOD_INCL_MAC,           RTGETOPT_REQ_STRING  },
     377        { "--excl-mac",         DHCP_ADDMOD_EXCL_MAC,           RTGETOPT_REQ_STRING  },
     378        { "--del-mac",          DHCP_ADDMOD_DEL_MAC,            RTGETOPT_REQ_STRING  },
     379        { "--incl-mac-wild",    DHCP_ADDMOD_INCL_MAC_WILD,      RTGETOPT_REQ_STRING  },
     380        { "--excl-mac-wild",    DHCP_ADDMOD_EXCL_MAC_WILD,      RTGETOPT_REQ_STRING  },
     381        { "--del-mac-wild",     DHCP_ADDMOD_DEL_MAC_WILD,       RTGETOPT_REQ_STRING  },
     382        { "--incl-vendor",      DHCP_ADDMOD_INCL_VENDOR,        RTGETOPT_REQ_STRING  },
     383        { "--excl-vendor",      DHCP_ADDMOD_EXCL_VENDOR,        RTGETOPT_REQ_STRING  },
     384        { "--del-vendor",       DHCP_ADDMOD_DEL_VENDOR,         RTGETOPT_REQ_STRING  },
     385        { "--incl-vendor-wild", DHCP_ADDMOD_INCL_VENDOR_WILD,   RTGETOPT_REQ_STRING  },
     386        { "--excl-vendor-wild", DHCP_ADDMOD_EXCL_VENDOR_WILD,   RTGETOPT_REQ_STRING  },
     387        { "--del-vendor-wild",  DHCP_ADDMOD_DEL_VENDOR_WILD,    RTGETOPT_REQ_STRING  },
     388        { "--incl-user",        DHCP_ADDMOD_INCL_USER,          RTGETOPT_REQ_STRING  },
     389        { "--excl-user",        DHCP_ADDMOD_EXCL_USER,          RTGETOPT_REQ_STRING  },
     390        { "--del-user",         DHCP_ADDMOD_DEL_USER,           RTGETOPT_REQ_STRING  },
     391        { "--incl-user-wild",   DHCP_ADDMOD_INCL_USER_WILD,     RTGETOPT_REQ_STRING  },
     392        { "--excl-user-wild",   DHCP_ADDMOD_EXCL_USER_WILD,     RTGETOPT_REQ_STRING  },
     393        { "--del-user-wild",    DHCP_ADDMOD_DEL_USER_WILD,      RTGETOPT_REQ_STRING  },
     394        { "--zap-conditions",   DHCP_ADDMOD_ZAP_CONDITIONS,     RTGETOPT_REQ_NOTHING },
     395        /* obsolete, to be removed: */
    234396        { "--id",               'i', RTGETOPT_REQ_UINT8   },    // obsolete, backwards compatibility only.
    235397        { "--value",            'p', RTGETOPT_REQ_STRING  },    // obsolete, backwards compatibility only.
     
    239401    };
    240402
    241     const char       *pszServerIp           = NULL;
    242     const char       *pszNetmask            = NULL;
    243     const char       *pszLowerIp            = NULL;
    244     const char       *pszUpperIp            = NULL;
    245     int               fEnabled              = -1;
    246 
    247     DhcpOpts          GlobalDhcpOptions;
    248     DhcpOptIds        GlobalDhcpOptions2Delete;
    249     VmSlot2OptionsM   VmSlot2Options;
    250     VmSlot2OptionIdsM VmSlot2Options2Delete;
    251 
    252     const char       *pszVmName             = NULL;
    253     uint8_t           u8Slot                = 0;
    254     DhcpOpts         *pScopeOptions         = &GlobalDhcpOptions;
    255     DhcpOptIds       *pScopeOptions2Delete  = &GlobalDhcpOptions2Delete;
    256 
    257     bool              fNeedValueOrRemove    = false; /* Only used with --id; remove in 6.1+ */
    258     uint8_t           u8OptId               = 0;     /* Only used too keep --id for following --value/--remove. remove in 6.1+ */
    259 
    260     RTGETOPTSTATE GetState;
    261     int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
    262     AssertRCReturn(vrc, RTEXITCODE_FAILURE);
    263 
    264     RTGETOPTUNION ValueUnion;
    265     while ((vrc = RTGetOpt(&GetState, &ValueUnion)))
    266     {
    267         switch (vrc)
    268         {
    269             DHCPD_CMD_COMMON_OPTION_CASES(pCtx, vrc, &ValueUnion);
    270             case 'a':   // --server-ip
    271                 pszServerIp = ValueUnion.psz;
    272                 break;
    273             case 'm':   // --netmask
    274                 pszNetmask = ValueUnion.psz;
    275                 break;
    276             case 'l':   // --lower-ip
    277                 pszLowerIp = ValueUnion.psz;
    278                 break;
    279             case 'u':   // --upper-ip
    280                 pszUpperIp = ValueUnion.psz;
    281                 break;
    282             case 'e':   // --enable
    283                 fEnabled = 1;
    284                 break;
    285             case 'd':   // --disable
    286                 fEnabled = 0;
    287                 break;
    288 
    289             case 'g':   // --global     Sets the option scope to 'global'.
    290                 if (fNeedValueOrRemove)
    291                     return errorSyntax("Incomplete option sequence preseeding '--global'");
    292                 pScopeOptions         = &GlobalDhcpOptions;
    293                 pScopeOptions2Delete  = &GlobalDhcpOptions2Delete;
    294                 break;
    295 
    296             case 'M':   // --vm         Sets the option scope to ValueUnion.psz + 0.
    297                 if (fNeedValueOrRemove)
    298                     return errorSyntax("Incomplete option sequence preseeding '--vm'");
    299                 pszVmName = ValueUnion.psz;
    300                 u8Slot    = 0;
    301                 pScopeOptions        = &VmSlot2Options[VmNameSlotKey(pszVmName, u8Slot)];
    302                 pScopeOptions2Delete = &VmSlot2Options2Delete[VmNameSlotKey(pszVmName, u8Slot)];
    303                 break;
    304 
    305             case 'n':   // --nic        Sets the option scope to pszVmName + (ValueUnion.u8 - 1).
    306                 if (!pszVmName)
    307                     return errorSyntax("--nic option requires a --vm preceeding selecting the VM it should apply to");
    308                 if (fNeedValueOrRemove)
    309                     return errorSyntax("Incomplete option sequence preseeding '--nic=%u", ValueUnion.u8);
    310                 u8Slot = ValueUnion.u8;
    311                 if (u8Slot < 1)
    312                     return errorSyntax("invalid NIC number: %u", u8Slot);
    313                 --u8Slot;
    314                 pScopeOptions        = &VmSlot2Options[VmNameSlotKey(pszVmName, u8Slot)];
    315                 pScopeOptions2Delete = &VmSlot2Options2Delete[VmNameSlotKey(pszVmName, u8Slot)];
    316                 break;
    317 
    318             case 'A':   // --add-opt num hexvalue
     403    /*
     404     * Parse the arguments in two passes:
     405     *
     406     *  1. Validate the command line and establish the IDHCPServer settings.
     407     *  2. Execute the various IDHCPConfig settings changes.
     408     *
     409     * This is considered simpler than duplicating the command line instructions
     410     * into elaborate structures and executing these.
     411     */
     412    RTEXITCODE          rcExit = RTEXITCODE_SUCCESS;
     413    ComPtr<IDHCPServer> ptrDHCPServer;
     414    for (size_t iPass = 0; iPass < 2; iPass++)
     415    {
     416        const char         *pszServerIp         = NULL;
     417        const char         *pszNetmask          = NULL;
     418        const char         *pszLowerIp          = NULL;
     419        const char         *pszUpperIp          = NULL;
     420        int                 fEnabled            = -1;
     421
     422        DHCPCmdScope        Scope;
     423        char                szMACAddress[32];
     424
     425        bool                fNeedValueOrRemove  = false; /* Only used with --id; remove in 6.1+ */
     426        uint8_t             u8OptId             = 0;     /* Only used too keep --id for following --value/--remove. remove in 6.1+ */
     427
     428        RTGETOPTSTATE GetState;
     429        int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
     430        AssertRCReturn(vrc, RTEXITCODE_FAILURE);
     431
     432        RTGETOPTUNION ValueUnion;
     433        while ((vrc = RTGetOpt(&GetState, &ValueUnion)))
     434        {
     435            switch (vrc)
    319436            {
    320                 uint8_t const idAddOpt = ValueUnion.u8;
    321                 vrc = RTGetOptFetchValue(&GetState, &ValueUnion, RTGETOPT_REQ_STRING);
    322                 if (RT_FAILURE(vrc))
    323                     return errorFetchValue(1, "--add-opt", vrc, &ValueUnion);
    324                 pScopeOptions->push_back(DhcpOptSpec((DhcpOpt_T)idAddOpt, Utf8Str(ValueUnion.psz)));
    325                 break;
     437                DHCPD_CMD_COMMON_OPTION_CASES(pCtx, vrc, &ValueUnion);
     438                case 'a':   // --server-ip
     439                    pszServerIp = ValueUnion.psz;
     440                    break;
     441                case 'm':   // --netmask
     442                    pszNetmask = ValueUnion.psz;
     443                    break;
     444                case 'l':   // --lower-ip
     445                    pszLowerIp = ValueUnion.psz;
     446                    break;
     447                case 'u':   // --upper-ip
     448                    pszUpperIp = ValueUnion.psz;
     449                    break;
     450                case 'e':   // --enable
     451                    fEnabled = 1;
     452                    break;
     453                case 'd':   // --disable
     454                    fEnabled = 0;
     455                    break;
     456
     457                /*
     458                 * Configuration selection:
     459                 */
     460                case 'g':   // --global     Sets the option scope to 'global'.
     461                    if (fNeedValueOrRemove)
     462                        return errorSyntax("Incomplete option sequence preseeding '--global'");
     463                    Scope.setGlobal();
     464                    break;
     465
     466                case 'G':   // --group
     467                    if (fNeedValueOrRemove)
     468                        return errorSyntax("Incomplete option sequence preseeding '--group'");
     469                    if (!*ValueUnion.psz)
     470                        return errorSyntax("Group name cannot be empty");
     471                    Scope.setGroup(ValueUnion.psz);
     472                    break;
     473
     474                case 'E':   // --mac-address
     475                    if (fNeedValueOrRemove)
     476                        return errorSyntax("Incomplete option sequence preseeding '--mac-address'");
     477                    RTStrPrintf(szMACAddress, sizeof(szMACAddress), "%RTmac", &ValueUnion.MacAddr);
     478                    Scope.setMACAddress(szMACAddress);
     479                    break;
     480
     481                case 'M':   // --vm         Sets the option scope to ValueUnion.psz + 0.
     482                    if (fNeedValueOrRemove)
     483                        return errorSyntax("Incomplete option sequence preseeding '--vm'");
     484                    Scope.setMachineNIC(ValueUnion.psz);
     485                    break;
     486
     487                case 'n':   // --nic        Sets the option scope to pszVmName + (ValueUnion.u8 - 1).
     488                    if (Scope.getScope() != DHCPConfigScope_MachineNIC)
     489                        return errorSyntax("--nic option requires a --vm preceeding selecting the VM it should apply to");
     490                    if (fNeedValueOrRemove)
     491                        return errorSyntax("Incomplete option sequence preseeding '--nic=%u", ValueUnion.u8);
     492                    if (ValueUnion.u8 < 1)
     493                        return errorSyntax("invalid NIC number: %u", ValueUnion.u8);
     494                    Scope.setMachineSlot(ValueUnion.u8 - 1);
     495                    break;
     496
     497                /*
     498                 * Modify configuration:
     499                 */
     500                case 's':   // --set-opt num stringvalue
     501                {
     502                    uint8_t const idAddOpt = ValueUnion.u8;
     503                    vrc = RTGetOptFetchValue(&GetState, &ValueUnion, RTGETOPT_REQ_STRING);
     504                    if (RT_FAILURE(vrc))
     505                        return errorFetchValue(1, "--set-opt", vrc, &ValueUnion);
     506                    if (iPass == 1)
     507                    {
     508                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
     509                        if (ptrConfig.isNull())
     510                            return RTEXITCODE_FAILURE;
     511                        CHECK_ERROR2I_STMT(ptrConfig, SetOption((DhcpOpt_T)idAddOpt, DHCPOptionEncoding_Legacy,
     512                                                                Bstr(ValueUnion.psz).raw()), rcExit = RTEXITCODE_FAILURE);
     513                    }
     514                    break;
     515                }
     516
     517                case 'x':   // --set-opt-hex num hex-string
     518                {
     519                    uint8_t const idAddOpt = ValueUnion.u8;
     520                    vrc = RTGetOptFetchValue(&GetState, &ValueUnion, RTGETOPT_REQ_STRING);
     521                    if (RT_FAILURE(vrc))
     522                        return errorFetchValue(1, "--set-opt-hex", vrc, &ValueUnion);
     523                    uint8_t abBuf[256];
     524                    size_t cbRet;
     525                    vrc = RTStrConvertHexBytesEx(ValueUnion.psz, abBuf, sizeof(abBuf), RTSTRCONVERTHEXBYTES_F_SEP_COLON,
     526                                                 NULL, &cbRet);
     527                    if (RT_FAILURE(vrc))
     528                        return errorArgument("Malformed hex string given to --set-opt-hex %u: %s\n", idAddOpt, ValueUnion.psz);
     529                    if (iPass == 1)
     530                    {
     531                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
     532                        if (ptrConfig.isNull())
     533                            return RTEXITCODE_FAILURE;
     534                        CHECK_ERROR2I_STMT(ptrConfig, SetOption((DhcpOpt_T)idAddOpt, DHCPOptionEncoding_Hex,
     535                                                                Bstr(ValueUnion.psz).raw()), rcExit = RTEXITCODE_FAILURE);
     536                    }
     537                    break;
     538                }
     539
     540                case 'D':   // --del-opt num
     541                    if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
     542                        return errorSyntax("--del-opt does not apply to the 'add' subcommand");
     543                    if (iPass == 1)
     544                    {
     545                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
     546                        if (ptrConfig.isNull())
     547                            return RTEXITCODE_FAILURE;
     548                        CHECK_ERROR2I_STMT(ptrConfig, RemoveOption((DhcpOpt_T)ValueUnion.u8), rcExit = RTEXITCODE_FAILURE);
     549                    }
     550                    break;
     551
     552                case DHCP_ADDMOD_ZAP_OPTIONS:
     553                    if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
     554                        return errorSyntax("--zap-options does not apply to the 'add' subcommand");
     555                    if (iPass == 1)
     556                    {
     557                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
     558                        if (ptrConfig.isNull())
     559                            return RTEXITCODE_FAILURE;
     560                        CHECK_ERROR2I_STMT(ptrConfig, RemoveAllOptions(), rcExit = RTEXITCODE_FAILURE);
     561                    }
     562                    break;
     563
     564                case 'q':   // --min-lease-time
     565                    if (iPass == 1)
     566                    {
     567                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
     568                        if (ptrConfig.isNull())
     569                            return RTEXITCODE_FAILURE;
     570                        CHECK_ERROR2I_STMT(ptrConfig, COMSETTER(MinLeaseTime)(ValueUnion.u32), rcExit = RTEXITCODE_FAILURE);
     571                    }
     572                    break;
     573
     574                case 'L':   // --default-lease-time
     575                    if (iPass == 1)
     576                    {
     577                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
     578                        if (ptrConfig.isNull())
     579                            return RTEXITCODE_FAILURE;
     580                        CHECK_ERROR2I_STMT(ptrConfig, COMSETTER(DefaultLeaseTime)(ValueUnion.u32), rcExit = RTEXITCODE_FAILURE);
     581                    }
     582                    break;
     583
     584                case 'Q':   // --max-lease-time
     585                    if (iPass == 1)
     586                    {
     587                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
     588                        if (ptrConfig.isNull())
     589                            return RTEXITCODE_FAILURE;
     590                        CHECK_ERROR2I_STMT(ptrConfig, COMSETTER(MaxLeaseTime)(ValueUnion.u32), rcExit = RTEXITCODE_FAILURE);
     591                    }
     592                    break;
     593
     594                case 'R':   // --remove-config
     595                    if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
     596                        return errorSyntax("--remove-config does not apply to the 'add' subcommand");
     597                    if (Scope.getScope() == DHCPConfigScope_Global)
     598                        return errorSyntax("--remove-config cannot be applied to the global config");
     599                    if (iPass == 1)
     600                    {
     601                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
     602                        if (ptrConfig.isNull())
     603                            return RTEXITCODE_FAILURE;
     604                        CHECK_ERROR2I_STMT(ptrConfig, Remove(), rcExit = RTEXITCODE_FAILURE);
     605                    }
     606                    Scope.setGlobal();
     607                    break;
     608
     609                case 'f':   // --fixed-address
     610                    if (Scope.getScope() != DHCPConfigScope_MachineNIC && Scope.getScope() != DHCPConfigScope_MAC)
     611                        return errorSyntax("--fixed-address can only be applied to a VM NIC or an MAC address");
     612                    if (iPass == 1)
     613                    {
     614                        ComPtr<IDHCPIndividualConfig> &ptrIndividualConfig = Scope.getIndividual(ptrDHCPServer);
     615                        if (ptrIndividualConfig.isNull())
     616                            return RTEXITCODE_FAILURE;
     617                        CHECK_ERROR2I_STMT(ptrIndividualConfig, COMSETTER(FixedAddress)(Bstr(ValueUnion.psz).raw()),
     618                                           rcExit = RTEXITCODE_FAILURE);
     619                    }
     620                    break;
     621
     622                /*
     623                 * Group conditions:
     624                 */
     625                case DHCP_ADDMOD_INCL_MAC:
     626                case DHCP_ADDMOD_EXCL_MAC:
     627                case DHCP_ADDMOD_DEL_MAC:
     628                case DHCP_ADDMOD_INCL_MAC_WILD:
     629                case DHCP_ADDMOD_EXCL_MAC_WILD:
     630                case DHCP_ADDMOD_DEL_MAC_WILD:
     631                case DHCP_ADDMOD_INCL_VENDOR:
     632                case DHCP_ADDMOD_EXCL_VENDOR:
     633                case DHCP_ADDMOD_DEL_VENDOR:
     634                case DHCP_ADDMOD_INCL_VENDOR_WILD:
     635                case DHCP_ADDMOD_EXCL_VENDOR_WILD:
     636                case DHCP_ADDMOD_DEL_VENDOR_WILD:
     637                case DHCP_ADDMOD_INCL_USER:
     638                case DHCP_ADDMOD_EXCL_USER:
     639                case DHCP_ADDMOD_DEL_USER:
     640                case DHCP_ADDMOD_INCL_USER_WILD:
     641                case DHCP_ADDMOD_EXCL_USER_WILD:
     642                case DHCP_ADDMOD_DEL_USER_WILD:
     643                {
     644                    if (Scope.getScope() != DHCPConfigScope_Group)
     645                        return errorSyntax("A group must be selected to perform condition alterations.");
     646                    if (!*ValueUnion.psz)
     647                        return errorSyntax("Condition value cannot be empty"); /* or can it? */
     648                    if (iPass != 1)
     649                        break;
     650
     651                    DHCPGroupConditionType enmType;
     652                    switch (vrc)
     653                    {
     654                        case DHCP_ADDMOD_INCL_MAC: case DHCP_ADDMOD_EXCL_MAC: case DHCP_ADDMOD_DEL_MAC:
     655                            enmType = DHCPGroupConditionType_MAC;
     656                            break;
     657                        case DHCP_ADDMOD_INCL_MAC_WILD: case DHCP_ADDMOD_EXCL_MAC_WILD: case DHCP_ADDMOD_DEL_MAC_WILD:
     658                            enmType = DHCPGroupConditionType_MACWildcard;
     659                            break;
     660                        case DHCP_ADDMOD_INCL_VENDOR: case DHCP_ADDMOD_EXCL_VENDOR: case DHCP_ADDMOD_DEL_VENDOR:
     661                            enmType = DHCPGroupConditionType_vendorClassID;
     662                            break;
     663                        case DHCP_ADDMOD_INCL_VENDOR_WILD: case DHCP_ADDMOD_EXCL_VENDOR_WILD: case DHCP_ADDMOD_DEL_VENDOR_WILD:
     664                            enmType = DHCPGroupConditionType_vendorClassIDWildcard;
     665                            break;
     666                        case DHCP_ADDMOD_INCL_USER: case DHCP_ADDMOD_EXCL_USER: case DHCP_ADDMOD_DEL_USER:
     667                            enmType = DHCPGroupConditionType_userClassID;
     668                            break;
     669                        case DHCP_ADDMOD_INCL_USER_WILD: case DHCP_ADDMOD_EXCL_USER_WILD: case DHCP_ADDMOD_DEL_USER_WILD:
     670                            enmType = DHCPGroupConditionType_userClassIDWildcard;
     671                            break;
     672                        default:
     673                            AssertFailedReturn(RTEXITCODE_FAILURE);
     674                    }
     675
     676                    int fInclusive;
     677                    switch (vrc)
     678                    {
     679                        case DHCP_ADDMOD_DEL_MAC:
     680                        case DHCP_ADDMOD_DEL_MAC_WILD:
     681                        case DHCP_ADDMOD_DEL_USER:
     682                        case DHCP_ADDMOD_DEL_USER_WILD:
     683                        case DHCP_ADDMOD_DEL_VENDOR:
     684                        case DHCP_ADDMOD_DEL_VENDOR_WILD:
     685                            fInclusive = -1;
     686                            break;
     687                        case DHCP_ADDMOD_EXCL_MAC:
     688                        case DHCP_ADDMOD_EXCL_MAC_WILD:
     689                        case DHCP_ADDMOD_EXCL_USER:
     690                        case DHCP_ADDMOD_EXCL_USER_WILD:
     691                        case DHCP_ADDMOD_EXCL_VENDOR:
     692                        case DHCP_ADDMOD_EXCL_VENDOR_WILD:
     693                            fInclusive = 0;
     694                            break;
     695                        case DHCP_ADDMOD_INCL_MAC:
     696                        case DHCP_ADDMOD_INCL_MAC_WILD:
     697                        case DHCP_ADDMOD_INCL_USER:
     698                        case DHCP_ADDMOD_INCL_USER_WILD:
     699                        case DHCP_ADDMOD_INCL_VENDOR:
     700                        case DHCP_ADDMOD_INCL_VENDOR_WILD:
     701                            fInclusive = 1;
     702                            break;
     703                        default:
     704                            AssertFailedReturn(RTEXITCODE_FAILURE);
     705                    }
     706
     707                    ComPtr<IDHCPGroupConfig> &ptrGroupConfig = Scope.getGroup(ptrDHCPServer);
     708                    if (ptrGroupConfig.isNull())
     709                        return RTEXITCODE_FAILURE;
     710                    if (fInclusive >= 0)
     711                    {
     712                        ComPtr<IDHCPGroupCondition> ptrCondition;
     713                        CHECK_ERROR2I_STMT(ptrGroupConfig, AddCondition((BOOL)fInclusive, enmType, Bstr(ValueUnion.psz).raw(),
     714                                                                        ptrCondition.asOutParam()), rcExit = RTEXITCODE_FAILURE);
     715                    }
     716                    else
     717                    {
     718                        com::SafeIfaceArray<IDHCPGroupCondition> Conditions;
     719                        CHECK_ERROR2I_STMT(ptrGroupConfig, COMGETTER(Conditions)(ComSafeArrayAsOutParam(Conditions)),
     720                                           rcExit = RTEXITCODE_FAILURE; break);
     721                        bool fFound = false;
     722                        for (size_t iCond = 0; iCond < Conditions.size(); iCond++)
     723                            {
     724                                DHCPGroupConditionType_T enmCurType = DHCPGroupConditionType_MAC;
     725                                CHECK_ERROR2I_STMT(Conditions[iCond], COMGETTER(Type)(&enmCurType),
     726                                                   rcExit = RTEXITCODE_FAILURE; continue);
     727                                if (enmCurType == enmType)
     728                                {
     729                                    Bstr bstrValue;
     730                                    CHECK_ERROR2I_STMT(Conditions[iCond], COMGETTER(Value)(bstrValue.asOutParam()),
     731                                                      rcExit = RTEXITCODE_FAILURE; continue);
     732                                    if (RTUtf16CmpUtf8(bstrValue.raw(), ValueUnion.psz) == 0)
     733                                    {
     734                                        CHECK_ERROR2I_STMT(Conditions[iCond], Remove(), rcExit = RTEXITCODE_FAILURE);
     735                                        fFound = true;
     736                                    }
     737                                }
     738                            }
     739                        if (!fFound)
     740                            rcExit = RTMsgErrorExitFailure("Could not find any condition of type %d with value '%s' to delete",
     741                                                           enmType, ValueUnion.psz);
     742                    }
     743                    break;
     744                }
     745
     746                case DHCP_ADDMOD_ZAP_CONDITIONS:
     747                    if (Scope.getScope() != DHCPConfigScope_Group)
     748                        return errorSyntax("--zap-conditions can only be with a group selected");
     749                    if (iPass == 1)
     750                    {
     751                        ComPtr<IDHCPGroupConfig> &ptrGroupConfig = Scope.getGroup(ptrDHCPServer);
     752                        if (ptrGroupConfig.isNull())
     753                            return RTEXITCODE_FAILURE;
     754                        CHECK_ERROR2I_STMT(ptrGroupConfig, RemoveAllConditions(), rcExit = RTEXITCODE_FAILURE);
     755                    }
     756                    break;
     757
     758                /*
     759                 * For backwards compatibility. Remove in 6.1 or later.
     760                 */
     761
     762                case 'o':   // --options - obsolete, ignored.
     763                    break;
     764
     765                case 'i':   // --id
     766                    if (fNeedValueOrRemove)
     767                        return errorSyntax("Incomplete option sequence preseeding '--id=%u", ValueUnion.u8);
     768                    u8OptId = ValueUnion.u8;
     769                    fNeedValueOrRemove = true;
     770                    break;
     771
     772                case 'p':   // --value
     773                    if (!fNeedValueOrRemove)
     774                        return errorSyntax("--value without --id=dhcp-opt-no");
     775                    if (iPass == 1)
     776                    {
     777                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
     778                        if (ptrConfig.isNull())
     779                            return RTEXITCODE_FAILURE;
     780                        CHECK_ERROR2I_STMT(ptrConfig, SetOption((DhcpOpt_T)u8OptId, DHCPOptionEncoding_Legacy,
     781                                                                Bstr(ValueUnion.psz).raw()), rcExit = RTEXITCODE_FAILURE);
     782                    }
     783                    fNeedValueOrRemove = false;
     784                    break;
     785
     786                case 'r':   // --remove
     787                    if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
     788                        return errorSyntax("--remove does not apply to the 'add' subcommand");
     789                    if (!fNeedValueOrRemove)
     790                        return errorSyntax("--remove without --id=dhcp-opt-no");
     791
     792                    if (iPass == 1)
     793                    {
     794                        ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer);
     795                        if (ptrConfig.isNull())
     796                            return RTEXITCODE_FAILURE;
     797                        CHECK_ERROR2I_STMT(ptrConfig, RemoveOption((DhcpOpt_T)u8OptId), rcExit = RTEXITCODE_FAILURE);
     798                    }
     799                    fNeedValueOrRemove = false;
     800                    break;
     801
     802                default:
     803                    return errorGetOpt(vrc, &ValueUnion);
    326804            }
    327 
    328             case 'D':   // --del-opt num
    329                 if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
    330                     return errorSyntax("--del-opt does not apply to the 'add' subcommand");
    331                 pScopeOptions2Delete->push_back((DhcpOpt_T)ValueUnion.u8);
    332                 break;
    333 
    334             /*
    335              * For backwards compatibility. Remove in 6.1 or later.
    336              */
    337 
    338             case 'o':   // --options - obsolete, ignored.
    339                 break;
    340 
    341             case 'i':   // --id
    342                 if (fNeedValueOrRemove)
    343                     return errorSyntax("Incomplete option sequence preseeding '--id=%u", ValueUnion.u8);
    344                 u8OptId = ValueUnion.u8;
    345                 fNeedValueOrRemove = true;
    346                 break;
    347 
    348             case 'p':   // --value
    349                 if (!fNeedValueOrRemove)
    350                     return errorSyntax("--value without --id=dhcp-opt-no");
    351                 pScopeOptions->push_back(DhcpOptSpec((DhcpOpt_T)u8OptId, Utf8Str(ValueUnion.psz)));
    352                 fNeedValueOrRemove = false;
    353                 break;
    354 
    355             case 'r':   // --remove
    356                 if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
    357                     return errorSyntax("--remove does not apply to the 'add' subcommand");
    358                 if (!fNeedValueOrRemove)
    359                     return errorSyntax("--remove without --id=dhcp-opt-no");
    360                 pScopeOptions2Delete->push_back((DhcpOpt_T)u8OptId);
    361                 /** @todo remove from pScopeOptions */
    362                 fNeedValueOrRemove = false;
    363                 break;
    364 
    365             default:
    366                 return errorGetOpt(vrc, &ValueUnion);
    367         }
    368     }
    369 
    370     /*
    371      * Ensure we've got mandatory options and supply defaults
    372      * where needed (modify case)
    373      */
    374     if (!pCtx->pszNetwork && !pCtx->pszInterface)
    375         return errorSyntax("You need to specify either --network or --interface to identify the DHCP server");
    376 
    377     if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
    378     {
     805        }
     806
     807        if (iPass != 0)
     808            break;
     809
     810        /*
     811         * Ensure we've got mandatory options and supply defaults
     812         * where needed (modify case)
     813         */
     814        if (!pCtx->pszNetwork && !pCtx->pszInterface)
     815            return errorSyntax("You need to specify either --network or --interface to identify the DHCP server");
     816
     817        if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
     818        {
     819            RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     820            if (!pszServerIp)
     821                rcExit = errorSyntax("Missing required option: --ip");
     822            if (!pszNetmask)
     823                rcExit = errorSyntax("Missing required option: --netmask");
     824            if (!pszLowerIp)
     825                rcExit = errorSyntax("Missing required option: --lowerip");
     826            if (!pszUpperIp)
     827                rcExit = errorSyntax("Missing required option: --upperip");
     828            if (rcExit != RTEXITCODE_SUCCESS)
     829                return rcExit;
     830        }
     831
     832        /*
     833         * Find or create the server.
     834         */
     835        HRESULT rc;
     836        Bstr NetName;
     837        if (!pCtx->pszNetwork)
     838        {
     839            ComPtr<IHost> host;
     840            CHECK_ERROR(pCtx->pArg->virtualBox, COMGETTER(Host)(host.asOutParam()));
     841
     842            ComPtr<IHostNetworkInterface> hif;
     843            CHECK_ERROR(host, FindHostNetworkInterfaceByName(Bstr(pCtx->pszInterface).mutableRaw(), hif.asOutParam()));
     844            if (FAILED(rc))
     845                return errorArgument("Could not find interface '%s'", pCtx->pszInterface);
     846
     847            CHECK_ERROR(hif, COMGETTER(NetworkName) (NetName.asOutParam()));
     848            if (FAILED(rc))
     849                return errorArgument("Could not get network name for the interface '%s'", pCtx->pszInterface);
     850        }
     851        else
     852        {
     853            NetName = Bstr(pCtx->pszNetwork);
     854        }
     855
     856        rc = pCtx->pArg->virtualBox->FindDHCPServerByNetworkName(NetName.mutableRaw(), ptrDHCPServer.asOutParam());
     857        if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
     858        {
     859            if (SUCCEEDED(rc))
     860                return errorArgument("DHCP server already exists");
     861
     862            CHECK_ERROR(pCtx->pArg->virtualBox, CreateDHCPServer(NetName.mutableRaw(), ptrDHCPServer.asOutParam()));
     863            if (FAILED(rc))
     864                return errorArgument("Failed to create the DHCP server");
     865        }
     866        else if (FAILED(rc))
     867            return errorArgument("DHCP server does not exist");
     868
     869        /*
     870         * Apply IDHCPServer settings:
     871         */
     872        HRESULT hrc;
    379873        RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    380         if (!pszServerIp)
    381             rcExit = errorSyntax("Missing required option: --ip");
    382         if (!pszNetmask)
    383             rcExit = errorSyntax("Missing required option: --netmask");
    384         if (!pszLowerIp)
    385             rcExit = errorSyntax("Missing required option: --lowerip");
    386         if (!pszUpperIp)
    387             rcExit = errorSyntax("Missing required option: --upperip");
    388         if (rcExit != RTEXITCODE_SUCCESS)
    389             return rcExit;
    390     }
    391 
    392     /*
    393      * Find or create the server.
    394      */
    395     HRESULT rc;
    396     Bstr NetName;
    397     if (!pCtx->pszNetwork)
    398     {
    399         ComPtr<IHost> host;
    400         CHECK_ERROR(pCtx->pArg->virtualBox, COMGETTER(Host)(host.asOutParam()));
    401 
    402         ComPtr<IHostNetworkInterface> hif;
    403         CHECK_ERROR(host, FindHostNetworkInterfaceByName(Bstr(pCtx->pszInterface).mutableRaw(), hif.asOutParam()));
    404         if (FAILED(rc))
    405             return errorArgument("Could not find interface '%s'", pCtx->pszInterface);
    406 
    407         CHECK_ERROR(hif, COMGETTER(NetworkName) (NetName.asOutParam()));
    408         if (FAILED(rc))
    409             return errorArgument("Could not get network name for the interface '%s'", pCtx->pszInterface);
    410     }
    411     else
    412     {
    413         NetName = Bstr(pCtx->pszNetwork);
    414     }
    415 
    416     ComPtr<IDHCPServer> svr;
    417     rc = pCtx->pArg->virtualBox->FindDHCPServerByNetworkName(NetName.mutableRaw(), svr.asOutParam());
    418     if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD)
    419     {
    420         if (SUCCEEDED(rc))
    421             return errorArgument("DHCP server already exists");
    422 
    423         CHECK_ERROR(pCtx->pArg->virtualBox, CreateDHCPServer(NetName.mutableRaw(), svr.asOutParam()));
    424         if (FAILED(rc))
    425             return errorArgument("Failed to create the DHCP server");
    426     }
    427     else if (FAILED(rc))
    428         return errorArgument("DHCP server does not exist");
    429 
    430     /*
    431      * Apply settings.
    432      */
    433     HRESULT hrc;
    434     RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    435     if (pszServerIp || pszNetmask || pszLowerIp || pszUpperIp)
    436     {
    437         Bstr bstrServerIp(pszServerIp);
    438         Bstr bstrNetmask(pszNetmask);
    439         Bstr bstrLowerIp(pszLowerIp);
    440         Bstr bstrUpperIp(pszUpperIp);
    441 
    442         if (!pszServerIp)
    443         {
    444             CHECK_ERROR2_RET(hrc, svr, COMGETTER(IPAddress)(bstrServerIp.asOutParam()), RTEXITCODE_FAILURE);
    445         }
    446         if (!pszNetmask)
    447         {
    448             CHECK_ERROR2_RET(hrc, svr, COMGETTER(NetworkMask)(bstrNetmask.asOutParam()), RTEXITCODE_FAILURE);
    449         }
    450         if (!pszLowerIp)
    451         {
    452             CHECK_ERROR2_RET(hrc, svr, COMGETTER(LowerIP)(bstrLowerIp.asOutParam()), RTEXITCODE_FAILURE);
    453         }
    454         if (!pszUpperIp)
    455         {
    456             CHECK_ERROR2_RET(hrc, svr, COMGETTER(UpperIP)(bstrUpperIp.asOutParam()), RTEXITCODE_FAILURE);
    457         }
    458 
    459         CHECK_ERROR2_STMT(hrc, svr, SetConfiguration(bstrServerIp.raw(), bstrNetmask.raw(), bstrLowerIp.raw(), bstrUpperIp.raw()),
    460                           rcExit = errorArgument("Failed to set configuration (%ls, %ls, %ls, %ls)", bstrServerIp.raw(),
    461                                                  bstrNetmask.raw(), bstrLowerIp.raw(), bstrUpperIp.raw()));
    462     }
    463 
    464     if (fEnabled >= 0)
    465     {
    466         CHECK_ERROR2_STMT(hrc, svr, COMSETTER(Enabled)((BOOL)fEnabled), rcExit = RTEXITCODE_FAILURE);
    467     }
    468 
    469     /* Remove options: */
    470     for (DhcpOptIdIterator itOptId = GlobalDhcpOptions2Delete.begin(); itOptId != GlobalDhcpOptions2Delete.end(); ++itOptId)
    471     {
    472         CHECK_ERROR2_STMT(hrc, svr, RemoveGlobalOption(*itOptId), rcExit = RTEXITCODE_FAILURE);
    473     }
    474 
    475     for (VmSlot2OptionIdsIterator itIdVector = VmSlot2Options2Delete.begin();
    476          itIdVector != VmSlot2Options2Delete.end(); ++itIdVector)
    477     {
    478         for (DhcpOptIdIterator itOptId = itIdVector->second.begin(); itOptId != itIdVector->second.end(); ++itOptId)
    479         {
    480             CHECK_ERROR2_STMT(hrc, svr, RemoveVmSlotOption(Bstr(itIdVector->first.VmName.c_str()).raw(),
    481                                                            itIdVector->first.u8Slot, *itOptId),
    482                               rcExit = RTEXITCODE_FAILURE);
    483         }
    484     }
    485 
    486     /* Global Options */
    487     for (DhcpOptIterator itOpt = GlobalDhcpOptions.begin(); itOpt != GlobalDhcpOptions.end(); ++itOpt)
    488     {
    489         CHECK_ERROR2_STMT(hrc, svr, AddGlobalOption(itOpt->first, com::Bstr(itOpt->second.c_str()).raw()),
    490                           rcExit = RTEXITCODE_FAILURE);
    491     }
    492 
    493     /* VM slot options. */
    494     for (VmSlot2OptionsIterator it = VmSlot2Options.begin(); it != VmSlot2Options.end(); ++it)
    495     {
    496         for (DhcpOptIterator itOpt = it->second.begin(); itOpt != it->second.end(); ++itOpt)
    497         {
    498             CHECK_ERROR2_STMT(hrc, svr, AddVmSlotOption(Bstr(it->first.VmName.c_str()).raw(), it->first.u8Slot, itOpt->first,
    499                                                         com::Bstr(itOpt->second).raw()),
    500                               rcExit = RTEXITCODE_FAILURE);
     874        if (pszServerIp || pszNetmask || pszLowerIp || pszUpperIp)
     875        {
     876            Bstr bstrServerIp(pszServerIp);
     877            Bstr bstrNetmask(pszNetmask);
     878            Bstr bstrLowerIp(pszLowerIp);
     879            Bstr bstrUpperIp(pszUpperIp);
     880
     881            if (!pszServerIp)
     882            {
     883                CHECK_ERROR2_RET(hrc, ptrDHCPServer, COMGETTER(IPAddress)(bstrServerIp.asOutParam()), RTEXITCODE_FAILURE);
     884            }
     885            if (!pszNetmask)
     886            {
     887                CHECK_ERROR2_RET(hrc, ptrDHCPServer, COMGETTER(NetworkMask)(bstrNetmask.asOutParam()), RTEXITCODE_FAILURE);
     888            }
     889            if (!pszLowerIp)
     890            {
     891                CHECK_ERROR2_RET(hrc, ptrDHCPServer, COMGETTER(LowerIP)(bstrLowerIp.asOutParam()), RTEXITCODE_FAILURE);
     892            }
     893            if (!pszUpperIp)
     894            {
     895                CHECK_ERROR2_RET(hrc, ptrDHCPServer, COMGETTER(UpperIP)(bstrUpperIp.asOutParam()), RTEXITCODE_FAILURE);
     896            }
     897
     898            CHECK_ERROR2_STMT(hrc, ptrDHCPServer, SetConfiguration(bstrServerIp.raw(), bstrNetmask.raw(),
     899                                                                   bstrLowerIp.raw(), bstrUpperIp.raw()),
     900                              rcExit = errorArgument("Failed to set configuration (%ls, %ls, %ls, %ls)", bstrServerIp.raw(),
     901                                                     bstrNetmask.raw(), bstrLowerIp.raw(), bstrUpperIp.raw()));
     902        }
     903
     904        if (fEnabled >= 0)
     905        {
     906            CHECK_ERROR2_STMT(hrc, ptrDHCPServer, COMSETTER(Enabled)((BOOL)fEnabled), rcExit = RTEXITCODE_FAILURE);
    501907        }
    502908    }
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp

    r79748 r79771  
    859859{
    860860    HRESULT hrcRet = S_OK;
    861     com::SafeIfaceArray<IDHCPServer> svrs;
    862     CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(DHCPServers)(ComSafeArrayAsOutParam(svrs)), hrcCheck);
    863     for (size_t i = 0; i < svrs.size(); ++i)
     861    com::SafeIfaceArray<IDHCPServer> DHCPServers;
     862    CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(DHCPServers)(ComSafeArrayAsOutParam(DHCPServers)), hrcCheck);
     863    for (size_t i = 0; i < DHCPServers.size(); ++i)
    864864    {
    865865        if (i > 0)
    866866            RTPrintf("\n");
    867867
    868         ComPtr<IDHCPServer> svr = svrs[i];
     868        ComPtr<IDHCPServer> ptrDHCPServer = DHCPServers[i];
    869869        Bstr bstr;
    870         CHECK_ERROR2I_STMT(svr, COMGETTER(NetworkName)(bstr.asOutParam()), hrcRet = hrcCheck);
     870        CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(NetworkName)(bstr.asOutParam()), hrcRet = hrcCheck);
    871871        RTPrintf("NetworkName:    %ls\n", bstr.raw());
    872872
    873         CHECK_ERROR2I_STMT(svr, COMGETTER(IPAddress)(bstr.asOutParam()), hrcRet = hrcCheck);
     873        CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(IPAddress)(bstr.asOutParam()), hrcRet = hrcCheck);
    874874        RTPrintf("Dhcpd IP:       %ls\n", bstr.raw());
    875875
    876         CHECK_ERROR2I_STMT(svr, COMGETTER(LowerIP)(bstr.asOutParam()), hrcRet = hrcCheck);
     876        CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(LowerIP)(bstr.asOutParam()), hrcRet = hrcCheck);
    877877        RTPrintf("LowerIPAddress: %ls\n", bstr.raw());
    878878
    879         CHECK_ERROR2I_STMT(svr, COMGETTER(UpperIP)(bstr.asOutParam()), hrcRet = hrcCheck);
     879        CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(UpperIP)(bstr.asOutParam()), hrcRet = hrcCheck);
    880880        RTPrintf("UpperIPAddress: %ls\n", bstr.raw());
    881881
    882         CHECK_ERROR2I_STMT(svr, COMGETTER(NetworkMask)(bstr.asOutParam()), hrcRet = hrcCheck);
     882        CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(NetworkMask)(bstr.asOutParam()), hrcRet = hrcCheck);
    883883        RTPrintf("NetworkMask:    %ls\n", bstr.raw());
    884884
    885885        BOOL fEnabled = FALSE;
    886         CHECK_ERROR2I_STMT(svr, COMGETTER(Enabled)(&fEnabled), hrcRet = hrcCheck);
     886        CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(Enabled)(&fEnabled), hrcRet = hrcCheck);
    887887        RTPrintf("Enabled:        %s\n", fEnabled ? "Yes" : "No");
    888888
     
    891891        HRESULT hrc;
    892892        ComPtr<IDHCPGlobalConfig> ptrGlobal;
    893         CHECK_ERROR2_STMT(hrc, svr, COMGETTER(GlobalConfig)(ptrGlobal.asOutParam()), hrcRet = hrc);
     893        CHECK_ERROR2_STMT(hrc, ptrDHCPServer, COMGETTER(GlobalConfig)(ptrGlobal.asOutParam()), hrcRet = hrc);
    894894        if (SUCCEEDED(hrc))
    895895        {
     
    901901        /* Group configurations: */
    902902        com::SafeIfaceArray<IDHCPGroupConfig> Groups;
    903         CHECK_ERROR2_STMT(hrc, svr, COMGETTER(GroupConfigs)(ComSafeArrayAsOutParam(Groups)), hrcRet = hrc);
     903        CHECK_ERROR2_STMT(hrc, ptrDHCPServer, COMGETTER(GroupConfigs)(ComSafeArrayAsOutParam(Groups)), hrcRet = hrc);
    904904        if (FAILED(hrc))
    905905            RTPrintf("Groups:               %Rrc\n", hrc);
     
    913913                RTPrintf("Group:                %ls\n", bstr.raw());
    914914
     915                com::SafeIfaceArray<IDHCPGroupCondition> Conditions;
     916                CHECK_ERROR2_STMT(hrc, Groups[iGrp], COMGETTER(Conditions)(ComSafeArrayAsOutParam(Conditions)), hrcRet = hrc);
     917                if (FAILED(hrc))
     918                    RTPrintf("    Conditions:       %Rhrc\n", hrc);
     919                else if (Conditions.size() == 0)
     920                    RTPrintf("    Conditions:       None\n");
     921                else
     922                    for (size_t iCond = 0; iCond < Conditions.size(); iCond++)
     923                    {
     924                        BOOL fInclusive = TRUE;
     925                        CHECK_ERROR2_STMT(hrc, Conditions[iCond], COMGETTER(Inclusive)(&fInclusive), hrcRet = hrc);
     926                        DHCPGroupConditionType_T enmType = DHCPGroupConditionType_MAC;
     927                        CHECK_ERROR2_STMT(hrc, Conditions[iCond], COMGETTER(Type)(&enmType), hrcRet = hrc);
     928                        CHECK_ERROR2_STMT(hrc, Conditions[iCond], COMGETTER(Value)(bstr.asOutParam()), hrcRet = hrc);
     929
     930                        RTPrintf("    Conditions:       %s %s %ls\n",
     931                                 fInclusive ? "include" : "exclude",
     932                                   enmType == DHCPGroupConditionType_MAC                    ? "MAC       "
     933                                 : enmType == DHCPGroupConditionType_MACWildcard            ? "MAC*      "
     934                                 : enmType == DHCPGroupConditionType_vendorClassID          ? "VendorCID "
     935                                 : enmType == DHCPGroupConditionType_vendorClassIDWildcard  ? "VendorCID*"
     936                                 : enmType == DHCPGroupConditionType_userClassID            ? "UserCID   "
     937                                 : enmType == DHCPGroupConditionType_userClassIDWildcard    ? "UserCID*  "
     938                                 :                                                            "!UNKNOWN! ",
     939                                 bstr.raw());
     940                    }
     941
    915942                hrc = showDhcpConfig(Groups[iGrp]);
    916943                if (FAILED(hrc))
     
    922949        /* Individual host / NIC configurations: */
    923950        com::SafeIfaceArray<IDHCPIndividualConfig> Hosts;
    924         CHECK_ERROR2_STMT(hrc, svr, COMGETTER(IndividualConfigs)(ComSafeArrayAsOutParam(Hosts)), hrcRet = hrc);
     951        CHECK_ERROR2_STMT(hrc, ptrDHCPServer, COMGETTER(IndividualConfigs)(ComSafeArrayAsOutParam(Hosts)), hrcRet = hrc);
    925952        if (FAILED(hrc))
    926953            RTPrintf("Individual Configs:   %Rrc\n", hrc);
     
    936963                if (enmScope == DHCPConfigScope_MAC)
    937964                {
    938                     CHECK_ERROR2I_STMT(Hosts[i], COMGETTER(MACAddress)(bstr.asOutParam()), hrcRet = hrcCheck);
     965                    CHECK_ERROR2I_STMT(Hosts[iHost], COMGETTER(MACAddress)(bstr.asOutParam()), hrcRet = hrcCheck);
    939966                    RTPrintf("Individual Config:    MAC %ls\n", bstr.raw());
    940967                }
     
    942969                {
    943970                    ULONG uSlot = 0;
    944                     CHECK_ERROR2I_STMT(Hosts[i], COMGETTER(Slot)(&uSlot), hrcRet = hrcCheck);
    945                     CHECK_ERROR2I_STMT(Hosts[i], COMGETTER(MachineId)(bstr.asOutParam()), hrcRet = hrcCheck);
     971                    CHECK_ERROR2I_STMT(Hosts[iHost], COMGETTER(Slot)(&uSlot), hrcRet = hrcCheck);
     972                    CHECK_ERROR2I_STMT(Hosts[iHost], COMGETTER(MachineId)(bstr.asOutParam()), hrcRet = hrcCheck);
    946973                    Bstr bstrMACAddress;
    947                     hrc = Hosts[i]->COMGETTER(MACAddress)(bstrMACAddress.asOutParam()); /* No CHECK_ERROR2 stuff! */
     974                    hrc = Hosts[iHost]->COMGETTER(MACAddress)(bstrMACAddress.asOutParam()); /* No CHECK_ERROR2 stuff! */
    948975                    if (SUCCEEDED(hrc))
    949976                        RTPrintf("Individual Config:    VM NIC: %ls slot %u, MAC %ls\n", bstr.raw(), uSlot, bstrMACAddress.raw());
     
    952979                }
    953980
    954                 CHECK_ERROR2I_STMT(Hosts[i], COMGETTER(FixedAddress)(bstr.asOutParam()), hrcRet = hrcCheck);
     981                CHECK_ERROR2I_STMT(Hosts[iHost], COMGETTER(FixedAddress)(bstr.asOutParam()), hrcRet = hrcCheck);
    955982                if (bstr.isNotEmpty())
    956983                    RTPrintf("    Fixed Address:    %ls\n", bstr.raw());
     
    958985                    RTPrintf("    Fixed Address:    dynamic\n");
    959986
    960                 hrc = showDhcpConfig(Hosts[i]);
     987                hrc = showDhcpConfig(Hosts[iHost]);
    961988                if (FAILED(hrc))
    962989                    hrcRet = hrc;
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r79747 r79771  
    21402140  <interface
    21412141    name="IDHCPConfig" extends="$unknown"
    2142     uuid="38fdb664-f65e-4905-ee56-a8a912871bbf"
     2142    uuid="39cdde66-cfc3-4eec-7427-faf5b16469ae"
    21432143    wsmap="managed"
    21442144    reservedMethods="8" reservedAttributes="16"
     
    22232223      </param>
    22242224    </method>
     2225
     2226    <method name="remove">
     2227      <desc>
     2228        Remove this group or individual configuration.
     2229        Will of course not work on global configurations.
     2230      </desc>
     2231    </method>
     2232
    22252233  </interface>
    22262234
     
    22602268  <interface
    22612269    name="IDHCPGroupConfig" extends="IDHCPConfig"
    2262     uuid="406a5eca-d032-4f65-a882-6bb626a424a5"
     2270    uuid="537707f7-ebf9-4d5c-7aea-877bfc4256ba"
    22632271    wsmap="managed"
    22642272    reservedMethods="8" reservedAttributes="8"
     
    22822290
    22832291    <method name="addCondition">
     2292      <desc>Adds a new condition.</desc>
    22842293      <param name="inclusive"  dir="in" type="boolean"/>
    22852294      <param name="type"       dir="in" type="DHCPGroupConditionType"/>
    22862295      <param name="value"      dir="in" type="wstring"/>
    22872296      <param name="condition"  dir="return" type="IDHCPGroupCondition"/>
     2297    </method>
     2298
     2299    <method name="removeAllConditions">
     2300      <desc>Removes all conditions.</desc>
    22882301    </method>
    22892302
  • trunk/src/VBox/Main/include/DHCPConfigImpl.h

    r79747 r79771  
    9999    HRESULT         i_getAllOptions(std::vector<DhcpOpt_T> &aOptions, std::vector<DHCPOptionEncoding_T> &aEncodings,
    100100                                    std::vector<com::Utf8Str> &aValues);
     101    virtual HRESULT i_remove();
    101102    /** @} */
    102103
     
    178179        return i_getAllOptions(aOptions, aEncodings, aValues);
    179180    }
     181
     182    HRESULT remove() RT_OVERRIDE
     183    {
     184        return i_remove();
     185    }
    180186    /** @} */
    181187
     
    184190    HRESULT i_removeOption(DhcpOpt_T aOption) RT_OVERRIDE;
    185191    HRESULT i_removeAllOptions() RT_OVERRIDE;
     192    HRESULT i_remove() RT_OVERRIDE;
    186193};
    187194
     
    225232
    226233    HRESULT i_saveSettings(settings::DHCPGroupCondition &a_rDst);
     234    static HRESULT i_validateTypeAndValue(DHCPGroupConditionType_T enmType, com::Utf8Str const &strValue,
     235                                          VirtualBoxBase *pErrorDst);
    227236
    228237protected:
     
    326335        return i_getAllOptions(aOptions, aEncodings, aValues);
    327336    }
     337
     338    HRESULT remove() RT_OVERRIDE
     339    {
     340        return i_remove();
     341    }
    328342    /** @} */
    329343
     
    332346    HRESULT addCondition(BOOL aInclusive, DHCPGroupConditionType_T aType, const com::Utf8Str &aValue,
    333347                         ComPtr<IDHCPGroupCondition> &aCondition) RT_OVERRIDE;
     348    HRESULT removeAllConditions() RT_OVERRIDE;
    334349    /** @} */
    335350};
     
    444459        return i_getAllOptions(aOptions, aEncodings, aValues);
    445460    }
     461
     462    HRESULT remove() RT_OVERRIDE
     463    {
     464        return i_remove();
     465    }
    446466    /** @} */
    447467
  • trunk/src/VBox/Main/include/DHCPServerImpl.h

    r79761 r79771  
    6969     * @{ */
    7070    HRESULT i_saveSettings(settings::DHCPServer &data);
     71    HRESULT i_removeConfig(DHCPConfig *pConfig, DHCPConfigScope_T enmScope);
    7172    /** @} */
    7273
  • trunk/src/VBox/Main/src-server/DHCPConfigImpl.cpp

    r79761 r79771  
    2424#include "LoggingNew.h"
    2525
     26#include <iprt/ctype.h>
    2627#include <iprt/errcore.h>
    2728#include <iprt/net.h>
     
    3334
    3435#include "AutoCaller.h"
     36#include "DHCPServerImpl.h"
    3537#include "MachineImpl.h"
    3638#include "VirtualBoxImpl.h"
     
    271273
    272274
     275HRESULT DHCPConfig::i_remove()
     276{
     277    return m_pParent->i_removeConfig(this, m_enmScope);
     278}
     279
     280
     281
    273282/**
    274283 * Causes the global VirtualBox configuration file to be written
     
    450459
    451460
     461/**
     462 * Overriden to prevent removal.
     463 */
     464HRESULT DHCPGlobalConfig::i_remove()
     465{
     466    return setError(E_ACCESSDENIED, tr("Cannot delete the global config"));
     467}
     468
     469
    452470
    453471/*********************************************************************************************************************************
     
    500518
    501519
     520/**
     521 * Worker for validating the condition value according to the given type.
     522 *
     523 * @returns COM status code.
     524 * @param   enmType             The condition type.
     525 * @param   strValue            The condition value.
     526 * @param   pErrorDst           The object to use for reporting errors.
     527 */
     528/*static*/ HRESULT DHCPGroupCondition::i_validateTypeAndValue(DHCPGroupConditionType_T enmType, com::Utf8Str const &strValue,
     529                                                              VirtualBoxBase *pErrorDst)
     530{
     531    switch (enmType)
     532    {
     533        case DHCPGroupConditionType_MAC:
     534        {
     535            RTMAC MACAddress;
     536            int vrc = RTNetStrToMacAddr(strValue.c_str(), &MACAddress);
     537            if (RT_SUCCESS(vrc))
     538                return S_OK;
     539            return pErrorDst->setError(E_INVALIDARG, pErrorDst->tr("Not a valid MAC address: %s"), strValue.c_str());
     540        }
     541
     542        case DHCPGroupConditionType_MACWildcard:
     543        {
     544            /* This must be colon separated double xdigit bytes.  Single bytes
     545               shorthand or raw hexstrings won't match anything.  For reasons of
     546               simplicity, '?' can only be used to match xdigits, '*' must match 1+
     547               chars. */
     548            /** @todo test this properly...   */
     549            const char *psz           = strValue.c_str();
     550            size_t      off           = 0;
     551            unsigned    cPairsLeft    = 6;
     552            bool        fSeenAsterisk = false;
     553            for (;;)
     554            {
     555                char ch = psz[off++];
     556                if (RT_C_IS_XDIGIT(ch) || ch == '?')
     557                {
     558                    ch = psz[off++];
     559                    if (RT_C_IS_XDIGIT(ch) || ch == '?')
     560                    {
     561                        ch = psz[off++];
     562                        cPairsLeft -= 1;
     563                        if (cPairsLeft == 0)
     564                        {
     565                            if (!ch)
     566                                return S_OK;
     567                            return pErrorDst->setError(E_INVALIDARG,
     568                                                       pErrorDst->tr("Trailing chars in MAC wildcard address: %s (offset %zu)"),
     569                                                       psz, off - 1);
     570                        }
     571                        if (ch == ':' || ch == '*')
     572                            continue;
     573                        if (ch == '\0' && fSeenAsterisk)
     574                            return S_OK;
     575                        return pErrorDst->setError(E_INVALIDARG,
     576                                                   pErrorDst->tr("Malformed MAC wildcard address: %s (offset %zu)"),
     577                                                   psz, off - 1);
     578                    }
     579
     580                    if (ch == '*')
     581                    {
     582                        fSeenAsterisk = true;
     583                        do
     584                            ch = psz[off++];
     585                        while (ch == '*');
     586                        if (ch == '\0')
     587                            return S_OK;
     588                        cPairsLeft -= 1;
     589                        if (cPairsLeft == 0)
     590                            return pErrorDst->setError(E_INVALIDARG,
     591                                                       pErrorDst->tr("Trailing chars in MAC wildcard address: %s (offset %zu)"),
     592                                                       psz, off - 1);
     593                        if (ch == ':')
     594                            continue;
     595                    }
     596                    else
     597                        return pErrorDst->setError(E_INVALIDARG, pErrorDst->tr("Malformed MAC wildcard address: %s (offset %zu)"),
     598                                                   psz, off - 1);
     599                }
     600                else if (ch == '*')
     601                {
     602                    fSeenAsterisk = true;
     603                    do
     604                        ch = psz[off++];
     605                    while (ch == '*');
     606                    if (ch == '\0')
     607                        return S_OK;
     608                    if (ch == ':')
     609                    {
     610                        cPairsLeft -= 1;
     611                        if (cPairsLeft == 0)
     612                            return pErrorDst->setError(E_INVALIDARG,
     613                                                       pErrorDst->tr("Trailing chars in MAC wildcard address: %s (offset %zu)"),
     614                                                       psz, off - 1);
     615                        continue;
     616                    }
     617
     618                }
     619                else
     620                    return pErrorDst->setError(E_INVALIDARG, pErrorDst->tr("Malformed MAC wildcard address: %s (offset %zu)"),
     621                                               psz, off - 1);
     622
     623                /* Pick up after '*' in the two cases above: ch is not ':' or '\0'. */
     624                Assert(ch != ':' && ch != '\0');
     625                if (RT_C_IS_XDIGIT(ch) || ch == '?')
     626                {
     627                    ch = psz[off++];
     628                    if (RT_C_IS_XDIGIT(ch) || ch == '?' || ch == '*')
     629                    {
     630                        off -= 2;
     631                        continue;
     632                    }
     633                    if (ch == ':')
     634                    {
     635                        ch = psz[off++];
     636                        if (ch == '\0')
     637                            return S_OK;
     638                        cPairsLeft -= 1;
     639                        if (cPairsLeft == 0)
     640                            return pErrorDst->setError(E_INVALIDARG,
     641                                                       pErrorDst->tr("Trailing chars in MAC wildcard address: %s (offset %zu)"),
     642                                                       psz, off - 1);
     643                        continue;
     644                    }
     645                    if (ch == '\0')
     646                        return S_OK;
     647                    return pErrorDst->setError(E_INVALIDARG,
     648                                               pErrorDst->tr("Trailing chars in MAC wildcard address: %s (offset %zu)"),
     649                                               psz, off - 1);
     650                }
     651                return pErrorDst->setError(E_INVALIDARG,
     652                                           pErrorDst->tr("Malformed MAC wildcard address: %s (offset %zu)"),
     653                                           psz, off - 1);
     654            }
     655            break;
     656        }
     657
     658        case DHCPGroupConditionType_vendorClassID:
     659        case DHCPGroupConditionType_vendorClassIDWildcard:
     660        case DHCPGroupConditionType_userClassID:
     661        case DHCPGroupConditionType_userClassIDWildcard:
     662            if (strValue.length() == 0)
     663                return pErrorDst->setError(E_INVALIDARG, pErrorDst->tr("Value cannot be empty"));
     664            if (strValue.length() < 255)
     665                return pErrorDst->setError(E_INVALIDARG, pErrorDst->tr("Value is too long: %zu bytes"), strValue.length());
     666            break;
     667
     668        default:
     669            return pErrorDst->setError(E_INVALIDARG, pErrorDst->tr("Invalid condition type: %d"), enmType);
     670    }
     671
     672    return S_OK;
     673}
     674
     675
    502676HRESULT DHCPGroupCondition::getInclusive(BOOL *aInclusive)
    503677{
     
    534708        if (aType == m_enmType)
    535709            return S_OK;
     710        HRESULT hrc = i_validateTypeAndValue(aType, m_strValue, this);
     711        if (FAILED(hrc))
     712            return hrc;
    536713        m_enmType = aType;
    537714    }
     
    553730        if (aValue == m_strValue)
    554731            return S_OK;
    555         HRESULT hrc = m_strValue.assignEx(aValue);
     732        HRESULT hrc = i_validateTypeAndValue(m_enmType, aValue, this);
     733        if (FAILED(hrc))
     734            return hrc;
     735        hrc = m_strValue.assignEx(aValue);
    556736        if (FAILED(hrc))
    557737            return hrc;
     
    728908                                      ComPtr<IDHCPGroupCondition> &aCondition)
    729909{
    730     ComObjPtr<DHCPGroupCondition> ptrCondition;
    731     HRESULT hrc = ptrCondition.createObject();
    732     if (SUCCEEDED(hrc))
    733         hrc = ptrCondition->initWithDefaults(this, aInclusive != FALSE, aType, aValue);
    734     if (SUCCEEDED(hrc))
    735     {
    736         hrc = ptrCondition.queryInterfaceTo(aCondition.asOutParam());
     910    /*
     911     * Valdiate it.
     912     */
     913    HRESULT hrc = DHCPGroupCondition::i_validateTypeAndValue(aType, aValue, this);
     914    if (SUCCEEDED(hrc))
     915    {
     916        /*
     917         * Add it.
     918         */
     919        ComObjPtr<DHCPGroupCondition> ptrCondition;
     920        hrc = ptrCondition.createObject();
     921        if (SUCCEEDED(hrc))
     922            hrc = ptrCondition->initWithDefaults(this, aInclusive != FALSE, aType, aValue);
    737923        if (SUCCEEDED(hrc))
    738924        {
    739             AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    740             try
     925            hrc = ptrCondition.queryInterfaceTo(aCondition.asOutParam());
     926            if (SUCCEEDED(hrc))
    741927            {
    742                 m_Conditions.push_back(ptrCondition);
    743             }
    744             catch (std::bad_alloc &)
    745             {
    746                 aCondition.setNull();
    747                 return E_OUTOFMEMORY;
     928                {
     929                    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     930                    try
     931                    {
     932                        m_Conditions.push_back(ptrCondition);
     933                    }
     934                    catch (std::bad_alloc &)
     935                    {
     936                        aCondition.setNull();
     937                        return E_OUTOFMEMORY;
     938                    }
     939                }
     940
     941                hrc = i_doWriteConfig();
     942                if (FAILED(hrc))
     943                    aCondition.setNull();
    748944            }
    749945        }
     
    751947
    752948    return hrc;
     949}
     950
     951
     952HRESULT DHCPGroupConfig::removeAllConditions()
     953{
     954    {
     955        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     956        if (m_Conditions.size() == 0)
     957            return S_OK;
     958
     959        /** @todo sever the weak parent link for each entry...  */
     960        m_Conditions.erase(m_Conditions.begin(), m_Conditions.end());
     961    }
     962
     963    return i_doWriteConfig();
    753964}
    754965
  • trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp

    r79761 r79771  
    311311
    312312
     313/**
     314 * Called by VirtualBox to save our settings.
     315 */
    313316HRESULT DHCPServer::i_saveSettings(settings::DHCPServer &rData)
    314317{
     
    367370
    368371    return hrc;
     372}
     373
     374
     375HRESULT DHCPServer::i_removeConfig(DHCPConfig *pConfig, DHCPConfigScope_T enmScope)
     376{
     377    {
     378        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     379
     380        bool fFound = false;
     381        switch (enmScope)
     382        {
     383            case DHCPConfigScope_Group:
     384                for (Data::GroupConfigIterator it = m->groupConfigs.begin(); it != m->groupConfigs.end();)
     385                {
     386                    DHCPConfig *pCurConfig = it->second;
     387                    if (pCurConfig == pConfig)
     388                    {
     389                        fFound = true;
     390                        it = m->groupConfigs.erase(it);
     391                    }
     392                    else
     393                        ++it;
     394                }
     395                break;
     396
     397            case DHCPConfigScope_MAC:
     398            case DHCPConfigScope_MachineNIC:
     399                for (Data::IndividualConfigIterator it = m->individualConfigs.begin(); it != m->individualConfigs.end();)
     400                {
     401                    DHCPConfig *pCurConfig = it->second;
     402                    if (pCurConfig == pConfig)
     403                    {
     404                        fFound = true;
     405                        it = m->individualConfigs.erase(it);
     406                    }
     407                    else
     408                        ++it;
     409                }
     410                break;
     411
     412            default:
     413                AssertFailedReturn(E_FAIL);
     414        }
     415
     416        /* Don't complain if already removed, right? */
     417        if (!fFound)
     418            return S_OK;
     419    }
     420
     421    return i_doSaveSettings();
    369422}
    370423
Note: See TracChangeset for help on using the changeset viewer.

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