VirtualBox

Changeset 79761 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 14, 2019 3:18:41 AM (5 years ago)
Author:
vboxsync
Message:

Main/DHCPServer,Dhcpd,VBoxManage: Added --log option to the DHCP server so we can start logging early. Added log rotation and limits. Put the config file next to the log and leases file. Validate DHCP options by reusing the parser code from the server, adding a bunch more DHCP options to the parser. Removed legacy and hardcoded configuration options from the dhcp server, it's all config file now. Fixed a bug in the option parsing of the VBoxManage dhcpserver add/modify commands. bugref:9288

Location:
trunk/src/VBox
Files:
13 edited

Legend:

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

    r79620 r79761  
    230230        { "--vm",               'M', RTGETOPT_REQ_STRING  },
    231231        { "--nic",              'n', RTGETOPT_REQ_UINT8   },
    232         { "--add-opt",          'A', RTGETOPT_REQ_STRING  },
    233         { "--del-opt",          'D', RTGETOPT_REQ_STRING  },
     232        { "--add-opt",          'A', RTGETOPT_REQ_UINT8   },
     233        { "--del-opt",          'D', RTGETOPT_REQ_UINT8   },
    234234        { "--id",               'i', RTGETOPT_REQ_UINT8   },    // obsolete, backwards compatibility only.
    235235        { "--value",            'p', RTGETOPT_REQ_STRING  },    // obsolete, backwards compatibility only.
     
    497497        {
    498498            CHECK_ERROR2_STMT(hrc, svr, AddVmSlotOption(Bstr(it->first.VmName.c_str()).raw(), it->first.u8Slot, itOpt->first,
    499                                                         com::Bstr(itOpt->second.c_str()).raw()),
     499                                                        com::Bstr(itOpt->second).raw()),
    500500                              rcExit = RTEXITCODE_FAILURE);
    501501        }
  • trunk/src/VBox/Main/Makefile.kmk

    r79732 r79761  
    444444##         VBoxC, you shall obviously put them in VBOX_MAIN_DEFS!  So, one way or the other they they disappear from here...
    445445VBoxSVC_DEFS = \
     446       IN_VBOXSVC \
    446447        VBOX_MAIN_SETTINGS_ADDONS \
    447448        IN_VMM_STATIC \
     
    551552        src-server/DHCPServerImpl.cpp \
    552553        src-server/DHCPConfigImpl.cpp \
     554        ../NetworkServices/Dhcpd/DhcpOptions.cpp \
    553555        src-server/NetworkServiceRunner.cpp \
    554556        src-server/NATNetworkImpl.cpp \
  • trunk/src/VBox/Main/include/DHCPServerImpl.h

    r79732 r79761  
    113113     * @{  */
    114114    HRESULT i_doSaveSettings();
    115     HRESULT i_calcLeasesFilename(const com::Utf8Str &aNetwork) RT_NOEXCEPT;
     115    HRESULT i_calcLeasesConfigAndLogFilenames(const com::Utf8Str &aNetwork) RT_NOEXCEPT;
    116116    HRESULT i_writeDhcpdConfig(const char *pszFilename, uint32_t uMACAddressVersion) RT_NOEXCEPT;
    117117
  • trunk/src/VBox/Main/include/NetworkServiceRunner.h

    r79644 r79761  
    5353    int  start(bool aKillProcessOnStop);
    5454    int  stop();
     55    void detachFromServer();
    5556    bool isRunning();
    56     void detachFromServer();
     57
     58    RTPROCESS getPid() const;
    5759
    5860    /** @name Common options
  • trunk/src/VBox/Main/src-server/DHCPConfigImpl.cpp

    r79747 r79761  
    3636#include "VirtualBoxImpl.h"
    3737
     38#include "../../NetworkServices/Dhcpd/DhcpOptions.h"
     39
    3840
    3941
     
    159161HRESULT DHCPConfig::i_setOption(DhcpOpt_T aOption, DHCPOptionEncoding_T aEncoding, const com::Utf8Str &aValue)
    160162{
    161     /** @todo validate option value format. */
    162     {
    163         AutoWriteLock alock(m_pHack COMMA_LOCKVAL_SRC_POS);
    164         try
     163    /*
     164     * Validate the option as there is no point in allowing the user to set
     165     * something that the DHCP server does not grok.  It will only lead to
     166     * startup failures an no DHCP.  We share this code with the server.
     167     */
     168    DhcpOption *pParsed = NULL;
     169    int         rc      = VINF_SUCCESS;
     170    try
     171    {
     172        pParsed = DhcpOption::parse((uint8_t)aOption, aEncoding, aValue.c_str(), &rc);
     173    }
     174    catch (std::bad_alloc &)
     175    {
     176        return E_OUTOFMEMORY;
     177    }
     178    if (pParsed)
     179    {
     180        delete pParsed;
     181
     182        /*
     183         * Add/change it.
     184         */
    165185        {
    166             m_OptionMap[aOption] = settings::DhcpOptValue(aValue, aEncoding);
     186            AutoWriteLock alock(m_pHack COMMA_LOCKVAL_SRC_POS);
     187            try
     188            {
     189                m_OptionMap[aOption] = settings::DhcpOptValue(aValue, aEncoding);
     190            }
     191            catch (std::bad_alloc &)
     192            {
     193                return E_OUTOFMEMORY;
     194            }
    167195        }
    168         catch (std::bad_alloc &)
    169         {
    170             return E_OUTOFMEMORY;
    171         }
    172     }
    173     i_doWriteConfig();
    174     return S_OK;
     196        i_doWriteConfig();
     197        return S_OK;
     198    }
     199
     200    if (rc == VERR_WRONG_TYPE)
     201        return m_pHack->setError(E_INVALIDARG, m_pHack->tr("Unsupported encoding %d (option %d, value %s)"),
     202                                 (int)aEncoding, (int)aOption, aValue.c_str());
     203    if (rc == VERR_NOT_SUPPORTED)
     204        return m_pHack->setError(E_INVALIDARG, m_pHack->tr("Unsupported option %d (encoding %d, value %s)"),
     205                                 (int)aOption, (int)aEncoding, aValue.c_str());
     206    return m_pHack->setError(E_INVALIDARG, m_pHack->tr("Malformed option %d value '%s' (encoding %d, rc=%Rrc)"),
     207                             (int)aOption, aValue.c_str(), (int)aEncoding, rc);
    175208}
    176209
  • trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp

    r79749 r79761  
    6565    virtual ~DHCPServerRunner()
    6666    {}
    67 
    68     static const char * const kDsrKeyConfig;
    69     static const char * const kDsrKeyComment;
    7067};
    71 
    72 /*static*/ const char * const DHCPServerRunner::kDsrKeyConfig  = "--config";
    73 /*static*/ const char * const DHCPServerRunner::kDsrKeyComment = "--comment";
    7468
    7569
     
    8579        , uIndividualMACAddressVersion(1)
    8680    {
    87         szTempConfigFileName[0] = '\0';
    8881    }
    8982
     
    10194    DHCPServerRunner dhcp;
    10295
    103     char szTempConfigFileName[RTPATH_MAX];
    10496    com::Utf8Str strLeasesFilename;
     97    com::Utf8Str strConfigFilename;
     98    com::Utf8Str strLogFilename;
     99
    105100    com::Utf8Str networkName;
    106101    com::Utf8Str trunkName;
     
    10791074    if (m->dhcp.isRunning())
    10801075        return setErrorBoth(VBOX_E_OBJECT_IN_USE, VERR_PROCESS_RUNNING,
    1081                             tr("Cannot start DHCP server because it is already running"));
     1076                            tr("Cannot start DHCP server because it is already running (pid %RTproc)"), m->dhcp.getPid());
    10821077
    10831078    /*
     
    10871082    m->trunkName   = aTrunkName;
    10881083    m->trunkType   = aTrunkType;
    1089     HRESULT hrc = i_calcLeasesFilename(aNetworkName);
     1084    HRESULT hrc = i_calcLeasesConfigAndLogFilenames(aNetworkName);
    10901085    if (SUCCEEDED(hrc))
    10911086    {
     
    10931088         * Create configuration file path and write out the configuration.
    10941089         */
    1095         /** @todo put this next to the leases file.   */
    1096         int vrc = RTPathTemp(m->szTempConfigFileName, sizeof(m->szTempConfigFileName));
    1097         if (RT_SUCCESS(vrc))
    1098             vrc = RTPathAppend(m->szTempConfigFileName, sizeof(m->szTempConfigFileName), "dhcp-config-XXXXX.xml");
    1099         if (RT_SUCCESS(vrc))
    1100             vrc = RTFileCreateTemp(m->szTempConfigFileName, 0600);
    1101         if (RT_SUCCESS(vrc))
    1102         {
    1103             hrc = i_writeDhcpdConfig(m->szTempConfigFileName, uMACAddressVersion);
    1104             if (SUCCEEDED(hrc))
     1090        hrc = i_writeDhcpdConfig(m->strConfigFilename.c_str(), uMACAddressVersion);
     1091        if (SUCCEEDED(hrc))
     1092        {
     1093            /*
     1094             * Setup the arguments and start the DHCP server.
     1095             */
     1096            m->dhcp.resetArguments();
     1097            int vrc = m->dhcp.addArgPair("--comment", m->networkName.c_str());
     1098            if (RT_SUCCESS(vrc))
     1099                vrc = m->dhcp.addArgPair("--config", m->strConfigFilename.c_str());
     1100            if (RT_SUCCESS(vrc))
     1101                vrc = m->dhcp.addArgPair("--log", m->networkName.c_str());
     1102            /** @todo Add --log-flags, --log-group-settings, and --log-destinations with
     1103             *        associated IDHCPServer attributes.  (Not doing it now because that'll
     1104             *        exhaust all reserved attribute slot in 6.0.) */
     1105            if (RT_SUCCESS(vrc))
    11051106            {
    1106                 /*
    1107                  * Setup the arguments and start the DHCP server.
    1108                  */
    1109                 m->dhcp.resetArguments();
    1110                 vrc = m->dhcp.addArgPair(DHCPServerRunner::kDsrKeyConfig, m->szTempConfigFileName);
    1111                 if (RT_SUCCESS(vrc))
    1112                     vrc = m->dhcp.addArgPair(DHCPServerRunner::kDsrKeyComment, m->networkName.c_str());
    1113                 if (RT_SUCCESS(vrc))
    1114                     vrc = m->dhcp.start(true /*aKillProcessOnStop*/);
     1107                /* Start it: */
     1108                vrc = m->dhcp.start(true /*aKillProcessOnStop*/);
    11151109                if (RT_FAILURE(vrc))
    11161110                    hrc = setErrorVrc(vrc, tr("Failed to start DHCP server for '%s': %Rrc"), m->strName.c_str(), vrc);
    11171111            }
    1118             if (FAILED(hrc))
    1119             {
    1120                 RTFileDelete(m->szTempConfigFileName);
    1121                 m->szTempConfigFileName[0] = '\0';
    1122             }
    1123         }
    1124         else
    1125         {
    1126             m->szTempConfigFileName[0] = '\0';
    1127             hrc = setErrorVrc(vrc);
     1112            else
     1113                hrc = setErrorVrc(vrc, tr("Failed to assemble the command line for DHCP server '%s': %Rrc"),
     1114                                  m->strName.c_str(), vrc);
    11281115        }
    11291116    }
     
    11351122{
    11361123    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    1137 
    1138     if (m->szTempConfigFileName[0])
    1139     {
    1140         RTFileDelete(m->szTempConfigFileName);
    1141         m->szTempConfigFileName[0] = '\0';
    1142     }
    11431124
    11441125    int vrc = m->dhcp.stop();
     
    11741155    if (m->strLeasesFilename.isEmpty())
    11751156    {
    1176         HRESULT hrc = i_calcLeasesFilename(m->networkName.isEmpty() ? m->strName : m->networkName);
     1157        HRESULT hrc = i_calcLeasesConfigAndLogFilenames(m->networkName.isEmpty() ? m->strName : m->networkName);
    11771158        if (FAILED(hrc))
    11781159            return hrc;
     
    14241405 * Calculates and updates the value of strLeasesFilename given @a aNetwork.
    14251406 */
    1426 HRESULT DHCPServer::i_calcLeasesFilename(const com::Utf8Str &aNetwork) RT_NOEXCEPT
     1407HRESULT DHCPServer::i_calcLeasesConfigAndLogFilenames(const com::Utf8Str &aNetwork) RT_NOEXCEPT
    14271408{
    14281409    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     
    14331414        vrc = RTPathAppendCxx(m->strLeasesFilename, aNetwork);
    14341415    if (RT_SUCCESS(vrc))
    1435         vrc = m->strLeasesFilename.appendNoThrow("-Dhcpd.leases");
    1436     if (RT_SUCCESS(vrc))
    14371416    {
    14381417        RTPathPurgeFilename(RTPathFilename(m->strLeasesFilename.mutableRaw()), RTPATH_STR_F_STYLE_HOST);
    1439         m->strLeasesFilename.jolt();
    1440         return S_OK;
    1441     }
    1442     return setErrorBoth(E_FAIL, vrc, tr("Failed to construct lease filename: %Rrc"), vrc);
    1443 }
    1444 
     1418
     1419        /* The configuration file: */
     1420        vrc = m->strConfigFilename.assignNoThrow(m->strLeasesFilename);
     1421        if (RT_SUCCESS(vrc))
     1422            vrc = m->strConfigFilename.appendNoThrow("-Dhcpd.config");
     1423
     1424
     1425        /* The log file: */
     1426        if (RT_SUCCESS(vrc))
     1427        {
     1428            vrc = m->strLogFilename.assignNoThrow(m->strLeasesFilename);
     1429            if (RT_SUCCESS(vrc))
     1430                vrc = m->strLogFilename.appendNoThrow("-Dhcpd.log");
     1431
     1432            /* Finally, complete the leases file: */
     1433            if (RT_SUCCESS(vrc))
     1434            {
     1435                vrc = m->strLeasesFilename.appendNoThrow("-Dhcpd.leases");
     1436                if (RT_SUCCESS(vrc))
     1437                {
     1438                    RTPathPurgeFilename(RTPathFilename(m->strLeasesFilename.mutableRaw()), RTPATH_STR_F_STYLE_HOST);
     1439                    m->strLeasesFilename.jolt();
     1440                    return S_OK;
     1441                }
     1442            }
     1443        }
     1444    }
     1445    return setErrorBoth(E_FAIL, vrc, tr("Failed to construct leases, config and log filenames: %Rrc"), vrc);
     1446}
     1447
  • trunk/src/VBox/Main/src-server/NetworkServiceRunner.cpp

    r79644 r79761  
    286286    return false;
    287287}
     288
     289
     290/**
     291 * Gets the process ID of a running service, NIL_PROCESS if not running.
     292 */
     293RTPROCESS NetworkServiceRunner::getPid() const
     294{
     295    return m->Process;
     296}
     297
  • trunk/src/VBox/NetworkServices/Dhcpd/Config.cpp

    r79622 r79761  
    3636
    3737
     38/*********************************************************************************************************************************
     39*   Global Variables                                                                                                             *
     40*********************************************************************************************************************************/
     41/*static*/ bool Config::g_fInitializedLog = false;
     42
     43
    3844/**
    3945 * Configuration file exception.
     
    7076    : m_strHome()
    7177    , m_strNetwork()
    72     , m_strBaseName()
    7378    , m_strTrunk()
    7479    , m_enmTrunkType(kIntNetTrunkType_Invalid)
     
    140145
    141146/**
    142  * Internal network name (m_strNetwork) setter.
    143  *
    144  * Can only be called once.  Will also invoke i_sanitizeBaseName to update
    145  * m_strBaseName.
    146  *
    147  * @throws std::bad_alloc
    148  */
    149 void Config::i_setNetwork(const RTCString &aStrNetwork)
    150 {
    151     AssertReturnVoid(m_strNetwork.isEmpty());
    152 
    153     m_strNetwork = aStrNetwork;
    154     i_sanitizeBaseName();
    155 }
    156 
    157 
    158 /**
    159  * Interal worker for i_setNetwork() that sets m_strBaseName to sanitized the
    160  * version of m_strNetwork suitable for use as a path component.
    161  *
    162  * @throws std::bad_alloc
    163  */
    164 void Config::i_sanitizeBaseName()
    165 {
    166     if (m_strNetwork.isNotEmpty())
    167     {
    168         m_strBaseName = m_strNetwork;
    169         RTPathPurgeFilename(m_strBaseName.mutableRaw(), RTPATH_STR_F_STYLE_HOST);
    170         m_strBaseName.jolt();
    171     }
    172     else
    173         m_strBaseName.setNull();
    174 }
    175 
    176 
    177 /**
    178147 * Worker for i_complete() that initializes the release log of the process.
    179148 *
     
    182151 * command line?
    183152 *
    184  * @todo make the log file directly configurable?
     153 * @note This is only used when no --log parameter was given.
    185154 */
    186155int Config::i_logInit() RT_NOEXCEPT
    187156{
    188     if (m_strHome.isEmpty() || m_strBaseName.isEmpty())
     157    if (g_fInitializedLog)
     158        return VINF_SUCCESS;
     159
     160    if (m_strHome.isEmpty() || m_strNetwork.isEmpty())
    189161        return VERR_PATH_ZERO_LENGTH;
    190162
     
    193165    ssize_t cch = RTStrPrintf2(szLogFile, sizeof(szLogFile),
    194166                               "%s%c%s-Dhcpd.log",
    195                                m_strHome.c_str(), RTPATH_DELIMITER, m_strBaseName.c_str());
    196     if (cch <= 0)
    197         return VERR_BUFFER_OVERFLOW;
    198 
    199     /* Sanitize base name some more to be usable in an environment variable name: */
    200     char szEnvVarBase[128];
    201     cch = RTStrPrintf(szEnvVarBase, sizeof(szEnvVarBase), "VBOXDHCP_%s_RELEASE_LOG", m_strBaseName.c_str());
    202     if (cch <= 0)
    203         return VERR_BUFFER_OVERFLOW;
    204     for (char *p = szEnvVarBase; *p != '\0'; ++p)
    205         if (*p != '_' && !RT_C_IS_ALNUM(*p))
    206             *p = '_';
     167                               m_strHome.c_str(), RTPATH_DELIMITER, m_strNetwork.c_str());
     168    if (cch > 0)
     169    {
     170        RTPathPurgeFilename(RTPathFilename(szLogFile), RTPATH_STR_F_STYLE_HOST);
     171        return i_logInitWithFilename(szLogFile);
     172    }
     173    return VERR_BUFFER_OVERFLOW;
     174}
     175
     176
     177/**
     178 * Worker for i_logInit and for handling --log on the command line.
     179 *
     180 * @returns IPRT status code.
     181 * @param   pszFilename         The log filename.
     182 */
     183/*static*/ int Config::i_logInitWithFilename(const char *pszFilename) RT_NOEXCEPT
     184{
     185    AssertReturn(!g_fInitializedLog, VERR_WRONG_ORDER);
    207186
    208187    int rc = com::VBoxLogRelCreate("DHCP Server",
    209                                    szLogFile,
     188                                   pszFilename,
    210189                                   RTLOGFLAGS_PREFIX_TIME_PROG,
    211                                    "all all.restrict -default.restrict",
    212                                    szEnvVarBase,
     190                                   "all net_dhcpd.e.l",
     191                                   "VBOXDHCP_RELEASE_LOG",
    213192                                   RTLOGDEST_FILE
    214193#ifdef DEBUG
     
    217196                                   ,
    218197                                   32768 /* cMaxEntriesPerGroup */,
    219                                    0 /* cHistory */,
    220                                    0 /* uHistoryFileTime */,
    221                                    0 /* uHistoryFileSize */,
     198                                   5 /* cHistory */,
     199                                   RT_SEC_1DAY /* uHistoryFileTime */,
     200                                   _32M /* uHistoryFileSize */,
    222201                                   NULL /* pErrInfo */);
    223 
     202    if (RT_SUCCESS(rc))
     203        g_fInitializedLog = true;
     204    else
     205        RTMsgError("Log initialization failed: %Rrc, log file '%s'", rc, pszFilename);
    224206    return rc;
     207
    225208}
    226209
     
    324307
    325308
    326 /*static*/ Config *Config::hardcoded() RT_NOEXCEPT
    327 {
    328     std::unique_ptr<Config> config(i_createInstanceAndCallInit());
    329     AssertReturn(config.get() != NULL, NULL);
    330     try
    331     {
    332         config->i_setNetwork("HostInterfaceNetworking-vboxnet0");
    333         config->m_strTrunk.assign("vboxnet0");
    334     }
    335     catch (std::bad_alloc &)
    336     {
    337         return NULL;
    338     }
    339     config->m_enmTrunkType = kIntNetTrunkType_NetFlt;
    340 
    341     config->m_MacAddress.au8[0] = 0x08;
    342     config->m_MacAddress.au8[1] = 0x00;
    343     config->m_MacAddress.au8[2] = 0x27;
    344     config->m_MacAddress.au8[3] = 0xa9;
    345     config->m_MacAddress.au8[4] = 0xcf;
    346     config->m_MacAddress.au8[5] = 0xef;
    347 
    348 
    349     config->m_IPv4Address.u     = RT_H2N_U32_C(0xc0a838fe); /* 192.168.56.254 */
    350     config->m_IPv4Netmask.u     = RT_H2N_U32_C(0xffffff00); /* 255.255.255.0 */
    351 
    352     /* flip to test naks */
    353 #if 1
    354     config->m_IPv4PoolFirst.u   = RT_H2N_U32_C(0xc0a8385a); /* 192.168.56.90 */
    355     config->m_IPv4PoolLast.u    = RT_H2N_U32_C(0xc0a83863); /* 192.168.56.99 */
    356 #else
    357     config->m_IPv4PoolFirst.u   = RT_H2N_U32_C(0xc0a838c9); /* 192.168.56.201 */
    358     config->m_IPv4PoolLast.u    = RT_H2N_U32_C(0xc0a838dc); /* 192.168.56.220 */
    359 #endif
    360 
    361     int rc = config->i_complete();
     309/**
     310 * Parses the command line and loads the configuration.
     311 *
     312 * @returns The configuration, NULL if we ran into some fatal problem.
     313 * @param   argc    The argc from main().
     314 * @param   argv    The argv from main().
     315 */
     316Config *Config::create(int argc, char **argv) RT_NOEXCEPT
     317{
     318    /*
     319     * Parse the command line.
     320     */
     321    static const RTGETOPTDEF s_aOptions[] =
     322    {
     323        { "--comment",              '#', RTGETOPT_REQ_STRING },
     324        { "--config",               'c', RTGETOPT_REQ_STRING },
     325        { "--log",                  'l', RTGETOPT_REQ_STRING },
     326        { "--log-destinations",     'd', RTGETOPT_REQ_STRING },
     327        { "--log-flags",            'f', RTGETOPT_REQ_STRING },
     328        { "--log-group-settings",   'g', RTGETOPT_REQ_STRING },
     329    };
     330
     331    RTGETOPTSTATE State;
     332    int rc = RTGetOptInit(&State, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
    362333    AssertRCReturn(rc, NULL);
    363334
    364     return config.release();
    365 }
    366 
    367 
    368 /**
    369  * Old VBoxNetDHCP style command line parsing.
    370  *
    371  * @throws std::bad_alloc
    372  */
    373 /*static*/ Config *Config::compat(int argc, char **argv)
    374 {
    375     /* compatibility with old VBoxNetDHCP */
    376     static const RTGETOPTDEF s_aCompatOptions[] =
    377     {
    378         { "--ip-address",     'i',   RTGETOPT_REQ_IPV4ADDR },
    379         { "--lower-ip",       'l',   RTGETOPT_REQ_IPV4ADDR },
    380         { "--mac-address",    'a',   RTGETOPT_REQ_MACADDR },
    381         { "--need-main",      'M',   RTGETOPT_REQ_BOOL },
    382         { "--netmask",        'm',   RTGETOPT_REQ_IPV4ADDR },
    383         { "--network",        'n',   RTGETOPT_REQ_STRING },
    384         { "--trunk-name",     't',   RTGETOPT_REQ_STRING },
    385         { "--trunk-type",     'T',   RTGETOPT_REQ_STRING },
    386         { "--upper-ip",       'u',   RTGETOPT_REQ_IPV4ADDR },
    387     };
    388 
    389     RTGETOPTSTATE State;
    390     int rc = RTGetOptInit(&State, argc, argv, s_aCompatOptions, RT_ELEMENTS(s_aCompatOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
    391     AssertRCReturn(rc, NULL);
    392 
    393     std::unique_ptr<Config> config(i_createInstanceAndCallInit());
    394     AssertReturn(config.get() != NULL, NULL);
     335    const char *pszLogFile          = NULL;
     336    const char *pszLogGroupSettings = NULL;
     337    const char *pszLogDestinations  = NULL;
     338    const char *pszLogFlags         = NULL;
     339    const char *pszConfig           = NULL;
     340    const char *pszComment          = NULL;
    395341
    396342    for (;;)
     
    403349        switch (rc)
    404350        {
    405             case 'a': /* --mac-address */
    406                 if (   config->m_MacAddress.au16[0] != 0
    407                     || config->m_MacAddress.au16[1] != 0
    408                     || config->m_MacAddress.au16[2] != 0)
    409                 {
    410                     RTMsgError("Duplicate --mac-address option");
    411                     return NULL;
    412                 }
    413                 config->m_MacAddress = ValueUnion.MacAddr;
     351            case 'c': /* --config */
     352                pszConfig = ValueUnion.psz;
    414353                break;
    415354
    416             case 'i': /* --ip-address */
    417                 if (config->m_IPv4Address.u != 0)
    418                 {
    419                     RTMsgError("Duplicate --ip-address option");
    420                     return NULL;
    421                 }
    422                 config->m_IPv4Address = ValueUnion.IPv4Addr;
     355            case 'l':
     356                pszLogFile = ValueUnion.psz;
    423357                break;
    424358
    425             case 'l': /* --lower-ip */
    426                 if (config->m_IPv4PoolFirst.u != 0)
    427                 {
    428                     RTMsgError("Duplicate --lower-ip option");
    429                     return NULL;
    430                 }
    431                 config->m_IPv4PoolFirst = ValueUnion.IPv4Addr;
     359            case 'd':
     360                pszLogDestinations = ValueUnion.psz;
    432361                break;
    433362
    434             case 'M': /* --need-main */
    435                 /* for backward compatibility, ignored */
     363            case 'f':
     364                pszLogFlags = ValueUnion.psz;
    436365                break;
    437366
    438             case 'm': /* --netmask */
    439                 if (config->m_IPv4Netmask.u != 0)
    440                 {
    441                     RTMsgError("Duplicate --netmask option");
    442                     return NULL;
    443                 }
    444                 config->m_IPv4Netmask = ValueUnion.IPv4Addr;
     367            case 'g':
     368                pszLogGroupSettings = ValueUnion.psz;
    445369                break;
    446370
    447             case 'n': /* --network */
    448                 if (!config->m_strNetwork.isEmpty())
    449                 {
    450                     RTMsgError("Duplicate --network option");
    451                     return NULL;
    452                 }
    453                 config->i_setNetwork(ValueUnion.psz);
     371            case '#': /* --comment */
     372                /* The sole purpose of this option is to allow identification of DHCP
     373                 * server instances in the process list. We ignore the required string
     374                 * argument of this option. */
     375                pszComment = ValueUnion.psz;
    454376                break;
    455377
    456             case 't': /* --trunk-name */
    457                 if (!config->m_strTrunk.isEmpty())
    458                 {
    459                     RTMsgError("Duplicate --trunk-name option");
    460                     return NULL;
    461                 }
    462                 config->m_strTrunk.assign(ValueUnion.psz);
    463                 break;
    464 
    465             case 'T': /* --trunk-type */
    466                 if (config->m_enmTrunkType != kIntNetTrunkType_Invalid)
    467                 {
    468                     RTMsgError("Duplicate --trunk-type option");
    469                     return NULL;
    470                 }
    471                 else if (strcmp(ValueUnion.psz, "none") == 0)
    472                     config->m_enmTrunkType = kIntNetTrunkType_None;
    473                 else if (strcmp(ValueUnion.psz, "whatever") == 0)
    474                     config->m_enmTrunkType = kIntNetTrunkType_WhateverNone;
    475                 else if (strcmp(ValueUnion.psz, "netflt") == 0)
    476                     config->m_enmTrunkType = kIntNetTrunkType_NetFlt;
    477                 else if (strcmp(ValueUnion.psz, "netadp") == 0)
    478                     config->m_enmTrunkType = kIntNetTrunkType_NetAdp;
    479                 else
    480                 {
    481                     RTMsgError("Unknown trunk type '%s'", ValueUnion.psz);
    482                     return NULL;
    483                 }
    484                 break;
    485 
    486             case 'u': /* --upper-ip */
    487                 if (config->m_IPv4PoolLast.u != 0)
    488                 {
    489                     RTMsgError("Duplicate --upper-ip option");
    490                     return NULL;
    491                 }
    492                 config->m_IPv4PoolLast = ValueUnion.IPv4Addr;
    493                 break;
    494 
    495378            case VINF_GETOPT_NOT_OPTION:
    496                 RTMsgError("%s: Unexpected command line argument", ValueUnion.psz);
     379                RTMsgError("Unexpected command line argument: '%s'", ValueUnion.psz);
    497380                return NULL;
    498381
     
    503386    }
    504387
    505     rc = config->i_complete();
    506     if (RT_FAILURE(rc))
     388    if (!pszConfig)
     389    {
     390        RTMsgError("No configuration file specified (--config file)!\n");
    507391        return NULL;
    508 
    509     return config.release();
    510 }
    511 
    512 
    513 Config *Config::create(int argc, char **argv) RT_NOEXCEPT
    514 {
    515     static const RTGETOPTDEF s_aOptions[] =
    516     {
    517         { "--config",       'c', RTGETOPT_REQ_STRING },
    518         { "--comment",      '#', RTGETOPT_REQ_STRING }
    519     };
    520 
    521     RTGETOPTSTATE State;
    522     int rc = RTGetOptInit(&State, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
    523     AssertRCReturn(rc, NULL);
    524 
    525     std::unique_ptr<Config> config;
    526 
    527     for (;;)
    528     {
    529         RTGETOPTUNION ValueUnion;
    530         rc = RTGetOpt(&State, &ValueUnion);
    531         if (rc == 0)            /* done */
    532             break;
    533 
    534         switch (rc)
    535         {
    536             case 'c': /* --config */
    537                 if (config.get() != NULL)
    538                 {
    539                     RTMsgError("Duplicate option: --config '%s'\n", ValueUnion.psz);
    540                     return NULL;
    541                 }
    542 
    543                 RTMsgInfo("reading config from '%s'...\n", ValueUnion.psz);
    544                 config.reset(Config::i_read(ValueUnion.psz));
    545                 if (config.get() == NULL)
    546                     return NULL;
    547                 break;
    548 
    549             case '#': /* --comment */
    550                 /* The sole purpose of this option is to allow identification of DHCP
    551                  * server instances in the process list. We ignore the required string
    552                  * argument of this option.
    553                  */
    554                 continue;
    555 
    556             case VINF_GETOPT_NOT_OPTION:
    557                 RTMsgError("Unexpected command line argument: '%s'", ValueUnion.psz);
    558                 return NULL;
    559 
    560             default:
    561                 RTGetOptPrintError(rc, &ValueUnion);
    562                 return NULL;
    563         }
    564     }
    565 
    566     if (config.get() != NULL)
    567     {
    568         rc = config->i_complete();
     392    }
     393
     394    /*
     395     * Init the log if a log file was specified.
     396     */
     397    if (pszLogFile)
     398    {
     399        rc = i_logInitWithFilename(pszLogFile);
     400        if (RT_FAILURE(rc))
     401            RTMsgError("Failed to initialize log file '%s': %Rrc", pszLogFile, rc);
     402
     403        if (pszLogDestinations)
     404            RTLogDestinations(RTLogRelGetDefaultInstance(), pszLogDestinations);
     405        if (pszLogFlags)
     406            RTLogFlags(RTLogRelGetDefaultInstance(), pszLogFlags);
     407        if (pszLogGroupSettings)
     408            RTLogGroupSettings(RTLogRelGetDefaultInstance(), pszLogGroupSettings);
     409
     410        LogRel(("--config:  %s\n", pszComment));
     411        if (pszComment)
     412            LogRel(("--comment: %s\n", pszComment));
     413    }
     414
     415    /*
     416     * Read the log file.
     417     */
     418    RTMsgInfo("reading config from '%s'...\n", pszConfig);
     419    std::unique_ptr<Config> ptrConfig;
     420    ptrConfig.reset(Config::i_read(pszConfig));
     421    if (ptrConfig.get() != NULL)
     422    {
     423        rc = ptrConfig->i_complete();
    569424        if (RT_SUCCESS(rc))
    570             return config.release();
    571     }
    572     else
    573         RTMsgError("No configuration file specified (--config file)!\n");
     425            return ptrConfig.release();
     426    }
    574427    return NULL;
    575428}
     
    693546     * <DHCPServer> attributes
    694547     */
    695     const char *pszNetworkName;
    696     if (pElmServer->getAttributeValue("networkName", &pszNetworkName))
    697         i_setNetwork(pszNetworkName);
    698     else
     548    if (!pElmServer->getAttributeValue("networkName", m_strNetwork))
    699549        throw ConfigFileError("DHCPServer/@networkName missing");
    700     /** @todo log file override.  */
    701     /** @todo log level (dhcpd group flags).  */
    702     /** @todo log flags.  */
    703     /** @todo control logging to stderr/out.  */
    704     /** @todo if we like we could open the release log now.   */
     550    if (m_strNetwork.isEmpty())
     551        throw ConfigFileError("DHCPServer/@networkName is empty");
    705552
    706553    const char *pszTrunkType;
     
    732579        int rc = m_strLeasesFilename.assignNoThrow(getHome());
    733580        if (RT_SUCCESS(rc))
    734             rc = RTPathAppendCxx(m_strLeasesFilename, getBaseName());
     581            rc = RTPathAppendCxx(m_strLeasesFilename, m_strNetwork);
    735582        if (RT_SUCCESS(rc))
    736583            rc = m_strLeasesFilename.appendNoThrow("-Dhcpd.leases");
    737584        if (RT_FAILURE(rc))
    738585            throw ConfigFileError("Unexpected error constructing default m_strLeasesFilename value: %Rrc", rc);
     586        RTPathPurgeFilename(RTPathFilename(m_strLeasesFilename.mutableRaw()), RTPATH_STR_F_STYLE_HOST);
     587        m_strLeasesFilename.jolt();
    739588    }
    740589
     
    857706    int rc = RTStrToUInt8Full(pszName, 10, &u8Opt);
    858707    if (rc != VINF_SUCCESS) /* no warnings either */
    859         throw ConfigFileError("Bad option name '%s'", pszName);
     708        throw ConfigFileError("Bad option name '%s': %Rrc", pszName, rc);
    860709
    861710    /* The opional 'encoding' attribute: */
    862     uint32_t u32Enc = 0;        /* XXX: DhcpOptEncoding_Legacy */
     711    uint32_t u32Enc = 0;            /* XXX: DhcpOptEncoding_Legacy */
    863712    const char *pszEncoding;
    864713    if (pElmOption->getAttributeValue("encoding", &pszEncoding))
     
    866715        rc = RTStrToUInt32Full(pszEncoding, 10, &u32Enc);
    867716        if (rc != VINF_SUCCESS) /* no warnings either */
    868             throw ConfigFileError("Bad option encoding '%s'", pszEncoding);
     717            throw ConfigFileError("Bad option encoding '%s': %Rrc", pszEncoding, rc);
    869718
    870719        switch (u32Enc)
  • trunk/src/VBox/NetworkServices/Dhcpd/Config.h

    r79621 r79761  
    4545
    4646    RTCString       m_strNetwork;       /**< The name of the internal network the DHCP server is connected to. */
    47     RTCString       m_strBaseName;      /**< m_strNetwork sanitized to be usable in a path component. */
    4847    RTCString       m_strLeasesFilename;/**< The lease DB filename. */
    4948
     
    7069     *        vendor class and user class, including simple lists of these. */
    7170
     71    /** Set if we've initialized the log already (via command line). */
     72    static bool     g_fInitializedLog;
     73
    7274private:
    7375    Config();
     
    7779    static Config      *i_createInstanceAndCallInit() RT_NOEXCEPT;
    7880    int                 i_logInit() RT_NOEXCEPT;
     81    static int          i_logInitWithFilename(const char *pszFilename) RT_NOEXCEPT;
    7982    int                 i_complete() RT_NOEXCEPT;
    8083
     
    9295
    9396    const RTCString    &getNetwork() const RT_NOEXCEPT          { return m_strNetwork; }
    94     const RTCString    &getBaseName() const RT_NOEXCEPT         { return m_strBaseName; }
    9597    const RTCString    &getLeasesFilename() const RT_NOEXCEPT   { return m_strLeasesFilename; }
    9698
     
    124126    static void         i_getMacAddressAttribute(const xml::ElementNode *pElm, const char *pszAttrName, PRTMAC pMacAddr);
    125127    /** @} */
    126 
    127     void                i_setNetwork(const RTCString &aStrNetwork);
    128     void                i_sanitizeBaseName();
    129128};
    130129
  • trunk/src/VBox/NetworkServices/Dhcpd/DhcpOptions.cpp

    r79524 r79761  
    1616 */
    1717
     18
     19/*********************************************************************************************************************************
     20*   Header Files                                                                                                                 *
     21*********************************************************************************************************************************/
    1822#include "DhcpdInternal.h"
    1923#include "DhcpOptions.h"
    2024#include "DhcpMessage.h"
     25
     26#include <iprt/cidr.h>
    2127
    2228
     
    102108
    103109
     110int DhcpOption::parse1(bool &aValue, const char *pcszValue)
     111{
     112    pcszValue = RTStrStripL(pcszValue);
     113    if (   strcmp(pcszValue, "true") == 0
     114        || strcmp(pcszValue, "1")    == 0
     115        || strcmp(pcszValue, "yes")  == 0
     116        || strcmp(pcszValue, "on")   == 0 )
     117    {
     118        aValue = true;
     119        return VINF_SUCCESS;
     120    }
     121
     122    if (   strcmp(pcszValue, "false") == 0
     123        || strcmp(pcszValue, "0")     == 0
     124        || strcmp(pcszValue, "no")    == 0
     125        || strcmp(pcszValue, "off")   == 0 )
     126    {
     127        aValue = false;
     128        return VINF_SUCCESS;
     129    }
     130
     131    uint8_t bTmp;
     132    int rc = RTStrToUInt8Full(RTStrStripL(pcszValue), 10, &bTmp);
     133    if (rc == VERR_TRAILING_SPACES)
     134        rc = VINF_SUCCESS;
     135    if (RT_SUCCESS(rc))
     136        aValue = bTmp != 0;
     137
     138    return rc;
     139}
     140
     141
    104142int DhcpOption::parse1(uint8_t &aValue, const char *pcszValue)
    105143{
    106144    int rc = RTStrToUInt8Full(RTStrStripL(pcszValue), 10, &aValue);
    107 
    108145    if (rc == VERR_TRAILING_SPACES)
    109146        rc = VINF_SUCCESS;
     
    138175
    139176
    140 int DhcpOption::parseList(std::vector<RTNETADDRIPV4> &aList, const char *pcszValue)
    141 {
    142     std::vector<RTNETADDRIPV4> l;
    143     int rc;
     177int DhcpOption::parse1(DhcpIpv4AddrAndMask &aValue, const char *pcszValue)
     178{
     179    return RTCidrStrToIPv4(pcszValue, &aValue.Ipv4, &aValue.Mask);
     180}
     181
     182
     183template <typename a_Type>
     184static int DhcpOption::parseList(std::vector<a_Type> &aList, const char *pcszValue)
     185{
     186    std::vector<a_Type> vecTmp;
    144187
    145188    pcszValue = RTStrStripL(pcszValue);
    146     do {
    147         RTNETADDRIPV4 Addr;
    148         char *pszNext;
    149 
    150         rc = RTNetStrToIPv4AddrEx(pcszValue, &Addr, &pszNext);
    151         if (RT_FAILURE(rc))
     189    for (;;)
     190    {
     191        /* Assume space, tab, comma or semicolon is used as separator (superset of RTStrStrip): */
     192        const char *pszNext = strpbrk(pcszValue, " ,;:\t\n\r");
     193        char szTmp[256];
     194        if (pszNext)
     195        {
     196            size_t cchToCopy = pszNext - pcszValue;
     197            if (cchToCopy >= sizeof(szTmp))
     198                return VERR_INVALID_PARAMETER;
     199            memcpy(szTmp, pcszValue, cchToCopy);
     200            szTmp[cchToCopy] = '\0';
     201            pcszValue = szTmp;
     202
     203            /* Advance pszNext past the separator character and fluff: */
     204            char ch;
     205            do
     206                pszNext++;
     207            while ((ch = *pszNext) == ' ' || ch == ':' || ch == ';' || ch == '\t' || ch == '\n' || ch == '\r');
     208            if (ch == '\0')
     209                pszNext = NULL;
     210        }
     211
     212        /* Try convert it: */
     213        a_Type Value;
     214        int rc = DhcpOption::parse1(Value, pcszValue);
     215        if (RT_SUCCESS(rc))
     216            vecTmp.push_back(Value);
     217        else
    152218            return VERR_INVALID_PARAMETER;
    153219
    154         if (rc == VWRN_TRAILING_CHARS)
     220        if (pszNext)
     221            pcszValue = pszNext;
     222        else
     223            break;
     224    }
     225
     226    aList.swap(vecTmp);
     227    return VINF_SUCCESS;
     228
     229}
     230
     231/** ASSUME that uint8_t means hex byte strings. */
     232template <>
     233static int DhcpOption::parseList(std::vector<uint8_t> &aList, const char *pcszValue)
     234{
     235    uint8_t     abBuf[256];
     236    const char *pszNext = NULL;
     237    size_t      cbReturned = 0;
     238    int rc = RTStrConvertHexBytesEx(RTStrStripL(pcszValue), abBuf, sizeof(abBuf), RTSTRCONVERTHEXBYTES_F_SEP_COLON,
     239                                    &pszNext, &cbReturned);
     240    if (RT_SUCCESS(rc))
     241    {
     242        if (pszNext)
     243            pszNext = RTStrStripL(pszNext);
     244        if (*pszNext)
    155245        {
    156             pcszValue = RTStrStripL(pszNext);
    157             if (pcszValue == pszNext) /* garbage after address */
    158                 return VERR_INVALID_PARAMETER;
     246            for (size_t i = 0; i < cbReturned; i++)
     247                aList.push_back(abBuf[i]);
     248            return VINF_SUCCESS;
    159249        }
    160 
    161         l.push_back(Addr);
    162 
    163         /*
    164          * If we got VINF_SUCCESS or VWRN_TRAILING_SPACES then this
    165          * was the last address and we are done.
    166          */
    167     } while (rc == VWRN_TRAILING_CHARS);
    168 
    169     aList.swap(l);
    170     return VINF_SUCCESS;
    171 }
     250        rc = VERR_TRAILING_CHARS;
     251    }
     252    return rc;
     253}
     254
    172255
    173256
     
    208291
    209292
    210 DhcpOption *DhcpOption::parse(uint8_t aOptCode, int aEnc, const char *pcszValue)
    211 {
     293DhcpOption *DhcpOption::parse(uint8_t aOptCode, int aEnc, const char *pcszValue, int *prc /*= NULL*/)
     294{
     295    int rcIgn;
     296    if (!prc)
     297        prc = &rcIgn;
     298
    212299    switch (aEnc)
    213300    {
    214     case 0: /* DhcpOptEncoding_Legacy */
    215         switch (aOptCode)
    216         {
    217 #define HANDLE(_OptClass)                               \
    218             case _OptClass::optcode:                    \
    219                 return _OptClass::parse(pcszValue);
    220 
    221         HANDLE(OptSubnetMask);
    222         HANDLE(OptRouter);
    223         HANDLE(OptDNS);
    224         HANDLE(OptHostName);
    225         HANDLE(OptDomainName);
    226         HANDLE(OptRootPath);
    227         HANDLE(OptLeaseTime);
    228         HANDLE(OptRenewalTime);
    229         HANDLE(OptRebindingTime);
     301        case 0: /* DhcpOptEncoding_Legacy */
     302            switch (aOptCode)
     303            {
     304#define HANDLE(a_OptClass)  \
     305                case a_OptClass::optcode: \
     306                    return a_OptClass::parse(pcszValue, prc)
     307
     308                HANDLE(OptSubnetMask);                  // 1
     309                HANDLE(OptTimeOffset);                  // 2
     310                HANDLE(OptRouters);                     // 3
     311                HANDLE(OptTimeServers);                 // 4
     312                HANDLE(OptNameServers);                 // 5
     313                HANDLE(OptDNSes);                       // 6
     314                HANDLE(OptLogServers);                  // 7
     315                HANDLE(OptCookieServers);               // 8
     316                HANDLE(OptLPRServers);                  // 9
     317                HANDLE(OptImpressServers);              // 10
     318                HANDLE(OptResourceLocationServers);     // 11
     319                HANDLE(OptHostName);                    // 12
     320                HANDLE(OptBootFileSize);                // 13
     321                HANDLE(OptMeritDumpFile);               // 14
     322                HANDLE(OptDomainName);                  // 15
     323                HANDLE(OptSwapServer);                  // 16
     324                HANDLE(OptRootPath);                    // 17
     325                HANDLE(OptExtensionPath);               // 18
     326                HANDLE(OptIPForwarding);                // 19
     327                HANDLE(OptNonLocalSourceRouting);       // 20
     328                HANDLE(OptPolicyFilter);                // 21
     329                HANDLE(OptMaxDatagramReassemblySize);   // 22
     330                HANDLE(OptDefaultIPTTL);                // 23
     331                HANDLE(OptDefaultPathMTUAgingTimeout);  // 24
     332                HANDLE(OptPathMTUPlateauTable);         // 25
     333                HANDLE(OptInterfaceMTU);                // 26
     334                HANDLE(OptAllSubnetsAreLocal);          // 27
     335                HANDLE(OptBroadcastAddress);            // 28
     336                HANDLE(OptPerformMaskDiscovery);        // 29
     337                HANDLE(OptMaskSupplier);                // 30
     338                HANDLE(OptPerformRouterDiscovery);      // 31
     339                HANDLE(OptRouterSolicitationAddress);   // 32
     340                HANDLE(OptStaticRoute);                 // 33
     341                HANDLE(OptTrailerEncapsulation);        // 34
     342                HANDLE(OptARPCacheTimeout);             // 35
     343                HANDLE(OptEthernetEncapsulation);       // 36
     344                HANDLE(OptTCPDefaultTTL);               // 37
     345                HANDLE(OptTCPKeepaliveInterval);        // 38
     346                HANDLE(OptTCPKeepaliveGarbage);         // 39
     347                HANDLE(OptNISDomain);                   // 40
     348                HANDLE(OptNISServers);                  // 41
     349                HANDLE(OptNTPServers);                  // 42
     350                HANDLE(OptVendorSpecificInfo);          // 43
     351                HANDLE(OptNetBIOSNameServers);          // 44
     352                HANDLE(OptNetBIOSDatagramServers);      // 45
     353                HANDLE(OptNetBIOSNodeType);             // 46
     354                HANDLE(OptNetBIOSScope);                // 47
     355                HANDLE(OptXWindowsFontServers);         // 48
     356                HANDLE(OptXWindowsDisplayManager);      // 49
     357#ifndef IN_VBOXSVC /* Don't allow these in new configs */
     358                // OptRequestedAddress (50) is client only and not configurable.
     359                HANDLE(OptLeaseTime);                   // 51 - for historical reasons?  Configuable elsewhere now.
     360                // OptOptionOverload (52) is part of the protocol and not configurable.
     361                // OptMessageType (53) is part of the protocol and not configurable.
     362                // OptServerId (54) is the IP address of the server and configurable elsewhere.
     363                // OptParameterRequest (55) is client only and not configurable.
     364                // OptMessage (56) is server failure message and not configurable.
     365                // OptMaxDHCPMessageSize (57) is client only (?) and not configurable.
     366                HANDLE(OptRenewalTime);                 // 58 - for historical reasons?
     367                HANDLE(OptRebindingTime);               // 59 - for historical reasons?
     368                // OptVendorClassId (60) is client only and not configurable.
     369                // OptClientId (61) is client only and not configurable.
     370#endif
     371                HANDLE(OptNetWareIPDomainName);         // 62
     372                HANDLE(OptNetWareIPInformation);        // 63
     373                HANDLE(OptNISPlusDomain);               // 64
     374                HANDLE(OptNISPlusServers);              // 65
     375                HANDLE(OptTFTPServer);                  // 66 - perhaps we should use an alternative way to configure these.
     376                HANDLE(OptBootFileName);                // 67 - perhaps we should use an alternative way to configure these.
     377                HANDLE(OptMobileIPHomeAgents);          // 68
     378                HANDLE(OptSMTPServers);                 // 69
     379                HANDLE(OptPOP3Servers);                 // 70
     380                HANDLE(OptNNTPServers);                 // 71
     381                HANDLE(OptWWWServers);                  // 72
     382                HANDLE(OptFingerServers);               // 73
     383                HANDLE(OptIRCServers);                  // 74
     384                HANDLE(OptStreetTalkServers);           // 75
     385                HANDLE(OptSTDAServers);                 // 76
     386                // OptUserClassId (77) is client only and not configurable.
     387                HANDLE(OptSLPDirectoryAgent);           // 78
     388                HANDLE(OptSLPServiceScope);             // 79
     389                // OptRapidCommit (80) is not configurable.
    230390
    231391#undef HANDLE
     392                default:
     393                    if (prc)
     394                        *prc = VERR_NOT_IMPLEMENTED;
     395                    return NULL;
     396            }
     397            break;
     398
     399        case 1:
     400            return RawOption::parse(aOptCode, pcszValue, prc);
     401
    232402        default:
     403            if (prc)
     404                *prc = VERR_WRONG_TYPE;
    233405            return NULL;
    234         }
    235         break;
    236 
    237     case 1:
    238         return RawOption::parse(aOptCode, pcszValue);
    239 
    240     default:
    241         return NULL;
    242     }
    243 }
     406    }
     407}
  • trunk/src/VBox/NetworkServices/Dhcpd/DhcpOptions.h

    r79563 r79761  
    3333class DhcpClientMessage;
    3434
     35typedef struct DhcpIpv4AddrAndMask
     36{
     37    RTNETADDRIPV4   Ipv4;
     38    RTNETADDRIPV4   Mask;
     39} DhcpIpv4AddrAndMask;
     40
    3541
    3642class DhcpOption
    3743{
    38   protected:
     44protected:
    3945    uint8_t m_OptCode;
    40     bool m_fPresent;
    41 
    42   public:
     46    bool    m_fPresent;
     47
     48public:
    4349    explicit DhcpOption(uint8_t aOptCode)
    44       : m_OptCode(aOptCode), m_fPresent(true) {}
     50        : m_OptCode(aOptCode), m_fPresent(true)
     51    {}
    4552
    4653    DhcpOption(uint8_t aOptCode, bool fPresent)
    47       : m_OptCode(aOptCode), m_fPresent(fPresent) {}
     54        : m_OptCode(aOptCode), m_fPresent(fPresent)
     55    {}
    4856
    4957    virtual DhcpOption *clone() const = 0;
    5058
    51     virtual ~DhcpOption() {}
    52 
    53   public:
    54     static DhcpOption *parse(uint8_t aOptCode, int aEnc, const char *pcszValue);
    55 
    56   public:
     59    virtual ~DhcpOption()
     60    {}
     61
     62public:
     63    static DhcpOption *parse(uint8_t aOptCode, int aEnc, const char *pcszValue, int *prc = NULL);
     64
     65public:
    5766    uint8_t optcode() const RT_NOEXCEPT { return m_OptCode; }
    5867    bool    present() const RT_NOEXCEPT { return m_fPresent; }
    5968
    60   public:
     69public:
    6170    int encode(octets_t &dst) const;
    6271
     
    6473    int decode(const DhcpClientMessage &req);
    6574
    66   protected:
     75protected:
    6776    virtual ssize_t encodeValue(octets_t &dst) const = 0;
    6877    virtual int decodeValue(const octets_t &src, size_t cb) = 0;
    6978
    70   protected:
     79protected:
    7180    static const octets_t *findOption(const rawopts_t &aOptMap, uint8_t aOptCode);
    7281
    73   protected:
    74     /*
    75      * Serialization
    76      */
     82protected:
     83    /** @name Serialization
     84     * @{ */
     85    static void append(octets_t &aDst, bool aValue)
     86    {
     87        uint8_t b = aValue ? 1 : 0;
     88        aDst.push_back(b);
     89    }
     90
    7791    static void append(octets_t &aDst, uint8_t aValue)
    7892    {
     
    97111    }
    98112
     113    static void append(octets_t &aDst, DhcpIpv4AddrAndMask aIPv4)
     114    {
     115        aDst.insert(aDst.end(), (uint8_t *)&aIPv4, (uint8_t *)&aIPv4 + sizeof(aIPv4));
     116    }
     117
    99118    static void append(octets_t &aDst, const char *pszString, size_t cb)
    100119    {
     
    113132    }
    114133
    115 
    116     /*
    117      * Deserialization
    118      */
     134    /** @} */
     135
     136
     137    /** @name Deserialization
     138     * @{  */
     139    static void extract(bool &aValue, octets_t::const_iterator &pos)
     140    {
     141        aValue = *pos != 0;
     142        pos += sizeof(uint8_t);
     143    }
     144
    119145    static void extract(uint8_t &aValue, octets_t::const_iterator &pos)
    120146    {
     
    145171    }
    146172
     173    static void extract(DhcpIpv4AddrAndMask &aValue, octets_t::const_iterator &pos)
     174    {
     175        memcpy(&aValue, &pos[0], sizeof(aValue));
     176        pos += sizeof(aValue);
     177    }
     178
    147179#if 0 /** @todo fix me */
    148180    static void extract(RTCString &aString, octets_t::const_iterator &pos, size_t cb)
     
    153185#endif
    154186
    155 
    156     /*
    157      * Parse textual representation (e.g. in config file)
    158      */
     187    /** @} */
     188
     189    /** @name Parse textual representation (e.g. in config file)
     190     * @{  */
     191    static int parse1(bool &aValue, const char *pcszValue);
    159192    static int parse1(uint8_t &aValue, const char *pcszValue);
    160193    static int parse1(uint16_t &aValue, const char *pcszValue);
    161194    static int parse1(uint32_t &aValue, const char *pcszValue);
    162195    static int parse1(RTNETADDRIPV4 &aValue, const char *pcszValue);
    163 
    164     static int parseList(std::vector<RTNETADDRIPV4> &aList, const char *pcszValue);
     196    static int parse1(DhcpIpv4AddrAndMask &aValue, const char *pcszValue);
     197
     198    template <typename a_Type> static int parseList(std::vector<a_Type> &aList, const char *pcszValue);
    165199
    166200    static int parseHex(octets_t &aRawValue, const char *pcszValue);
     201
     202    /** @} */
    167203};
    168204
     
    180216
    181217
    182 /*
     218/**
    183219 * Only for << OptEnd() syntactic sugar...
    184220 */
     
    194230
    195231
    196 /*
     232/**
    197233 * Option that has no value
    198234 */
    199235class OptNoValueBase
    200   : public DhcpOption
    201 {
    202   public:
     236    : public DhcpOption
     237{
     238public:
    203239    explicit OptNoValueBase(uint8_t aOptCode)
    204       : DhcpOption(aOptCode, false) {}
     240        : DhcpOption(aOptCode, false)
     241    {}
    205242
    206243    OptNoValueBase(uint8_t aOptCode, bool fPresent)
    207       : DhcpOption(aOptCode, fPresent) {}
     244        : DhcpOption(aOptCode, fPresent)
     245    {}
    208246
    209247    OptNoValueBase(uint8_t aOptCode, const DhcpClientMessage &req)
    210       : DhcpOption(aOptCode, false)
     248        : DhcpOption(aOptCode, false)
    211249    {
    212250        decode(req);
     
    218256    }
    219257
    220   protected:
     258protected:
    221259    virtual ssize_t encodeValue(octets_t &dst) const
    222260    {
     
    225263    }
    226264
    227   public:
     265public:
    228266    static bool isLengthValid(size_t cb)
    229267    {
     
    245283template <uint8_t _OptCode>
    246284class OptNoValue
    247   : public OptNoValueBase
    248 {
    249   public:
     285    : public OptNoValueBase
     286{
     287public:
    250288    static const uint8_t optcode = _OptCode;
    251289
    252290    OptNoValue()
    253       : OptNoValueBase(optcode) {}
     291        : OptNoValueBase(optcode)
     292    {}
    254293
    255294    explicit OptNoValue(bool fPresent) /* there's no overloaded ctor with value */
    256       : OptNoValueBase(optcode, fPresent) {}
     295        : OptNoValueBase(optcode, fPresent)
     296    {}
    257297
    258298    explicit OptNoValue(const DhcpClientMessage &req)
    259       : OptNoValueBase(optcode, req) {}
     299        : OptNoValueBase(optcode, req)
     300    {}
    260301};
    261302
     
    267308template <typename T>
    268309class OptValueBase
    269   : public DhcpOption
    270 {
    271   public:
     310    : public DhcpOption
     311{
     312public:
    272313    typedef T value_t;
    273314
    274   protected:
     315protected:
    275316    T m_Value;
    276317
    277318    explicit OptValueBase(uint8_t aOptCode)
    278       : DhcpOption(aOptCode, false), m_Value() {}
     319        : DhcpOption(aOptCode, false), m_Value()
     320    {}
    279321
    280322    OptValueBase(uint8_t aOptCode, const T &aOptValue)
    281       : DhcpOption(aOptCode), m_Value(aOptValue) {}
     323        : DhcpOption(aOptCode), m_Value(aOptValue)
     324    {}
    282325
    283326    OptValueBase(uint8_t aOptCode, const DhcpClientMessage &req)
    284       : DhcpOption(aOptCode, false), m_Value()
     327        : DhcpOption(aOptCode, false), m_Value()
    285328    {
    286329        decode(req);
    287330    }
    288331
    289   public:
     332public:
    290333    virtual OptValueBase *clone() const
    291334    {
     
    293336    }
    294337
    295   public:
    296     T &value() { return m_Value; }
    297     const T &value() const { return m_Value; }
    298 
    299   protected:
     338public:
     339    T &value()              { return m_Value; }
     340    const T &value() const  { return m_Value; }
     341
     342protected:
    300343    virtual ssize_t encodeValue(octets_t &dst) const
    301344    {
     
    304347    }
    305348
    306   public:
     349public:
    307350    static bool isLengthValid(size_t cb)
    308351    {
     
    325368template<uint8_t _OptCode, typename T>
    326369class OptValue
    327   : public OptValueBase<T>
    328 {
    329   public:
     370    : public OptValueBase<T>
     371{
     372public:
    330373    using typename OptValueBase<T>::value_t;
    331374
    332   public:
     375public:
    333376    static const uint8_t optcode = _OptCode;
    334377
    335378    OptValue()
    336       : OptValueBase<T>(optcode) {}
     379        : OptValueBase<T>(optcode)
     380    {}
    337381
    338382    explicit OptValue(const T &aOptValue)
    339       : OptValueBase<T>(optcode, aOptValue) {}
     383        : OptValueBase<T>(optcode, aOptValue)
     384    {}
    340385
    341386    explicit OptValue(const DhcpClientMessage &req)
    342       : OptValueBase<T>(optcode, req) {}
    343 
    344     static OptValue *parse(const char *pcszValue)
     387        : OptValueBase<T>(optcode, req)
     388    {}
     389
     390    static OptValue *parse(const char *pcszValue, int *prc)
    345391    {
    346392        typename OptValueBase<T>::value_t v;
    347393        int rc = DhcpOption::parse1(v, pcszValue);
    348         if (RT_FAILURE(rc))
    349             return NULL;
    350         return new OptValue(v);
    351     }
    352 };
    353 
    354 
    355 
    356 /*
     394        *prc = rc;
     395        if (RT_SUCCESS(rc))
     396            return new OptValue(v);
     397        return NULL;
     398    }
     399};
     400
     401
     402
     403/**
    357404 * Option that contains a string.
    358405 */
    359406class OptStringBase
    360   : public DhcpOption
    361 {
    362   public:
     407    : public DhcpOption
     408{
     409public:
    363410    typedef RTCString value_t;
    364411
    365   protected:
     412protected:
    366413    RTCString m_String;
    367414
    368415    explicit OptStringBase(uint8_t aOptCode)
    369       : DhcpOption(aOptCode, false), m_String() {}
     416        : DhcpOption(aOptCode, false), m_String()
     417    {}
    370418
    371419    OptStringBase(uint8_t aOptCode, const RTCString &aOptString)
    372       : DhcpOption(aOptCode), m_String(aOptString) {}
     420        : DhcpOption(aOptCode), m_String(aOptString)
     421    {}
    373422
    374423    OptStringBase(uint8_t aOptCode, const DhcpClientMessage &req)
    375       : DhcpOption(aOptCode, false), m_String()
     424        : DhcpOption(aOptCode, false), m_String()
    376425    {
    377426        decode(req);
    378427    }
    379428
    380   public:
     429public:
    381430    virtual OptStringBase *clone() const
    382431    {
     
    384433    }
    385434
    386   public:
    387     RTCString &value() { return m_String; }
    388     const RTCString &value() const { return m_String; }
    389 
    390   protected:
     435public:
     436    RTCString &value()              { return m_String; }
     437    const RTCString &value() const  { return m_String; }
     438
     439protected:
    391440    virtual ssize_t encodeValue(octets_t &dst) const
    392441    {
     
    398447    }
    399448
    400   public:
     449public:
    401450    static bool isLengthValid(size_t cb)
    402451    {
     
    417466template<uint8_t _OptCode>
    418467class OptString
    419   : public OptStringBase
    420 {
    421   public:
     468    : public OptStringBase
     469{
     470public:
    422471    static const uint8_t optcode = _OptCode;
    423472
    424473    OptString()
    425       : OptStringBase(optcode) {}
     474        : OptStringBase(optcode)
     475    {}
    426476
    427477    explicit OptString(const RTCString &aOptString)
    428       : OptStringBase(optcode, aOptString) {}
     478        : OptStringBase(optcode, aOptString)
     479    {}
    429480
    430481    explicit OptString(const DhcpClientMessage &req)
    431       : OptStringBase(optcode, req) {}
    432 
    433     static OptString *parse(const char *pcszValue)
    434     {
     482        : OptStringBase(optcode, req)
     483    {}
     484
     485    static OptString *parse(const char *pcszValue, int *prc)
     486    {
     487        *prc = VINF_SUCCESS;
    435488        return new OptString(pcszValue);
    436489    }
     
    444497template <typename T>
    445498class OptListBase
    446   : public DhcpOption
    447 {
    448   public:
     499    : public DhcpOption
     500{
     501public:
    449502    typedef std::vector<T> value_t;
    450503
    451   protected:
     504protected:
    452505    std::vector<T> m_List;
    453506
    454507    explicit OptListBase(uint8_t aOptCode)
    455       : DhcpOption(aOptCode, false), m_List() {}
     508        : DhcpOption(aOptCode, false), m_List()
     509    {}
    456510
    457511    OptListBase(uint8_t aOptCode, const T &aOptSingle)
    458       : DhcpOption(aOptCode), m_List(1, aOptSingle) {}
     512        : DhcpOption(aOptCode), m_List(1, aOptSingle)
     513    {}
    459514
    460515    OptListBase(uint8_t aOptCode, const std::vector<T> &aOptList)
    461       : DhcpOption(aOptCode), m_List(aOptList) {}
     516        : DhcpOption(aOptCode), m_List(aOptList)
     517    {}
    462518
    463519    OptListBase(uint8_t aOptCode, const DhcpClientMessage &req)
    464       : DhcpOption(aOptCode, false), m_List()
     520        : DhcpOption(aOptCode, false), m_List()
    465521    {
    466522        decode(req);
    467523    }
    468524
    469   public:
     525public:
    470526    virtual OptListBase *clone() const
    471527    {
     
    473529    }
    474530
    475   public:
    476     std::vector<T> &value() { return m_List; }
     531public:
     532    std::vector<T> &value()             { return m_List; }
    477533    const std::vector<T> &value() const { return m_List; }
    478534
    479   protected:
     535protected:
    480536    virtual ssize_t encodeValue(octets_t &dst) const
    481537    {
     
    495551    }
    496552
    497   public:
     553public:
    498554    static bool isLengthValid(size_t cb)
    499555    {
     
    522578template<uint8_t _OptCode, typename T>
    523579class OptList
    524   : public OptListBase<T>
    525 
    526 {
    527   public:
     580    : public OptListBase<T>
     581
     582{
     583public:
    528584    using typename OptListBase<T>::value_t;
    529585
    530   public:
     586public:
    531587    static const uint8_t optcode = _OptCode;
    532588
    533589    OptList()
    534       : OptListBase<T>(optcode) {}
     590        : OptListBase<T>(optcode)
     591    {}
    535592
    536593    explicit OptList(const T &aOptSingle)
    537       : OptListBase<T>(optcode, aOptSingle) {}
     594        : OptListBase<T>(optcode, aOptSingle)
     595    {}
    538596
    539597    explicit OptList(const std::vector<T> &aOptList)
    540       : OptListBase<T>(optcode, aOptList) {}
     598        : OptListBase<T>(optcode, aOptList)
     599    {}
    541600
    542601    explicit OptList(const DhcpClientMessage &req)
    543       : OptListBase<T>(optcode, req) {}
    544 
    545     static OptList *parse(const char *pcszValue)
     602        : OptListBase<T>(optcode, req)
     603    {}
     604
     605    static OptList *parse(const char *pcszValue, int *prc)
    546606    {
    547607        typename OptListBase<T>::value_t v;
    548         int rc = DhcpOption::parseList(v, pcszValue);
    549         if (RT_FAILURE(rc) || v.empty())
    550             return NULL;
    551         return new OptList(v);
     608        int rc = DhcpOption::parseList<T>(v, pcszValue);
     609        if (RT_SUCCESS(rc))
     610        {
     611            if (!v.empty())
     612            {
     613                *prc = rc;
     614                return new OptList(v);
     615            }
     616            rc = VERR_NO_DATA;
     617        }
     618        *prc = rc;
     619        return NULL;
     620    }
     621};
     622
     623
     624template<uint8_t _OptCode, typename T>
     625class OptPairList
     626    : public OptListBase<T>
     627
     628{
     629public:
     630    using typename OptListBase<T>::value_t;
     631
     632public:
     633    static const uint8_t optcode = _OptCode;
     634
     635    OptPairList()
     636        : OptListBase<T>(optcode)
     637    {}
     638
     639    explicit OptPairList(const T &aOptSingle)
     640        : OptListBase<T>(optcode, aOptSingle)
     641    {}
     642
     643    explicit OptPairList(const std::vector<T> &aOptList)
     644        : OptListBase<T>(optcode, aOptList)
     645    {}
     646
     647    explicit OptPairList(const DhcpClientMessage &req)
     648        : OptListBase<T>(optcode, req)
     649    {}
     650
     651    static OptPairList *parse(const char *pcszValue, int *prc)
     652    {
     653        typename OptListBase<T>::value_t v;
     654        int rc = DhcpOption::parseList<T>(v, pcszValue);
     655        if (RT_SUCCESS(rc))
     656        {
     657            if (!v.empty())
     658            {
     659                if ((v.size() & 1) == 0)
     660                {
     661                    *prc = rc;
     662                    return new OptPairList(v);
     663                }
     664                rc = VERR_UNEVEN_INPUT;
     665            }
     666            else
     667                rc = VERR_NO_DATA;
     668        }
     669        *prc = rc;
     670        return NULL;
    552671    }
    553672};
     
    559678 */
    560679class RawOption
    561   : public DhcpOption
    562 {
    563   protected:
     680    : public DhcpOption
     681{
     682protected:
    564683    octets_t m_Data;
    565684
    566   public:
     685public:
    567686    explicit RawOption(uint8_t aOptCode)
    568       : DhcpOption(aOptCode, false), m_Data() {}
     687        : DhcpOption(aOptCode, false), m_Data()
     688    {}
    569689
    570690    RawOption(uint8_t aOptCode, const octets_t &aSrc)
    571       : DhcpOption(aOptCode), m_Data(aSrc) {}
    572 
    573   public:
     691        : DhcpOption(aOptCode), m_Data(aSrc)
     692    {}
     693
     694public:
    574695    virtual RawOption *clone() const
    575696    {
     
    578699
    579700
    580   protected:
     701protected:
    581702    virtual ssize_t encodeValue(octets_t &dst) const
    582703    {
     
    595716    }
    596717
    597   public:
    598     static RawOption *parse(uint8_t aOptCode, const char *pcszValue)
     718public:
     719    static RawOption *parse(uint8_t aOptCode, const char *pcszValue, int *prc)
    599720    {
    600721        octets_t data;
    601722        int rc = DhcpOption::parseHex(data, pcszValue);
    602         if (RT_FAILURE(rc))
    603             return NULL;
    604         return new RawOption(aOptCode, data);
     723        *prc = rc;
     724        if (RT_SUCCESS(rc))
     725            return new RawOption(aOptCode, data);
     726        return NULL;
    605727    }
    606728};
     
    613735typedef OptValue<1, RTNETADDRIPV4>      OptSubnetMask;
    614736typedef OptValue<2, uint32_t>           OptTimeOffset;
    615 typedef OptList<3, RTNETADDRIPV4>       OptRouter;
    616 typedef OptList<4, RTNETADDRIPV4>       OptTimeServer;
    617 typedef OptList<6, RTNETADDRIPV4>       OptDNS;
     737typedef OptList<3, RTNETADDRIPV4>       OptRouters;
     738typedef OptList<4, RTNETADDRIPV4>       OptTimeServers;
     739typedef OptList<5, RTNETADDRIPV4>       OptNameServers;
     740typedef OptList<6, RTNETADDRIPV4>       OptDNSes;
     741typedef OptList<7, RTNETADDRIPV4>       OptLogServers;
     742typedef OptList<8, RTNETADDRIPV4>       OptCookieServers;
     743typedef OptList<9, RTNETADDRIPV4>       OptLPRServers;
     744typedef OptList<10, RTNETADDRIPV4>      OptImpressServers;
     745typedef OptList<11, RTNETADDRIPV4>      OptResourceLocationServers;
    618746typedef OptString<12>                   OptHostName;
     747typedef OptValue<13, uint16_t>          OptBootFileSize;
     748typedef OptString<14>                   OptMeritDumpFile;
    619749typedef OptString<15>                   OptDomainName;
     750typedef OptValue<16, RTNETADDRIPV4>     OptSwapServer;
    620751typedef OptString<17>                   OptRootPath;
    621 
    622 /* DHCP related options */
     752typedef OptString<18>                   OptExtensionPath;
     753typedef OptValue<19, bool>              OptIPForwarding;
     754typedef OptValue<20, bool>              OptNonLocalSourceRouting;
     755typedef OptList<21, DhcpIpv4AddrAndMask> OptPolicyFilter;
     756typedef OptValue<22, uint16_t>          OptMaxDatagramReassemblySize;
     757typedef OptValue<23, uint16_t>          OptDefaultIPTTL;
     758typedef OptValue<24, uint32_t>          OptDefaultPathMTUAgingTimeout;
     759typedef OptList<25, uint16_t>           OptPathMTUPlateauTable;
     760typedef OptValue<26, uint16_t>          OptInterfaceMTU;
     761typedef OptValue<27, bool>              OptAllSubnetsAreLocal;
     762typedef OptValue<28, RTNETADDRIPV4>     OptBroadcastAddress;
     763typedef OptValue<29, bool>              OptPerformMaskDiscovery;
     764typedef OptValue<30, bool>              OptMaskSupplier;
     765typedef OptValue<31, bool>              OptPerformRouterDiscovery;
     766typedef OptValue<32, RTNETADDRIPV4>     OptRouterSolicitationAddress;
     767typedef OptPairList<33, RTNETADDRIPV4>  OptStaticRoute;
     768typedef OptValue<34, bool>              OptTrailerEncapsulation;
     769typedef OptValue<35, uint32_t>          OptARPCacheTimeout;
     770typedef OptValue<36, bool>              OptEthernetEncapsulation;
     771typedef OptValue<37, uint8_t>           OptTCPDefaultTTL;
     772typedef OptValue<38, uint32_t>          OptTCPKeepaliveInterval;
     773typedef OptValue<39, bool>              OptTCPKeepaliveGarbage;
     774typedef OptString<40>                   OptNISDomain;
     775typedef OptList<41, RTNETADDRIPV4>      OptNISServers;
     776typedef OptList<42, RTNETADDRIPV4>      OptNTPServers;
     777/* DHCP related options: */
    623778typedef OptList<43, uint8_t>            OptVendorSpecificInfo;
     779typedef OptList<44, RTNETADDRIPV4>      OptNetBIOSNameServers;
     780typedef OptList<45, RTNETADDRIPV4>      OptNetBIOSDatagramServers;
     781typedef OptValue<46, uint8_t>           OptNetBIOSNodeType;
     782typedef OptList<47, uint8_t>            OptNetBIOSScope;            /**< uint8_t or string? */
     783typedef OptList<48, RTNETADDRIPV4>      OptXWindowsFontServers;
     784typedef OptList<49, RTNETADDRIPV4>      OptXWindowsDisplayManager;
    624785typedef OptValue<50, RTNETADDRIPV4>     OptRequestedAddress;
    625786typedef OptValue<51, uint32_t>          OptLeaseTime;
     
    634795typedef OptList<60, uint8_t>            OptVendorClassId;
    635796typedef OptList<61, uint8_t>            OptClientId;
    636 typedef OptString<66>                   OptTFTPServer;   /* when overloaded */
    637 typedef OptString<67>                   OptBootFileName; /* when overloaded */
     797typedef OptString<62>                   OptNetWareIPDomainName;     /**< RFC2242 */
     798typedef OptList<63, uint8_t>            OptNetWareIPInformation;    /**< complicated, so just byte list for now. RFC2242 */
     799typedef OptString<64>                   OptNISPlusDomain;
     800typedef OptString<65>                   OptNISPlusServers;
     801typedef OptString<66>                   OptTFTPServer;              /**< when overloaded */
     802typedef OptString<67>                   OptBootFileName;            /**< when overloaded */
     803typedef OptList<68, RTNETADDRIPV4>      OptMobileIPHomeAgents;
     804typedef OptList<69, RTNETADDRIPV4>      OptSMTPServers;
     805typedef OptList<70, RTNETADDRIPV4>      OptPOP3Servers;
     806typedef OptList<71, RTNETADDRIPV4>      OptNNTPServers;
     807typedef OptList<72, RTNETADDRIPV4>      OptWWWServers;
     808typedef OptList<73, RTNETADDRIPV4>      OptFingerServers;
     809typedef OptList<74, RTNETADDRIPV4>      OptIRCServers;
     810typedef OptList<75, RTNETADDRIPV4>      OptStreetTalkServers;
     811typedef OptList<76, RTNETADDRIPV4>      OptSTDAServers;
    638812typedef OptList<77, uint8_t>            OptUserClassId;
    639 typedef OptNoValue<80>                  OptRapidCommit;  /* RFC4039 */
     813typedef OptList<78, uint8_t>            OptSLPDirectoryAgent;       /**< complicated, so just byte list for now. RFC2610 */
     814typedef OptList<79, uint8_t>            OptSLPServiceScope;         /**< complicated, so just byte list for now. RFC2610 */
     815typedef OptNoValue<80>                  OptRapidCommit;             /**< RFC4039 */
    640816/** @} */
    641817
  • trunk/src/VBox/NetworkServices/Dhcpd/DhcpdInternal.h

    r79622 r79761  
    2222#endif
    2323
    24 #define LOG_GROUP LOG_GROUP_NET_DHCPD
     24#ifndef IN_VBOXSVC
     25# define LOG_GROUP LOG_GROUP_NET_DHCPD
     26#elif !defined(LOG_GROUP)
     27# define LOG_GROUP LOG_GROUP_MAIN_DHCPCONFIG
     28#endif
    2529#include <iprt/stdint.h>
    2630#include <iprt/string.h>
  • trunk/src/VBox/NetworkServices/Dhcpd/VBoxNetDhcpd.cpp

    r79622 r79761  
    620620     * Parse the command line into a configuration object.
    621621     */
    622     /** @todo XXX: We no longer need hardcoded and compat methods. We should remove them soon. */
    623     if (argc < 2)
    624         m_Config = Config::hardcoded();
    625     else if (   strcmp(argv[1], "--config") == 0
    626              || strcmp(argv[1], "--comment") == 0)
    627         m_Config = Config::create(argc, argv);
    628     else
    629     {
    630         try
    631         {
    632             m_Config = Config::compat(argc, argv);
    633         }
    634         catch (std::bad_alloc &)
    635         {
    636             m_Config = NULL;
    637             RTMsgError("Out of memory");
    638             return VERR_NO_MEMORY;
    639         }
    640     }
     622    m_Config = Config::create(argc, argv);
    641623    if (m_Config == NULL)
    642624        return VERR_GENERAL_FAILURE;
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