Changeset 79761 in vbox for trunk/src/VBox
- Timestamp:
- Jul 14, 2019 3:18:41 AM (5 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp
r79620 r79761 230 230 { "--vm", 'M', RTGETOPT_REQ_STRING }, 231 231 { "--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 }, 234 234 { "--id", 'i', RTGETOPT_REQ_UINT8 }, // obsolete, backwards compatibility only. 235 235 { "--value", 'p', RTGETOPT_REQ_STRING }, // obsolete, backwards compatibility only. … … 497 497 { 498 498 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()), 500 500 rcExit = RTEXITCODE_FAILURE); 501 501 } -
trunk/src/VBox/Main/Makefile.kmk
r79732 r79761 444 444 ## VBoxC, you shall obviously put them in VBOX_MAIN_DEFS! So, one way or the other they they disappear from here... 445 445 VBoxSVC_DEFS = \ 446 IN_VBOXSVC \ 446 447 VBOX_MAIN_SETTINGS_ADDONS \ 447 448 IN_VMM_STATIC \ … … 551 552 src-server/DHCPServerImpl.cpp \ 552 553 src-server/DHCPConfigImpl.cpp \ 554 ../NetworkServices/Dhcpd/DhcpOptions.cpp \ 553 555 src-server/NetworkServiceRunner.cpp \ 554 556 src-server/NATNetworkImpl.cpp \ -
trunk/src/VBox/Main/include/DHCPServerImpl.h
r79732 r79761 113 113 * @{ */ 114 114 HRESULT i_doSaveSettings(); 115 HRESULT i_calcLeases Filename(const com::Utf8Str &aNetwork) RT_NOEXCEPT;115 HRESULT i_calcLeasesConfigAndLogFilenames(const com::Utf8Str &aNetwork) RT_NOEXCEPT; 116 116 HRESULT i_writeDhcpdConfig(const char *pszFilename, uint32_t uMACAddressVersion) RT_NOEXCEPT; 117 117 -
trunk/src/VBox/Main/include/NetworkServiceRunner.h
r79644 r79761 53 53 int start(bool aKillProcessOnStop); 54 54 int stop(); 55 void detachFromServer(); 55 56 bool isRunning(); 56 void detachFromServer(); 57 58 RTPROCESS getPid() const; 57 59 58 60 /** @name Common options -
trunk/src/VBox/Main/src-server/DHCPConfigImpl.cpp
r79747 r79761 36 36 #include "VirtualBoxImpl.h" 37 37 38 #include "../../NetworkServices/Dhcpd/DhcpOptions.h" 39 38 40 39 41 … … 159 161 HRESULT DHCPConfig::i_setOption(DhcpOpt_T aOption, DHCPOptionEncoding_T aEncoding, const com::Utf8Str &aValue) 160 162 { 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 */ 165 185 { 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 } 167 195 } 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); 175 208 } 176 209 -
trunk/src/VBox/Main/src-server/DHCPServerImpl.cpp
r79749 r79761 65 65 virtual ~DHCPServerRunner() 66 66 {} 67 68 static const char * const kDsrKeyConfig;69 static const char * const kDsrKeyComment;70 67 }; 71 72 /*static*/ const char * const DHCPServerRunner::kDsrKeyConfig = "--config";73 /*static*/ const char * const DHCPServerRunner::kDsrKeyComment = "--comment";74 68 75 69 … … 85 79 , uIndividualMACAddressVersion(1) 86 80 { 87 szTempConfigFileName[0] = '\0';88 81 } 89 82 … … 101 94 DHCPServerRunner dhcp; 102 95 103 char szTempConfigFileName[RTPATH_MAX];104 96 com::Utf8Str strLeasesFilename; 97 com::Utf8Str strConfigFilename; 98 com::Utf8Str strLogFilename; 99 105 100 com::Utf8Str networkName; 106 101 com::Utf8Str trunkName; … … 1079 1074 if (m->dhcp.isRunning()) 1080 1075 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()); 1082 1077 1083 1078 /* … … 1087 1082 m->trunkName = aTrunkName; 1088 1083 m->trunkType = aTrunkType; 1089 HRESULT hrc = i_calcLeases Filename(aNetworkName);1084 HRESULT hrc = i_calcLeasesConfigAndLogFilenames(aNetworkName); 1090 1085 if (SUCCEEDED(hrc)) 1091 1086 { … … 1093 1088 * Create configuration file path and write out the configuration. 1094 1089 */ 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)) 1105 1106 { 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*/); 1115 1109 if (RT_FAILURE(vrc)) 1116 1110 hrc = setErrorVrc(vrc, tr("Failed to start DHCP server for '%s': %Rrc"), m->strName.c_str(), vrc); 1117 1111 } 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); 1128 1115 } 1129 1116 } … … 1135 1122 { 1136 1123 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1137 1138 if (m->szTempConfigFileName[0])1139 {1140 RTFileDelete(m->szTempConfigFileName);1141 m->szTempConfigFileName[0] = '\0';1142 }1143 1124 1144 1125 int vrc = m->dhcp.stop(); … … 1174 1155 if (m->strLeasesFilename.isEmpty()) 1175 1156 { 1176 HRESULT hrc = i_calcLeases Filename(m->networkName.isEmpty() ? m->strName : m->networkName);1157 HRESULT hrc = i_calcLeasesConfigAndLogFilenames(m->networkName.isEmpty() ? m->strName : m->networkName); 1177 1158 if (FAILED(hrc)) 1178 1159 return hrc; … … 1424 1405 * Calculates and updates the value of strLeasesFilename given @a aNetwork. 1425 1406 */ 1426 HRESULT DHCPServer::i_calcLeases Filename(const com::Utf8Str &aNetwork) RT_NOEXCEPT1407 HRESULT DHCPServer::i_calcLeasesConfigAndLogFilenames(const com::Utf8Str &aNetwork) RT_NOEXCEPT 1427 1408 { 1428 1409 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); … … 1433 1414 vrc = RTPathAppendCxx(m->strLeasesFilename, aNetwork); 1434 1415 if (RT_SUCCESS(vrc)) 1435 vrc = m->strLeasesFilename.appendNoThrow("-Dhcpd.leases");1436 if (RT_SUCCESS(vrc))1437 1416 { 1438 1417 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 286 286 return false; 287 287 } 288 289 290 /** 291 * Gets the process ID of a running service, NIL_PROCESS if not running. 292 */ 293 RTPROCESS NetworkServiceRunner::getPid() const 294 { 295 return m->Process; 296 } 297 -
trunk/src/VBox/NetworkServices/Dhcpd/Config.cpp
r79622 r79761 36 36 37 37 38 /********************************************************************************************************************************* 39 * Global Variables * 40 *********************************************************************************************************************************/ 41 /*static*/ bool Config::g_fInitializedLog = false; 42 43 38 44 /** 39 45 * Configuration file exception. … … 70 76 : m_strHome() 71 77 , m_strNetwork() 72 , m_strBaseName()73 78 , m_strTrunk() 74 79 , m_enmTrunkType(kIntNetTrunkType_Invalid) … … 140 145 141 146 /** 142 * Internal network name (m_strNetwork) setter.143 *144 * Can only be called once. Will also invoke i_sanitizeBaseName to update145 * m_strBaseName.146 *147 * @throws std::bad_alloc148 */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 the160 * version of m_strNetwork suitable for use as a path component.161 *162 * @throws std::bad_alloc163 */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 else173 m_strBaseName.setNull();174 }175 176 177 /**178 147 * Worker for i_complete() that initializes the release log of the process. 179 148 * … … 182 151 * command line? 183 152 * 184 * @ todo make the log file directly configurable?153 * @note This is only used when no --log parameter was given. 185 154 */ 186 155 int Config::i_logInit() RT_NOEXCEPT 187 156 { 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()) 189 161 return VERR_PATH_ZERO_LENGTH; 190 162 … … 193 165 ssize_t cch = RTStrPrintf2(szLogFile, sizeof(szLogFile), 194 166 "%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); 207 186 208 187 int rc = com::VBoxLogRelCreate("DHCP Server", 209 szLogFile,188 pszFilename, 210 189 RTLOGFLAGS_PREFIX_TIME_PROG, 211 "all all.restrict -default.restrict",212 szEnvVarBase,190 "all net_dhcpd.e.l", 191 "VBOXDHCP_RELEASE_LOG", 213 192 RTLOGDEST_FILE 214 193 #ifdef DEBUG … … 217 196 , 218 197 32768 /* cMaxEntriesPerGroup */, 219 0/* cHistory */,220 0/* uHistoryFileTime */,221 0/* uHistoryFileSize */,198 5 /* cHistory */, 199 RT_SEC_1DAY /* uHistoryFileTime */, 200 _32M /* uHistoryFileSize */, 222 201 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); 224 206 return rc; 207 225 208 } 226 209 … … 324 307 325 308 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 */ 316 Config *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); 362 333 AssertRCReturn(rc, NULL); 363 334 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; 395 341 396 342 for (;;) … … 403 349 switch (rc) 404 350 { 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; 414 353 break; 415 354 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; 423 357 break; 424 358 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; 432 361 break; 433 362 434 case ' M': /* --need-main */435 /* for backward compatibility, ignored */363 case 'f': 364 pszLogFlags = ValueUnion.psz; 436 365 break; 437 366 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; 445 369 break; 446 370 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; 454 376 break; 455 377 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 else480 {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 495 378 case VINF_GETOPT_NOT_OPTION: 496 RTMsgError(" %s: Unexpected command line argument", ValueUnion.psz);379 RTMsgError("Unexpected command line argument: '%s'", ValueUnion.psz); 497 380 return NULL; 498 381 … … 503 386 } 504 387 505 rc = config->i_complete(); 506 if (RT_FAILURE(rc)) 388 if (!pszConfig) 389 { 390 RTMsgError("No configuration file specified (--config file)!\n"); 507 391 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(); 569 424 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 } 574 427 return NULL; 575 428 } … … 693 546 * <DHCPServer> attributes 694 547 */ 695 const char *pszNetworkName; 696 if (pElmServer->getAttributeValue("networkName", &pszNetworkName)) 697 i_setNetwork(pszNetworkName); 698 else 548 if (!pElmServer->getAttributeValue("networkName", m_strNetwork)) 699 549 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"); 705 552 706 553 const char *pszTrunkType; … … 732 579 int rc = m_strLeasesFilename.assignNoThrow(getHome()); 733 580 if (RT_SUCCESS(rc)) 734 rc = RTPathAppendCxx(m_strLeasesFilename, getBaseName());581 rc = RTPathAppendCxx(m_strLeasesFilename, m_strNetwork); 735 582 if (RT_SUCCESS(rc)) 736 583 rc = m_strLeasesFilename.appendNoThrow("-Dhcpd.leases"); 737 584 if (RT_FAILURE(rc)) 738 585 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(); 739 588 } 740 589 … … 857 706 int rc = RTStrToUInt8Full(pszName, 10, &u8Opt); 858 707 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); 860 709 861 710 /* The opional 'encoding' attribute: */ 862 uint32_t u32Enc = 0; /* XXX: DhcpOptEncoding_Legacy */711 uint32_t u32Enc = 0; /* XXX: DhcpOptEncoding_Legacy */ 863 712 const char *pszEncoding; 864 713 if (pElmOption->getAttributeValue("encoding", &pszEncoding)) … … 866 715 rc = RTStrToUInt32Full(pszEncoding, 10, &u32Enc); 867 716 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); 869 718 870 719 switch (u32Enc) -
trunk/src/VBox/NetworkServices/Dhcpd/Config.h
r79621 r79761 45 45 46 46 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. */48 47 RTCString m_strLeasesFilename;/**< The lease DB filename. */ 49 48 … … 70 69 * vendor class and user class, including simple lists of these. */ 71 70 71 /** Set if we've initialized the log already (via command line). */ 72 static bool g_fInitializedLog; 73 72 74 private: 73 75 Config(); … … 77 79 static Config *i_createInstanceAndCallInit() RT_NOEXCEPT; 78 80 int i_logInit() RT_NOEXCEPT; 81 static int i_logInitWithFilename(const char *pszFilename) RT_NOEXCEPT; 79 82 int i_complete() RT_NOEXCEPT; 80 83 … … 92 95 93 96 const RTCString &getNetwork() const RT_NOEXCEPT { return m_strNetwork; } 94 const RTCString &getBaseName() const RT_NOEXCEPT { return m_strBaseName; }95 97 const RTCString &getLeasesFilename() const RT_NOEXCEPT { return m_strLeasesFilename; } 96 98 … … 124 126 static void i_getMacAddressAttribute(const xml::ElementNode *pElm, const char *pszAttrName, PRTMAC pMacAddr); 125 127 /** @} */ 126 127 void i_setNetwork(const RTCString &aStrNetwork);128 void i_sanitizeBaseName();129 128 }; 130 129 -
trunk/src/VBox/NetworkServices/Dhcpd/DhcpOptions.cpp
r79524 r79761 16 16 */ 17 17 18 19 /********************************************************************************************************************************* 20 * Header Files * 21 *********************************************************************************************************************************/ 18 22 #include "DhcpdInternal.h" 19 23 #include "DhcpOptions.h" 20 24 #include "DhcpMessage.h" 25 26 #include <iprt/cidr.h> 21 27 22 28 … … 102 108 103 109 110 int 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 104 142 int DhcpOption::parse1(uint8_t &aValue, const char *pcszValue) 105 143 { 106 144 int rc = RTStrToUInt8Full(RTStrStripL(pcszValue), 10, &aValue); 107 108 145 if (rc == VERR_TRAILING_SPACES) 109 146 rc = VINF_SUCCESS; … … 138 175 139 176 140 int DhcpOption::parseList(std::vector<RTNETADDRIPV4> &aList, const char *pcszValue) 141 { 142 std::vector<RTNETADDRIPV4> l; 143 int rc; 177 int DhcpOption::parse1(DhcpIpv4AddrAndMask &aValue, const char *pcszValue) 178 { 179 return RTCidrStrToIPv4(pcszValue, &aValue.Ipv4, &aValue.Mask); 180 } 181 182 183 template <typename a_Type> 184 static int DhcpOption::parseList(std::vector<a_Type> &aList, const char *pcszValue) 185 { 186 std::vector<a_Type> vecTmp; 144 187 145 188 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 152 218 return VERR_INVALID_PARAMETER; 153 219 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. */ 232 template <> 233 static 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) 155 245 { 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; 159 249 } 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 172 255 173 256 … … 208 291 209 292 210 DhcpOption *DhcpOption::parse(uint8_t aOptCode, int aEnc, const char *pcszValue) 211 { 293 DhcpOption *DhcpOption::parse(uint8_t aOptCode, int aEnc, const char *pcszValue, int *prc /*= NULL*/) 294 { 295 int rcIgn; 296 if (!prc) 297 prc = &rcIgn; 298 212 299 switch (aEnc) 213 300 { 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. 230 390 231 391 #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 232 402 default: 403 if (prc) 404 *prc = VERR_WRONG_TYPE; 233 405 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 33 33 class DhcpClientMessage; 34 34 35 typedef struct DhcpIpv4AddrAndMask 36 { 37 RTNETADDRIPV4 Ipv4; 38 RTNETADDRIPV4 Mask; 39 } DhcpIpv4AddrAndMask; 40 35 41 36 42 class DhcpOption 37 43 { 38 44 protected: 39 45 uint8_t m_OptCode; 40 bool m_fPresent;41 42 46 bool m_fPresent; 47 48 public: 43 49 explicit DhcpOption(uint8_t aOptCode) 44 : m_OptCode(aOptCode), m_fPresent(true) {} 50 : m_OptCode(aOptCode), m_fPresent(true) 51 {} 45 52 46 53 DhcpOption(uint8_t aOptCode, bool fPresent) 47 : m_OptCode(aOptCode), m_fPresent(fPresent) {} 54 : m_OptCode(aOptCode), m_fPresent(fPresent) 55 {} 48 56 49 57 virtual DhcpOption *clone() const = 0; 50 58 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 62 public: 63 static DhcpOption *parse(uint8_t aOptCode, int aEnc, const char *pcszValue, int *prc = NULL); 64 65 public: 57 66 uint8_t optcode() const RT_NOEXCEPT { return m_OptCode; } 58 67 bool present() const RT_NOEXCEPT { return m_fPresent; } 59 68 60 69 public: 61 70 int encode(octets_t &dst) const; 62 71 … … 64 73 int decode(const DhcpClientMessage &req); 65 74 66 75 protected: 67 76 virtual ssize_t encodeValue(octets_t &dst) const = 0; 68 77 virtual int decodeValue(const octets_t &src, size_t cb) = 0; 69 78 70 79 protected: 71 80 static const octets_t *findOption(const rawopts_t &aOptMap, uint8_t aOptCode); 72 81 73 protected: 74 /* 75 * Serialization 76 */ 82 protected: 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 77 91 static void append(octets_t &aDst, uint8_t aValue) 78 92 { … … 97 111 } 98 112 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 99 118 static void append(octets_t &aDst, const char *pszString, size_t cb) 100 119 { … … 113 132 } 114 133 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 119 145 static void extract(uint8_t &aValue, octets_t::const_iterator &pos) 120 146 { … … 145 171 } 146 172 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 147 179 #if 0 /** @todo fix me */ 148 180 static void extract(RTCString &aString, octets_t::const_iterator &pos, size_t cb) … … 153 185 #endif 154 186 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); 159 192 static int parse1(uint8_t &aValue, const char *pcszValue); 160 193 static int parse1(uint16_t &aValue, const char *pcszValue); 161 194 static int parse1(uint32_t &aValue, const char *pcszValue); 162 195 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); 165 199 166 200 static int parseHex(octets_t &aRawValue, const char *pcszValue); 201 202 /** @} */ 167 203 }; 168 204 … … 180 216 181 217 182 /* 218 /** 183 219 * Only for << OptEnd() syntactic sugar... 184 220 */ … … 194 230 195 231 196 /* 232 /** 197 233 * Option that has no value 198 234 */ 199 235 class OptNoValueBase 200 : public DhcpOption201 { 202 236 : public DhcpOption 237 { 238 public: 203 239 explicit OptNoValueBase(uint8_t aOptCode) 204 : DhcpOption(aOptCode, false) {} 240 : DhcpOption(aOptCode, false) 241 {} 205 242 206 243 OptNoValueBase(uint8_t aOptCode, bool fPresent) 207 : DhcpOption(aOptCode, fPresent) {} 244 : DhcpOption(aOptCode, fPresent) 245 {} 208 246 209 247 OptNoValueBase(uint8_t aOptCode, const DhcpClientMessage &req) 210 : DhcpOption(aOptCode, false)248 : DhcpOption(aOptCode, false) 211 249 { 212 250 decode(req); … … 218 256 } 219 257 220 258 protected: 221 259 virtual ssize_t encodeValue(octets_t &dst) const 222 260 { … … 225 263 } 226 264 227 265 public: 228 266 static bool isLengthValid(size_t cb) 229 267 { … … 245 283 template <uint8_t _OptCode> 246 284 class OptNoValue 247 : public OptNoValueBase248 { 249 285 : public OptNoValueBase 286 { 287 public: 250 288 static const uint8_t optcode = _OptCode; 251 289 252 290 OptNoValue() 253 : OptNoValueBase(optcode) {} 291 : OptNoValueBase(optcode) 292 {} 254 293 255 294 explicit OptNoValue(bool fPresent) /* there's no overloaded ctor with value */ 256 : OptNoValueBase(optcode, fPresent) {} 295 : OptNoValueBase(optcode, fPresent) 296 {} 257 297 258 298 explicit OptNoValue(const DhcpClientMessage &req) 259 : OptNoValueBase(optcode, req) {} 299 : OptNoValueBase(optcode, req) 300 {} 260 301 }; 261 302 … … 267 308 template <typename T> 268 309 class OptValueBase 269 : public DhcpOption270 { 271 310 : public DhcpOption 311 { 312 public: 272 313 typedef T value_t; 273 314 274 315 protected: 275 316 T m_Value; 276 317 277 318 explicit OptValueBase(uint8_t aOptCode) 278 : DhcpOption(aOptCode, false), m_Value() {} 319 : DhcpOption(aOptCode, false), m_Value() 320 {} 279 321 280 322 OptValueBase(uint8_t aOptCode, const T &aOptValue) 281 : DhcpOption(aOptCode), m_Value(aOptValue) {} 323 : DhcpOption(aOptCode), m_Value(aOptValue) 324 {} 282 325 283 326 OptValueBase(uint8_t aOptCode, const DhcpClientMessage &req) 284 : DhcpOption(aOptCode, false), m_Value()327 : DhcpOption(aOptCode, false), m_Value() 285 328 { 286 329 decode(req); 287 330 } 288 331 289 332 public: 290 333 virtual OptValueBase *clone() const 291 334 { … … 293 336 } 294 337 295 296 T &value() { return m_Value; }297 const T &value() const { return m_Value; }298 299 338 public: 339 T &value() { return m_Value; } 340 const T &value() const { return m_Value; } 341 342 protected: 300 343 virtual ssize_t encodeValue(octets_t &dst) const 301 344 { … … 304 347 } 305 348 306 349 public: 307 350 static bool isLengthValid(size_t cb) 308 351 { … … 325 368 template<uint8_t _OptCode, typename T> 326 369 class OptValue 327 : public OptValueBase<T>328 { 329 370 : public OptValueBase<T> 371 { 372 public: 330 373 using typename OptValueBase<T>::value_t; 331 374 332 375 public: 333 376 static const uint8_t optcode = _OptCode; 334 377 335 378 OptValue() 336 : OptValueBase<T>(optcode) {} 379 : OptValueBase<T>(optcode) 380 {} 337 381 338 382 explicit OptValue(const T &aOptValue) 339 : OptValueBase<T>(optcode, aOptValue) {} 383 : OptValueBase<T>(optcode, aOptValue) 384 {} 340 385 341 386 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) 345 391 { 346 392 typename OptValueBase<T>::value_t v; 347 393 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 /** 357 404 * Option that contains a string. 358 405 */ 359 406 class OptStringBase 360 : public DhcpOption361 { 362 407 : public DhcpOption 408 { 409 public: 363 410 typedef RTCString value_t; 364 411 365 412 protected: 366 413 RTCString m_String; 367 414 368 415 explicit OptStringBase(uint8_t aOptCode) 369 : DhcpOption(aOptCode, false), m_String() {} 416 : DhcpOption(aOptCode, false), m_String() 417 {} 370 418 371 419 OptStringBase(uint8_t aOptCode, const RTCString &aOptString) 372 : DhcpOption(aOptCode), m_String(aOptString) {} 420 : DhcpOption(aOptCode), m_String(aOptString) 421 {} 373 422 374 423 OptStringBase(uint8_t aOptCode, const DhcpClientMessage &req) 375 : DhcpOption(aOptCode, false), m_String()424 : DhcpOption(aOptCode, false), m_String() 376 425 { 377 426 decode(req); 378 427 } 379 428 380 429 public: 381 430 virtual OptStringBase *clone() const 382 431 { … … 384 433 } 385 434 386 387 RTCString &value() { return m_String; }388 const RTCString &value() const { return m_String; }389 390 435 public: 436 RTCString &value() { return m_String; } 437 const RTCString &value() const { return m_String; } 438 439 protected: 391 440 virtual ssize_t encodeValue(octets_t &dst) const 392 441 { … … 398 447 } 399 448 400 449 public: 401 450 static bool isLengthValid(size_t cb) 402 451 { … … 417 466 template<uint8_t _OptCode> 418 467 class OptString 419 : public OptStringBase420 { 421 468 : public OptStringBase 469 { 470 public: 422 471 static const uint8_t optcode = _OptCode; 423 472 424 473 OptString() 425 : OptStringBase(optcode) {} 474 : OptStringBase(optcode) 475 {} 426 476 427 477 explicit OptString(const RTCString &aOptString) 428 : OptStringBase(optcode, aOptString) {} 478 : OptStringBase(optcode, aOptString) 479 {} 429 480 430 481 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; 435 488 return new OptString(pcszValue); 436 489 } … … 444 497 template <typename T> 445 498 class OptListBase 446 : public DhcpOption447 { 448 499 : public DhcpOption 500 { 501 public: 449 502 typedef std::vector<T> value_t; 450 503 451 504 protected: 452 505 std::vector<T> m_List; 453 506 454 507 explicit OptListBase(uint8_t aOptCode) 455 : DhcpOption(aOptCode, false), m_List() {} 508 : DhcpOption(aOptCode, false), m_List() 509 {} 456 510 457 511 OptListBase(uint8_t aOptCode, const T &aOptSingle) 458 : DhcpOption(aOptCode), m_List(1, aOptSingle) {} 512 : DhcpOption(aOptCode), m_List(1, aOptSingle) 513 {} 459 514 460 515 OptListBase(uint8_t aOptCode, const std::vector<T> &aOptList) 461 : DhcpOption(aOptCode), m_List(aOptList) {} 516 : DhcpOption(aOptCode), m_List(aOptList) 517 {} 462 518 463 519 OptListBase(uint8_t aOptCode, const DhcpClientMessage &req) 464 : DhcpOption(aOptCode, false), m_List()520 : DhcpOption(aOptCode, false), m_List() 465 521 { 466 522 decode(req); 467 523 } 468 524 469 525 public: 470 526 virtual OptListBase *clone() const 471 527 { … … 473 529 } 474 530 475 476 std::vector<T> &value() { return m_List; }531 public: 532 std::vector<T> &value() { return m_List; } 477 533 const std::vector<T> &value() const { return m_List; } 478 534 479 535 protected: 480 536 virtual ssize_t encodeValue(octets_t &dst) const 481 537 { … … 495 551 } 496 552 497 553 public: 498 554 static bool isLengthValid(size_t cb) 499 555 { … … 522 578 template<uint8_t _OptCode, typename T> 523 579 class OptList 524 : public OptListBase<T>525 526 { 527 580 : public OptListBase<T> 581 582 { 583 public: 528 584 using typename OptListBase<T>::value_t; 529 585 530 586 public: 531 587 static const uint8_t optcode = _OptCode; 532 588 533 589 OptList() 534 : OptListBase<T>(optcode) {} 590 : OptListBase<T>(optcode) 591 {} 535 592 536 593 explicit OptList(const T &aOptSingle) 537 : OptListBase<T>(optcode, aOptSingle) {} 594 : OptListBase<T>(optcode, aOptSingle) 595 {} 538 596 539 597 explicit OptList(const std::vector<T> &aOptList) 540 : OptListBase<T>(optcode, aOptList) {} 598 : OptListBase<T>(optcode, aOptList) 599 {} 541 600 542 601 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) 546 606 { 547 607 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 624 template<uint8_t _OptCode, typename T> 625 class OptPairList 626 : public OptListBase<T> 627 628 { 629 public: 630 using typename OptListBase<T>::value_t; 631 632 public: 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; 552 671 } 553 672 }; … … 559 678 */ 560 679 class RawOption 561 : public DhcpOption562 { 563 680 : public DhcpOption 681 { 682 protected: 564 683 octets_t m_Data; 565 684 566 685 public: 567 686 explicit RawOption(uint8_t aOptCode) 568 : DhcpOption(aOptCode, false), m_Data() {} 687 : DhcpOption(aOptCode, false), m_Data() 688 {} 569 689 570 690 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 694 public: 574 695 virtual RawOption *clone() const 575 696 { … … 578 699 579 700 580 701 protected: 581 702 virtual ssize_t encodeValue(octets_t &dst) const 582 703 { … … 595 716 } 596 717 597 598 static RawOption *parse(uint8_t aOptCode, const char *pcszValue )718 public: 719 static RawOption *parse(uint8_t aOptCode, const char *pcszValue, int *prc) 599 720 { 600 721 octets_t data; 601 722 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; 605 727 } 606 728 }; … … 613 735 typedef OptValue<1, RTNETADDRIPV4> OptSubnetMask; 614 736 typedef OptValue<2, uint32_t> OptTimeOffset; 615 typedef OptList<3, RTNETADDRIPV4> OptRouter; 616 typedef OptList<4, RTNETADDRIPV4> OptTimeServer; 617 typedef OptList<6, RTNETADDRIPV4> OptDNS; 737 typedef OptList<3, RTNETADDRIPV4> OptRouters; 738 typedef OptList<4, RTNETADDRIPV4> OptTimeServers; 739 typedef OptList<5, RTNETADDRIPV4> OptNameServers; 740 typedef OptList<6, RTNETADDRIPV4> OptDNSes; 741 typedef OptList<7, RTNETADDRIPV4> OptLogServers; 742 typedef OptList<8, RTNETADDRIPV4> OptCookieServers; 743 typedef OptList<9, RTNETADDRIPV4> OptLPRServers; 744 typedef OptList<10, RTNETADDRIPV4> OptImpressServers; 745 typedef OptList<11, RTNETADDRIPV4> OptResourceLocationServers; 618 746 typedef OptString<12> OptHostName; 747 typedef OptValue<13, uint16_t> OptBootFileSize; 748 typedef OptString<14> OptMeritDumpFile; 619 749 typedef OptString<15> OptDomainName; 750 typedef OptValue<16, RTNETADDRIPV4> OptSwapServer; 620 751 typedef OptString<17> OptRootPath; 621 622 /* DHCP related options */ 752 typedef OptString<18> OptExtensionPath; 753 typedef OptValue<19, bool> OptIPForwarding; 754 typedef OptValue<20, bool> OptNonLocalSourceRouting; 755 typedef OptList<21, DhcpIpv4AddrAndMask> OptPolicyFilter; 756 typedef OptValue<22, uint16_t> OptMaxDatagramReassemblySize; 757 typedef OptValue<23, uint16_t> OptDefaultIPTTL; 758 typedef OptValue<24, uint32_t> OptDefaultPathMTUAgingTimeout; 759 typedef OptList<25, uint16_t> OptPathMTUPlateauTable; 760 typedef OptValue<26, uint16_t> OptInterfaceMTU; 761 typedef OptValue<27, bool> OptAllSubnetsAreLocal; 762 typedef OptValue<28, RTNETADDRIPV4> OptBroadcastAddress; 763 typedef OptValue<29, bool> OptPerformMaskDiscovery; 764 typedef OptValue<30, bool> OptMaskSupplier; 765 typedef OptValue<31, bool> OptPerformRouterDiscovery; 766 typedef OptValue<32, RTNETADDRIPV4> OptRouterSolicitationAddress; 767 typedef OptPairList<33, RTNETADDRIPV4> OptStaticRoute; 768 typedef OptValue<34, bool> OptTrailerEncapsulation; 769 typedef OptValue<35, uint32_t> OptARPCacheTimeout; 770 typedef OptValue<36, bool> OptEthernetEncapsulation; 771 typedef OptValue<37, uint8_t> OptTCPDefaultTTL; 772 typedef OptValue<38, uint32_t> OptTCPKeepaliveInterval; 773 typedef OptValue<39, bool> OptTCPKeepaliveGarbage; 774 typedef OptString<40> OptNISDomain; 775 typedef OptList<41, RTNETADDRIPV4> OptNISServers; 776 typedef OptList<42, RTNETADDRIPV4> OptNTPServers; 777 /* DHCP related options: */ 623 778 typedef OptList<43, uint8_t> OptVendorSpecificInfo; 779 typedef OptList<44, RTNETADDRIPV4> OptNetBIOSNameServers; 780 typedef OptList<45, RTNETADDRIPV4> OptNetBIOSDatagramServers; 781 typedef OptValue<46, uint8_t> OptNetBIOSNodeType; 782 typedef OptList<47, uint8_t> OptNetBIOSScope; /**< uint8_t or string? */ 783 typedef OptList<48, RTNETADDRIPV4> OptXWindowsFontServers; 784 typedef OptList<49, RTNETADDRIPV4> OptXWindowsDisplayManager; 624 785 typedef OptValue<50, RTNETADDRIPV4> OptRequestedAddress; 625 786 typedef OptValue<51, uint32_t> OptLeaseTime; … … 634 795 typedef OptList<60, uint8_t> OptVendorClassId; 635 796 typedef OptList<61, uint8_t> OptClientId; 636 typedef OptString<66> OptTFTPServer; /* when overloaded */ 637 typedef OptString<67> OptBootFileName; /* when overloaded */ 797 typedef OptString<62> OptNetWareIPDomainName; /**< RFC2242 */ 798 typedef OptList<63, uint8_t> OptNetWareIPInformation; /**< complicated, so just byte list for now. RFC2242 */ 799 typedef OptString<64> OptNISPlusDomain; 800 typedef OptString<65> OptNISPlusServers; 801 typedef OptString<66> OptTFTPServer; /**< when overloaded */ 802 typedef OptString<67> OptBootFileName; /**< when overloaded */ 803 typedef OptList<68, RTNETADDRIPV4> OptMobileIPHomeAgents; 804 typedef OptList<69, RTNETADDRIPV4> OptSMTPServers; 805 typedef OptList<70, RTNETADDRIPV4> OptPOP3Servers; 806 typedef OptList<71, RTNETADDRIPV4> OptNNTPServers; 807 typedef OptList<72, RTNETADDRIPV4> OptWWWServers; 808 typedef OptList<73, RTNETADDRIPV4> OptFingerServers; 809 typedef OptList<74, RTNETADDRIPV4> OptIRCServers; 810 typedef OptList<75, RTNETADDRIPV4> OptStreetTalkServers; 811 typedef OptList<76, RTNETADDRIPV4> OptSTDAServers; 638 812 typedef OptList<77, uint8_t> OptUserClassId; 639 typedef OptNoValue<80> OptRapidCommit; /* RFC4039 */ 813 typedef OptList<78, uint8_t> OptSLPDirectoryAgent; /**< complicated, so just byte list for now. RFC2610 */ 814 typedef OptList<79, uint8_t> OptSLPServiceScope; /**< complicated, so just byte list for now. RFC2610 */ 815 typedef OptNoValue<80> OptRapidCommit; /**< RFC4039 */ 640 816 /** @} */ 641 817 -
trunk/src/VBox/NetworkServices/Dhcpd/DhcpdInternal.h
r79622 r79761 22 22 #endif 23 23 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 25 29 #include <iprt/stdint.h> 26 30 #include <iprt/string.h> -
trunk/src/VBox/NetworkServices/Dhcpd/VBoxNetDhcpd.cpp
r79622 r79761 620 620 * Parse the command line into a configuration object. 621 621 */ 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); 641 623 if (m_Config == NULL) 642 624 return VERR_GENERAL_FAILURE;
Note:
See TracChangeset
for help on using the changeset viewer.